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:
parent
538b38202e
commit
1c583cde13
5 changed files with 168 additions and 69 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
---------
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Design
|
|||
guide.hex.trans
|
||||
guide.impl.c.format
|
||||
keyword-arguments
|
||||
nailboard
|
||||
range
|
||||
ring
|
||||
sig
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue