1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-26 08:41:47 -07:00

Naive nailboard implementation (complete).

Copied from Perforce
 Change: 184395
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-02-19 18:25:40 +00:00
parent 538b38202e
commit 1c583cde13
5 changed files with 168 additions and 69 deletions

View file

@ -15,31 +15,61 @@ SRCID(nailboard, "$Id$");
Bool NailboardCheck(Nailboard board)
{
Index i;
CHECKS(Nailboard, board);
CHECKU(Arena, board->arena);
CHECKL(RangeCheck(&board->range));
/* nails is >= number of set bits in mark, but we can't check this */
/* We know that shift corresponds to pool->align. */
CHECKL(BoolCheck(board->newNails));
CHECKL(board->levels <= NAILBOARD_MAX_LEVELS);
CHECKL(0 < board->alignShift);
CHECKL(0 < board->levelShift);
for (i = 0; i < board->levels; ++i) {
/* weak check for BTs @@@@ */
CHECKL(board->level[i] != NULL);
}
/* distinctNails must be the same as the number of set bits in
* level[0].mark, but we don't want to check this as it's O(n).
*/
CHECKL(board->distinctNails <= board->nails);
/* weak check for BTs @@@@ */
CHECKL(board->mark != NULL);
CHECKL(BoolCheck(board->newNails));
return TRUE;
}
static Size nailboardSize(Count bits, Count levels, Shift shift)
{
Index i;
Size size;
AVER(bits >> ((levels - 1) * shift) != 0);
AVER(bits >> (levels * shift) == 0);
size = 0;
for (i = 0; i < levels; ++i) {
size += BTSize(bits >> (i * shift));
}
return size;
}
Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment,
Addr base, Addr limit)
{
void *p;
Nailboard board;
Count bits;
Count bits, levels;
Index i;
Size size;
Res res;
Shift levelShift = MPS_WORD_SHIFT;
AVER(boardReturn != NULL);
AVERT(Arena, arena);
AVERT(Align, alignment);
AVER(base < limit);
AVER(AddrIsAligned(base, alignment));
AVER(AddrIsAligned(limit, alignment));
res = ControlAlloc(&p, arena, sizeof(NailboardStruct), FALSE);
bits = AddrOffset(base, limit) / alignment;
levels = SizeRoundUp(SizeLog2(bits), levelShift) / levelShift;
AVER(levels <= NAILBOARD_MAX_LEVELS);
size = sizeof(NailboardStruct) + sizeof(BT*) * (levels - 1);
res = ControlAlloc(&p, arena, size, FALSE);
if(res != ResOK)
goto failAllocNailboard;
board = p;
@ -47,20 +77,31 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment,
board->nails = (Count)0;
board->distinctNails = (Count)0;
board->newNails = FALSE;
board->markShift = SizeLog2((Size)alignment);
board->levels = levels;
board->alignShift = SizeLog2(alignment);
board->levelShift = levelShift;
RangeInit(&board->range, base, limit);
bits = RangeSize(&board->range) >> board->markShift;
res = ControlAlloc(&p, arena, BTSize(bits), FALSE);
res = ControlAlloc(&p, arena, nailboardSize(bits, levels, levelShift), FALSE);
if(res != ResOK)
goto failMarkTable;
board->mark = p;
BTResRange(board->mark, 0, bits);
goto failAllocNails;
AVER(bits == RangeSize(&board->range) >> board->alignShift);
for (i = 0; i < levels; ++i) {
AVER(bits > 0);
board->level[i] = p;
BTResRange(board->level[i], 0, bits);
p = AddrAdd(p, BTSize(bits));
bits >>= levelShift;
}
AVER(bits == 0);
board->sig = NailboardSig;
AVERT(Nailboard, board);
*boardReturn = board;
return ResOK;
failMarkTable:
failAllocNails:
ControlFree(arena, board, sizeof(NailboardStruct));
failAllocNailboard:
return res;
@ -72,17 +113,18 @@ void NailboardDestroy(Nailboard board)
Count bits;
AVERT(Nailboard, board);
arena = board->arena;
bits = RangeSize(&board->range) >> board->markShift;
ControlFree(board->arena, board->mark, BTSize(bits));
arena = board->arena;
bits = RangeSize(&board->range) >> board->alignShift;
ControlFree(arena, board->level[0],
nailboardSize(bits, board->levels, board->levelShift));
board->sig = SigInvalid;
ControlFree(arena, board, sizeof(NailboardStruct));
}
Align NailboardAlignment(Nailboard board)
{
return (Align)1 << board->markShift;
return (Align)1 << board->alignShift;
}
void NailboardClearNewNails(Nailboard board)
@ -95,77 +137,102 @@ Bool NailboardNewNails(Nailboard board)
return board->newNails;
}
/* nailboardIndex -- return the index of the nail corresponding to addr */
static Index nailboardIndex(Nailboard board, Addr addr)
/* nailboardIndex -- return the index of the nail corresponding to
* addr in the given level.
*/
static Index nailboardIndex(Nailboard board, Index level, Addr addr)
{
return AddrOffset(RangeBase(&board->range), addr) >> board->markShift;
AVERT(Nailboard, board);
AVER(level < board->levels);
AVER(RangeBase(&board->range) <= addr);
AVER(addr <= RangeLimit(&board->range));
return AddrOffset(RangeBase(&board->range), addr)
>> (board->alignShift + level * board->levelShift);
}
/* nailboardIndexRange -- update *ibaseReturn and *ilimitReturn to be
* the indexes of the nail corresponding to base and limit
* respectively.
* respectively, in the given level.
*/
static void nailboardIndexRange(Index *ibaseReturn, Index *ilimitReturn,
Nailboard board, Addr base, Addr limit)
Nailboard board, Index level,
Addr base, Addr limit)
{
AVERT(Nailboard, board);
AVER(RangeBase(&board->range) <= base);
AVER(base <= limit);
AVER(limit <= RangeLimit(&board->range));
AVER(base < limit);
*ibaseReturn = nailboardIndex(board, base);
*ilimitReturn = nailboardIndex(board, limit);
*ibaseReturn = nailboardIndex(board, level, base);
*ilimitReturn = nailboardIndex(board, level, AddrSub(limit, 1)) + 1;
}
Bool NailboardGet(Nailboard board, Addr addr)
{
AVERT(Nailboard, board);
AVER(RangeContains(&board->range, addr));
return BTGet(board->mark, nailboardIndex(board, addr));
return BTGet(board->level[0], nailboardIndex(board, 0, addr));
}
Bool NailboardSet(Nailboard board, Addr addr)
{
Index i;
Index i, j;
AVERT(Nailboard, board);
AVER(RangeContains(&board->range, addr));
++ board->nails;
i = nailboardIndex(board, addr);
if (!BTGet(board->mark, i)) {
BTSet(board->mark, i);
board->newNails = TRUE;
++ board->distinctNails;
return FALSE;
j = nailboardIndex(board, 0, addr);
if (BTGet(board->level[0], j)) {
return TRUE;
}
return TRUE;
BTSet(board->level[0], j);
board->newNails = TRUE;
++ board->distinctNails;
for (i = 1; i < board->levels; ++i) {
j = nailboardIndex(board, i, addr);
if (BTGet(board->level[i], j)) {
break;
}
BTSet(board->level[i], j);
}
return FALSE;
}
void NailboardSetRange(Nailboard board, Addr base, Addr limit)
{
Index ibase, ilimit;
nailboardIndexRange(&ibase, &ilimit, board, base, limit);
AVER(BTIsResRange(board->mark, ibase, ilimit));
BTSetRange(board->mark, ibase, ilimit);
Index i, ibase, ilimit;
nailboardIndexRange(&ibase, &ilimit, board, 0, base, limit);
AVER(BTIsResRange(board->level[0], ibase, ilimit));
BTSetRange(board->level[0], ibase, ilimit);
board->nails += ilimit - ibase;
board->distinctNails += ilimit - ibase;
for (i = 1; i < board->levels; ++i) {
nailboardIndexRange(&ibase, &ilimit, board, i, base, limit);
BTSetRange(board->level[i], ibase, ilimit);
}
}
Bool NailboardIsSetRange(Nailboard board, Addr base, Addr limit)
{
Index ibase, ilimit;
nailboardIndexRange(&ibase, &ilimit, board, base, limit);
AVERT(Nailboard, board);
nailboardIndexRange(&ibase, &ilimit, board, 0, base, limit);
return board->distinctNails >= ilimit - ibase
&& BTIsSetRange(board->mark, ibase, ilimit);
&& BTIsSetRange(board->level[0], ibase, ilimit);
}
Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit)
{
Index ibase, ilimit;
nailboardIndexRange(&ibase, &ilimit, board, base, limit);
return BTIsResRange(board->mark, ibase, ilimit);
Index i;
AVERT(Nailboard, board);
i = board->levels;
while (i > 0) {
Index ibase, ilimit;
i -= 1;
nailboardIndexRange(&ibase, &ilimit, board, i, base, limit);
if (BTIsResRange(board->level[i], ibase, ilimit))
return TRUE;
}
return FALSE;
}

View file

@ -12,17 +12,21 @@
#include "mpmtypes.h"
#include "range.h"
#define NAILBOARD_MAX_LEVELS ((MPS_WORD_WIDTH + MPS_WORD_SHIFT - 1) / MPS_WORD_SHIFT)
typedef struct NailboardStruct *Nailboard;
typedef struct NailboardStruct {
Sig sig;
Arena arena;
RangeStruct range; /* range covered by nailboard */
Shift markShift; /* to convert offset into bit index for mark */
BT mark; /* mark table used to record ambiguous fixes */
Count nails; /* no. of ambigFixes, not necessarily distinct */
Count distinctNails; /* number of distinct ambigFixes */
Bool newNails; /* set to TRUE if a new nail is set */
RangeStruct range; /* range of addresses covered by nailboard */
Count levels; /* number of levels */
Count nails; /* number of calls to NailboardSet */
Count distinctNails; /* number of nails in the board */
Bool newNails; /* set to TRUE if a new nail is set */
Shift alignShift; /* shift due to address alignment */
Shift levelShift; /* additional shift for each level */
BT level[1]; /* bit tables for each level */
} NailboardStruct;
#define NailboardSig ((Sig)0x5194A17B) /* SIGnature NAILBoard */

View file

@ -191,21 +191,21 @@ References
Document History
----------------
- 2002-05-23 RB_ Created empty catalogue based on P4DTI design document catalogue.
- 2002-06-07 RB_ Added a bunch of design documents referenced by the source code.
- 2002-06-21 NB_ Remove P4DTI reference, which doesn't fit here. Maybe one day we'll have a corporate design document procedure.
- 2002-06-24 RB_ Added fix, object-debug, thread-manager, and thread-safety.
- 2007-02-08 RHSK Added message-gc and shield.
- 2007-06-12 RHSK Added cstyle.
- 2007-06-28 RHSK Added diag.
- 2008-12-04 RHSK Added tests.
- 2008-12-10 RHSK Correct description of message-gc: gc begin or end.
- 2012-09-14 RB_ Added link to critical-path
- 2013-05-10 RB_ Fixed link to sig and added guide.hex.trans
- 2013-05-22 GDR_ Add link to keyword-arguments.
- 2013-05-25 RB_ Replacing "cstyle" with reworked "guide.impl.c.format".
- 2013-06-07 RB_ Converting to reST_. Linking to [RB_2002-06-18]_.
- 2014-01-17 GDR_ Add abq, nailboard, range.
- 2002-05-23 RB_ Created empty catalogue based on P4DTI design document catalogue.
- 2002-06-07 RB_ Added a bunch of design documents referenced by the source code.
- 2002-06-21 NB_ Remove P4DTI reference, which doesn't fit here. Maybe one day we'll have a corporate design document procedure.
- 2002-06-24 RB_ Added fix, object-debug, thread-manager, and thread-safety.
- 2007-02-08 RHSK Added message-gc and shield.
- 2007-06-12 RHSK Added cstyle.
- 2007-06-28 RHSK Added diag.
- 2008-12-04 RHSK Added tests.
- 2008-12-10 RHSK Correct description of message-gc: gc begin or end.
- 2012-09-14 RB_ Added link to critical-path
- 2013-05-10 RB_ Fixed link to sig and added guide.hex.trans
- 2013-05-22 GDR_ Add link to keyword-arguments.
- 2013-05-25 RB_ Replacing "cstyle" with reworked "guide.impl.c.format".
- 2013-06-07 RB_ Converting to reST_. Linking to [RB_2002-06-18]_.
- 2014-01-17 GDR_ Add abq, nailboard, range.
.. _RB: http://www.ravenbrook.com/consultants/rb
.. _NB: http://www.ravenbrook.com/consultants/nb

View file

@ -52,6 +52,33 @@ logarithmic in the size of the range. (Because scanning overhead must
be proportional to the number of objects, not to their size.)
Overview
--------
We maintain a (level 0) bit table with one bit for each (aligned)
address in the range. In addition, we maintain a (level 1) bit table
with one bit for each ``scale`` bits in the level 0 bit table (this
bit is set if any bit in the corresponding word in the level 0 table
is set). And so on until we reach the level *k* bit table which is
just one word long.
The size of the level *i* bit table is the ceiling of
(``limit`` ``base``) / (``align`` × ``scale``\ :superscript:`i`\ )
where ``base`` and ``limit`` are the bounds of the address range being
represented in the nailboard, ``align`` is the pool alignment.
The address *a* may be looked up in the level *i* bit table at the bit
(*a* ``base``) / (``align`` × ``scale``\ :superscript:`i`\ )
and since ``align`` and ``scale`` are powers of 2, that's
(*a* ``base``) >> (log\ :subscript:`2`\ ``align`` + *i* log\ :subscript:`2`\ ``scale``)
Interface
---------

View file

@ -14,6 +14,7 @@ Design
guide.hex.trans
guide.impl.c.format
keyword-arguments
nailboard
range
ring
sig