mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-28 01:00:52 -07:00
Merge branch/2018-07-04/mvff-perf into the master sources.
Copied from Perforce Change: 194439
This commit is contained in:
commit
2b469ef694
10 changed files with 313 additions and 245 deletions
|
|
@ -692,12 +692,15 @@ Res ControlAlloc(void **baseReturn, Arena arena, size_t size)
|
|||
|
||||
void ControlFree(Arena arena, void* base, size_t size)
|
||||
{
|
||||
Pool pool;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
AVER(base != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(arena->poolReady);
|
||||
|
||||
PoolFree(ArenaControlPool(arena), (Addr)base, (Size)size);
|
||||
pool = ArenaControlPool(arena);
|
||||
PoolFree(pool, (Addr)base, (Size)size);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -875,8 +878,9 @@ static void arenaExcludePage(Arena arena, Range pageRange)
|
|||
{
|
||||
RangeStruct oldRange;
|
||||
Res res;
|
||||
Land land = ArenaFreeLand(arena);
|
||||
|
||||
res = LandDelete(&oldRange, ArenaFreeLand(arena), pageRange);
|
||||
res = LandDelete(&oldRange, land, pageRange);
|
||||
AVER(res == ResOK); /* we just gave memory to the Land */
|
||||
}
|
||||
|
||||
|
|
@ -896,12 +900,14 @@ static Res arenaFreeLandInsertExtend(Range rangeReturn, Arena arena,
|
|||
Range range)
|
||||
{
|
||||
Res res;
|
||||
Land land;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
AVERT(Range, range);
|
||||
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), range);
|
||||
land = ArenaFreeLand(arena);
|
||||
res = LandInsert(rangeReturn, land, range);
|
||||
|
||||
if (res == ResLIMIT) { /* CBS block pool ran out of blocks */
|
||||
RangeStruct pageRange;
|
||||
|
|
@ -910,7 +916,7 @@ static Res arenaFreeLandInsertExtend(Range rangeReturn, Arena arena,
|
|||
return res;
|
||||
/* .insert.exclude: Must insert before exclude so that we can
|
||||
bootstrap when the zoned CBS is empty. */
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), range);
|
||||
res = LandInsert(rangeReturn, land, range);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBS block pool */
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
}
|
||||
|
|
@ -941,6 +947,7 @@ static void arenaFreeLandInsertSteal(Range rangeReturn, Arena arena,
|
|||
res = arenaFreeLandInsertExtend(rangeReturn, arena, rangeIO);
|
||||
|
||||
if (res != ResOK) {
|
||||
Land land;
|
||||
Addr pageBase, pageLimit;
|
||||
Tract tract;
|
||||
AVER(ResIsAllocFailure(res));
|
||||
|
|
@ -960,7 +967,8 @@ static void arenaFreeLandInsertSteal(Range rangeReturn, Arena arena,
|
|||
MFSExtend(ArenaCBSBlockPool(arena), pageBase, pageLimit);
|
||||
|
||||
/* Try again. */
|
||||
res = LandInsert(rangeReturn, ArenaFreeLand(arena), rangeIO);
|
||||
land = ArenaFreeLand(arena);
|
||||
res = LandInsert(rangeReturn, land, rangeIO);
|
||||
AVER(res == ResOK); /* we just gave memory to the CBS block pool */
|
||||
}
|
||||
|
||||
|
|
@ -1016,9 +1024,11 @@ void ArenaFreeLandDelete(Arena arena, Addr base, Addr limit)
|
|||
{
|
||||
RangeStruct range, oldRange;
|
||||
Res res;
|
||||
Land land;
|
||||
|
||||
RangeInit(&range, base, limit);
|
||||
res = LandDelete(&oldRange, ArenaFreeLand(arena), &range);
|
||||
land = ArenaFreeLand(arena);
|
||||
res = LandDelete(&oldRange, land, &range);
|
||||
|
||||
/* Shouldn't be any other kind of failure because we were only deleting
|
||||
a non-coalesced block. See .chunk.no-coalesce and
|
||||
|
|
@ -1046,6 +1056,7 @@ Res ArenaFreeLandAlloc(Tract *tractReturn, Arena arena, ZoneSet zones,
|
|||
Index baseIndex;
|
||||
Count pages;
|
||||
Res res;
|
||||
Land land;
|
||||
|
||||
AVER(tractReturn != NULL);
|
||||
AVERT(Arena, arena);
|
||||
|
|
@ -1060,8 +1071,8 @@ Res ArenaFreeLandAlloc(Tract *tractReturn, Arena arena, ZoneSet zones,
|
|||
|
||||
/* Step 1. Find a range of address space. */
|
||||
|
||||
res = LandFindInZones(&found, &range, &oldRange, ArenaFreeLand(arena),
|
||||
size, zones, high);
|
||||
land = ArenaFreeLand(arena);
|
||||
res = LandFindInZones(&found, &range, &oldRange, land, size, zones, high);
|
||||
|
||||
if (res == ResLIMIT) { /* found block, but couldn't store info */
|
||||
RangeStruct pageRange;
|
||||
|
|
@ -1069,8 +1080,7 @@ Res ArenaFreeLandAlloc(Tract *tractReturn, Arena arena, ZoneSet zones,
|
|||
if (res != ResOK) /* disastrously short on memory */
|
||||
return res;
|
||||
arenaExcludePage(arena, &pageRange);
|
||||
res = LandFindInZones(&found, &range, &oldRange, ArenaFreeLand(arena),
|
||||
size, zones, high);
|
||||
res = LandFindInZones(&found, &range, &oldRange, land, size, zones, high);
|
||||
AVER(res != ResLIMIT);
|
||||
}
|
||||
|
||||
|
|
|
|||
108
mps/code/cbs.c
108
mps/code/cbs.c
|
|
@ -10,6 +10,11 @@
|
|||
* collections of memory blocks.
|
||||
*
|
||||
* .sources: <design/cbs/>.
|
||||
*
|
||||
* .critical: In manual-allocation-bound programs using MVFF, many of
|
||||
* these functions are on the critical paths via mps_alloc (and then
|
||||
* PoolAlloc, MVFFAlloc, failoverFind*, cbsFind*) and mps_free (and
|
||||
* then MVFFFree, failoverInsert, cbsInsert).
|
||||
*/
|
||||
|
||||
#include "cbs.h"
|
||||
|
|
@ -121,11 +126,11 @@ static Bool cbsTestNode(SplayTree splay, Tree tree, void *closure)
|
|||
CBSBlock block;
|
||||
Size *sizeP = closure;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVERT(Tree, tree);
|
||||
AVER(sizeP != NULL);
|
||||
AVER(*sizeP > 0);
|
||||
AVER(IsA(CBSFast, cbsOfSplay(splay)));
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVERT_CRITICAL(Tree, tree);
|
||||
AVER_CRITICAL(sizeP != NULL);
|
||||
AVER_CRITICAL(*sizeP > 0);
|
||||
AVER_CRITICAL(IsA(CBSFast, cbsOfSplay(splay)));
|
||||
|
||||
block = cbsBlockOfTree(tree);
|
||||
|
||||
|
|
@ -138,11 +143,11 @@ static Bool cbsTestTree(SplayTree splay, Tree tree,
|
|||
CBSFastBlock block;
|
||||
Size *sizeP = closure;
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVERT(Tree, tree);
|
||||
AVER(sizeP != NULL);
|
||||
AVER(*sizeP > 0);
|
||||
AVER(IsA(CBSFast, cbsOfSplay(splay)));
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVERT_CRITICAL(Tree, tree);
|
||||
AVER_CRITICAL(sizeP != NULL);
|
||||
AVER_CRITICAL(*sizeP > 0);
|
||||
AVER_CRITICAL(IsA(CBSFast, cbsOfSplay(splay)));
|
||||
|
||||
block = cbsFastBlockOfTree(tree);
|
||||
|
||||
|
|
@ -313,7 +318,7 @@ static void cbsFinish(Inst inst)
|
|||
|
||||
static Size cbsSize(Land land)
|
||||
{
|
||||
CBS cbs = MustBeA(CBS, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBS, land);
|
||||
return cbs->size;
|
||||
}
|
||||
|
||||
|
|
@ -425,12 +430,12 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
|
|||
{
|
||||
Bool b;
|
||||
|
||||
AVERT(CBS, cbs);
|
||||
AVERT(CBSBlock, block);
|
||||
AVERT_CRITICAL(CBS, cbs);
|
||||
AVERT_CRITICAL(CBSBlock, block);
|
||||
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
b = SplayTreeInsert(cbsSplay(cbs), cbsBlockTree(block));
|
||||
AVER(b);
|
||||
AVER_CRITICAL(b);
|
||||
STATISTIC(++cbs->treeSize);
|
||||
cbs->size += CBSBlockSize(block);
|
||||
}
|
||||
|
|
@ -442,14 +447,11 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block)
|
|||
*
|
||||
* .insert.alloc: Will only allocate a block if the range does not
|
||||
* abut an existing range.
|
||||
*
|
||||
* .insert.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
static Res cbsInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
CBS cbs = MustBeA(CBS, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBS, land);
|
||||
Bool b;
|
||||
Res res;
|
||||
Addr base, limit, newBase, newLimit;
|
||||
|
|
@ -486,7 +488,7 @@ static Res cbsInsert(Range rangeReturn, Land land, Range range)
|
|||
leftMerge = FALSE;
|
||||
} else {
|
||||
leftCBS = cbsBlockOfTree(leftSplay);
|
||||
AVER(leftCBS->limit <= base);
|
||||
AVER_CRITICAL(leftCBS->limit <= base);
|
||||
leftMerge = leftCBS->limit == base;
|
||||
}
|
||||
|
||||
|
|
@ -876,15 +878,15 @@ static void cbsFindDeleteRange(Range rangeReturn, Range oldRangeReturn,
|
|||
static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs = MustBeA(CBS, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBS, land);
|
||||
Bool found;
|
||||
Tree tree;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVER_CRITICAL(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindFirst(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
|
|
@ -893,9 +895,9 @@ static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
|
|||
CBSBlock block;
|
||||
RangeStruct range;
|
||||
block = cbsBlockOfTree(tree);
|
||||
AVER(CBSBlockSize(block) >= size);
|
||||
AVER_CRITICAL(CBSBlockSize(block) >= size);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= size);
|
||||
AVER_CRITICAL(RangeSize(&range) >= size);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
size, findDelete);
|
||||
}
|
||||
|
|
@ -952,15 +954,15 @@ static Bool cbsTestTreeInZones(SplayTree splay, Tree tree,
|
|||
static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs = MustBeA(CBSFast, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBSFast, land);
|
||||
Bool found;
|
||||
Tree tree;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVER_CRITICAL(SizeIsAligned(size, LandAlignment(land)));
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindLast(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
|
|
@ -969,9 +971,9 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
CBSBlock block;
|
||||
RangeStruct range;
|
||||
block = cbsBlockOfTree(tree);
|
||||
AVER(CBSBlockSize(block) >= size);
|
||||
AVER_CRITICAL(CBSBlockSize(block) >= size);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= size);
|
||||
AVER_CRITICAL(RangeSize(&range) >= size);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
size, findDelete);
|
||||
}
|
||||
|
|
@ -985,13 +987,13 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
|
|||
static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
|
||||
Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
CBS cbs = MustBeA(CBSFast, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBSFast, land);
|
||||
Bool found = FALSE;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVER(size > 0);
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
if (!SplayTreeIsEmpty(cbsSplay(cbs))) {
|
||||
RangeStruct range;
|
||||
|
|
@ -1004,11 +1006,11 @@ static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
|
|||
METER_ACC(cbs->treeSearch, cbs->treeSize);
|
||||
found = SplayFindFirst(&tree, cbsSplay(cbs), &cbsTestNode,
|
||||
&cbsTestTree, &maxSize);
|
||||
AVER(found); /* maxSize is exact, so we will find it. */
|
||||
AVER_CRITICAL(found); /* maxSize is exact, so we will find it. */
|
||||
block = cbsBlockOfTree(tree);
|
||||
AVER(CBSBlockSize(block) >= maxSize);
|
||||
AVER_CRITICAL(CBSBlockSize(block) >= maxSize);
|
||||
RangeInit(&range, CBSBlockBase(block), CBSBlockLimit(block));
|
||||
AVER(RangeSize(&range) >= maxSize);
|
||||
AVER_CRITICAL(RangeSize(&range) >= maxSize);
|
||||
cbsFindDeleteRange(rangeReturn, oldRangeReturn, land, &range,
|
||||
size, findDelete);
|
||||
}
|
||||
|
|
@ -1022,7 +1024,7 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
Range oldRangeReturn, Land land, Size size,
|
||||
ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
CBS cbs = MustBeA(CBSZoned, land);
|
||||
CBS cbs = MustBeA_CRITICAL(CBSZoned, land);
|
||||
CBSBlock block;
|
||||
Tree tree;
|
||||
cbsTestNodeInZonesClosureStruct closure;
|
||||
|
|
@ -1031,11 +1033,11 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
SplayFindFunction splayFind;
|
||||
RangeStruct rangeStruct, oldRangeStruct;
|
||||
|
||||
AVER(foundReturn != NULL);
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
/* AVERT(ZoneSet, zoneSet); */
|
||||
AVERT(Bool, high);
|
||||
AVER_CRITICAL(foundReturn != NULL);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
/* AVERT_CRITICAL(ZoneSet, zoneSet); */
|
||||
AVERT_CRITICAL(Bool, high);
|
||||
|
||||
landFind = high ? cbsFindLast : cbsFindFirst;
|
||||
splayFind = high ? SplayFindLast : SplayFindFirst;
|
||||
|
|
@ -1064,10 +1066,10 @@ static Res cbsFindInZones(Bool *foundReturn, Range rangeReturn,
|
|||
|
||||
block = cbsBlockOfTree(tree);
|
||||
|
||||
AVER(CBSBlockBase(block) <= closure.base);
|
||||
AVER(AddrOffset(closure.base, closure.limit) >= size);
|
||||
AVER(ZoneSetSub(ZoneSetOfRange(LandArena(land), closure.base, closure.limit), zoneSet));
|
||||
AVER(closure.limit <= CBSBlockLimit(block));
|
||||
AVER_CRITICAL(CBSBlockBase(block) <= closure.base);
|
||||
AVER_CRITICAL(AddrOffset(closure.base, closure.limit) >= size);
|
||||
AVER_CRITICAL(ZoneSetSub(ZoneSetOfRange(LandArena(land), closure.base, closure.limit), zoneSet));
|
||||
AVER_CRITICAL(closure.limit <= CBSBlockLimit(block));
|
||||
|
||||
if (!high)
|
||||
RangeInit(&rangeStruct, closure.base, AddrAdd(closure.base, size));
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@
|
|||
EVENT(X, SegFree , 0x0014, TRUE, Seg) \
|
||||
EVENT(X, PoolInit , 0x0015, TRUE, Pool) \
|
||||
EVENT(X, PoolFinish , 0x0016, TRUE, Pool) \
|
||||
EVENT(X, PoolAlloc , 0x0017, TRUE, Object) \
|
||||
EVENT(X, PoolFree , 0x0018, TRUE, Object) \
|
||||
EVENT(X, PoolAlloc , 0x0017, FALSE, Object) \
|
||||
EVENT(X, PoolFree , 0x0018, FALSE, Object) \
|
||||
EVENT(X, LandInit , 0x0019, TRUE, Pool) \
|
||||
EVENT(X, Intern , 0x001a, TRUE, User) \
|
||||
EVENT(X, Label , 0x001b, TRUE, User) \
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
* Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: <design/failover/>
|
||||
*
|
||||
* .critical: In manual-allocation-bound programs using MVFF, many of
|
||||
* these functions are on the critical paths via mps_alloc (and then
|
||||
* PoolAlloc, MVFFAlloc, failoverFind*) and mps_free (and then
|
||||
* MVFFFree, failoverInsert).
|
||||
*/
|
||||
|
||||
#include "failover.h"
|
||||
|
|
@ -63,18 +68,18 @@ static void failoverFinish(Inst inst)
|
|||
|
||||
static Size failoverSize(Land land)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
return LandSize(fo->primary) + LandSize(fo->secondary);
|
||||
}
|
||||
|
||||
|
||||
static Res failoverInsert(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
Res res;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(Range, range);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVERT_CRITICAL(Range, range);
|
||||
|
||||
/* Provide more opportunities for coalescence. See
|
||||
* <design/failover/#impl.assume.flush>.
|
||||
|
|
@ -150,7 +155,7 @@ static Res failoverDelete(Range rangeReturn, Land land, Range range)
|
|||
}
|
||||
}
|
||||
if (res == ResOK) {
|
||||
AVER(RangesNest(&oldRange, range));
|
||||
AVER_CRITICAL(RangesNest(&oldRange, range));
|
||||
RangeCopy(rangeReturn, &oldRange);
|
||||
}
|
||||
return res;
|
||||
|
|
@ -170,11 +175,11 @@ static Bool failoverIterate(Land land, LandVisitor visitor, void *closure)
|
|||
|
||||
static Bool failoverFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
/* See <design/failover/#impl.assume.flush>. */
|
||||
(void)LandFlush(fo->primary, fo->secondary);
|
||||
|
|
@ -186,11 +191,11 @@ static Bool failoverFindFirst(Range rangeReturn, Range oldRangeReturn, Land land
|
|||
|
||||
static Bool failoverFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
/* See <design/failover/#impl.assume.flush>. */
|
||||
(void)LandFlush(fo->primary, fo->secondary);
|
||||
|
|
@ -202,11 +207,11 @@ static Bool failoverFindLast(Range rangeReturn, Range oldRangeReturn, Land land,
|
|||
|
||||
static Bool failoverFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
/* See <design/failover/#impl.assume.flush>. */
|
||||
(void)LandFlush(fo->primary, fo->secondary);
|
||||
|
|
@ -218,16 +223,16 @@ static Bool failoverFindLargest(Range rangeReturn, Range oldRangeReturn, Land la
|
|||
|
||||
static Bool failoverFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
Failover fo = MustBeA(Failover, land);
|
||||
Failover fo = MustBeA_CRITICAL(Failover, land);
|
||||
Bool found = FALSE;
|
||||
Res res;
|
||||
|
||||
AVER(FALSE); /* TODO: this code is completely untested! */
|
||||
AVER(foundReturn != NULL);
|
||||
AVER(rangeReturn != NULL);
|
||||
AVER(oldRangeReturn != NULL);
|
||||
/* AVERT(ZoneSet, zoneSet); */
|
||||
AVERT(Bool, high);
|
||||
AVER_CRITICAL(FALSE); /* TODO: this code is completely untested! */
|
||||
AVER_CRITICAL(foundReturn != NULL);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVER_CRITICAL(oldRangeReturn != NULL);
|
||||
/* AVERT_CRITICAL(ZoneSet, zoneSet); */
|
||||
AVERT_CRITICAL(Bool, high);
|
||||
|
||||
/* See <design/failover/#impl.assume.flush>. */
|
||||
(void)LandFlush(fo->primary, fo->secondary);
|
||||
|
|
|
|||
107
mps/code/land.c
107
mps/code/land.c
|
|
@ -4,6 +4,13 @@
|
|||
* Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* .design: <design/land/>
|
||||
*
|
||||
* .critical.macros: In manual-allocation-bound programs using MVFF,
|
||||
* the Land generic functions are on the critical path via mps_free.
|
||||
* In non-checking varieties we provide macro alternatives (in mpm.h)
|
||||
* to these functions that call the underlying methods directly,
|
||||
* giving a few percent improvement in performance but skipping the
|
||||
* re-entrancy checking provided by landEnter and landLeave.
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
|
|
@ -143,40 +150,34 @@ void LandFinish(Land land)
|
|||
/* LandSize -- return the total size of ranges in land
|
||||
*
|
||||
* See <design/land/#function.size>
|
||||
*
|
||||
* .size.critical: In manual-allocation-bound programs using MVFF this
|
||||
* is on the critical path.
|
||||
*/
|
||||
|
||||
Size LandSize(Land land)
|
||||
Size (LandSize)(Land land)
|
||||
{
|
||||
/* .enter-leave.simple */
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVERC(Land, land);
|
||||
|
||||
return Method(Land, land, sizeMethod)(land);
|
||||
return LandSizeMacro(land);
|
||||
}
|
||||
|
||||
|
||||
/* LandInsert -- insert range of addresses into land
|
||||
*
|
||||
* See <design/land/#function.insert>
|
||||
*
|
||||
* .insert.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Res LandInsert(Range rangeReturn, Land land, Range range)
|
||||
Res (LandInsert)(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Res res;
|
||||
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVERT_CRITICAL(Range, range);
|
||||
AVER_CRITICAL(RangeIsAligned(range, land->alignment));
|
||||
AVER_CRITICAL(!RangeIsEmpty(range));
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERC(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(RangeIsAligned(range, land->alignment));
|
||||
AVER(!RangeIsEmpty(range));
|
||||
landEnter(land);
|
||||
|
||||
res = Method(Land, land, insert)(rangeReturn, land, range);
|
||||
res = LandInsertMacro(rangeReturn, land, range);
|
||||
|
||||
landLeave(land);
|
||||
return res;
|
||||
|
|
@ -188,7 +189,7 @@ Res LandInsert(Range rangeReturn, Land land, Range range)
|
|||
* See <design/land/#function.delete>
|
||||
*/
|
||||
|
||||
Res LandDelete(Range rangeReturn, Land land, Range range)
|
||||
Res (LandDelete)(Range rangeReturn, Land land, Range range)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -198,7 +199,7 @@ Res LandDelete(Range rangeReturn, Land land, Range range)
|
|||
AVER(RangeIsAligned(range, land->alignment));
|
||||
landEnter(land);
|
||||
|
||||
res = Method(Land, land, delete)(rangeReturn, land, range);
|
||||
res = LandDeleteMacro(rangeReturn, land, range);
|
||||
|
||||
landLeave(land);
|
||||
return res;
|
||||
|
|
@ -208,19 +209,16 @@ Res LandDelete(Range rangeReturn, Land land, Range range)
|
|||
/* LandIterate -- iterate over isolated ranges of addresses in land
|
||||
*
|
||||
* See <design/land/#function.iterate>
|
||||
*
|
||||
* .iterate.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Bool LandIterate(Land land, LandVisitor visitor, void *closure)
|
||||
Bool (LandIterate)(Land land, LandVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVER_CRITICAL(FUNCHECK(visitor));
|
||||
AVERC(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, iterate)(land, visitor, closure);
|
||||
b = LandIterateMacro(land, visitor, closure);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -233,14 +231,14 @@ Bool LandIterate(Land land, LandVisitor visitor, void *closure)
|
|||
* See <design/land/#function.iterate.and.delete>
|
||||
*/
|
||||
|
||||
Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure)
|
||||
Bool (LandIterateAndDelete)(Land land, LandDeleteVisitor visitor, void *closure)
|
||||
{
|
||||
Bool b;
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVER_CRITICAL(FUNCHECK(visitor));
|
||||
AVERC(Land, land);
|
||||
AVER(FUNCHECK(visitor));
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, iterateAndDelete)(land, visitor, closure);
|
||||
b = LandIterateAndDeleteMacro(land, visitor, closure);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -252,7 +250,7 @@ Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure)
|
|||
* See <design/land/#function.find.first>
|
||||
*/
|
||||
|
||||
Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
Bool (LandFindFirst)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Bool b;
|
||||
|
||||
|
|
@ -263,8 +261,7 @@ Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size
|
|||
AVERT(FindDelete, findDelete);
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, findFirst)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
b = LandFindFirstMacro(rangeReturn, oldRangeReturn, land, size, findDelete);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -276,7 +273,7 @@ Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size
|
|||
* See <design/land/#function.find.last>
|
||||
*/
|
||||
|
||||
Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
Bool (LandFindLast)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Bool b;
|
||||
|
||||
|
|
@ -287,8 +284,7 @@ Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size,
|
|||
AVERT(FindDelete, findDelete);
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, findLast)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
b = LandFindLastMacro(rangeReturn, oldRangeReturn, land, size, findDelete);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -300,7 +296,7 @@ Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size,
|
|||
* See <design/land/#function.find.largest>
|
||||
*/
|
||||
|
||||
Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
Bool (LandFindLargest)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete)
|
||||
{
|
||||
Bool b;
|
||||
|
||||
|
|
@ -311,8 +307,7 @@ Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size si
|
|||
AVERT(FindDelete, findDelete);
|
||||
landEnter(land);
|
||||
|
||||
b = Method(Land, land, findLargest)(rangeReturn, oldRangeReturn, land, size,
|
||||
findDelete);
|
||||
b = LandFindLargestMacro(rangeReturn, oldRangeReturn, land, size, findDelete);
|
||||
|
||||
landLeave(land);
|
||||
return b;
|
||||
|
|
@ -324,7 +319,7 @@ Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size si
|
|||
* See <design/land/#function.find.zones>
|
||||
*/
|
||||
|
||||
Res LandFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
Res (LandFindInZones)(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high)
|
||||
{
|
||||
Res res;
|
||||
|
||||
|
|
@ -337,8 +332,8 @@ Res LandFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn,
|
|||
AVERT(Bool, high);
|
||||
landEnter(land);
|
||||
|
||||
res = Method(Land, land, findInZones)(foundReturn, rangeReturn, oldRangeReturn,
|
||||
land, size, zoneSet, high);
|
||||
res = LandFindInZonesMacro(foundReturn, rangeReturn, oldRangeReturn,
|
||||
land, size, zoneSet, high);
|
||||
|
||||
landLeave(land);
|
||||
return res;
|
||||
|
|
@ -360,20 +355,25 @@ Res LandDescribe(Land land, mps_lib_FILE *stream, Count depth)
|
|||
*
|
||||
* closure argument is the destination Land. Attempt to insert the
|
||||
* range into the destination.
|
||||
*
|
||||
* .flush.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical paths via mps_alloc (and then PoolAlloc,
|
||||
* MVFFAlloc, failoverFind*, LandFlush) and mps_free (and then
|
||||
* MVFFFree, failoverInsert, LandFlush).
|
||||
*/
|
||||
static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closure)
|
||||
Bool LandFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
||||
void *closure)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct newRange;
|
||||
Land dest;
|
||||
|
||||
AVER(deleteReturn != NULL);
|
||||
AVERC(Land, land);
|
||||
AVERT(Range, range);
|
||||
AVER(closure != NULL);
|
||||
AVER_CRITICAL(deleteReturn != NULL);
|
||||
AVERC_CRITICAL(Land, land);
|
||||
AVERT_CRITICAL(Range, range);
|
||||
AVER_CRITICAL(closure != NULL);
|
||||
|
||||
dest = closure;
|
||||
dest = MustBeA_CRITICAL(Land, closure);
|
||||
res = LandInsert(&newRange, dest, range);
|
||||
if (res == ResOK) {
|
||||
*deleteReturn = TRUE;
|
||||
|
|
@ -388,17 +388,14 @@ static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range,
|
|||
/* LandFlush -- move ranges from src to dest
|
||||
*
|
||||
* See <design/land/#function.flush>
|
||||
*
|
||||
* .flush.critical: In manual-allocation-bound programs using MVFF
|
||||
* this is on the critical path.
|
||||
*/
|
||||
|
||||
Bool LandFlush(Land dest, Land src)
|
||||
Bool (LandFlush)(Land dest, Land src)
|
||||
{
|
||||
AVERC_CRITICAL(Land, dest);
|
||||
AVERC_CRITICAL(Land, src);
|
||||
AVERC(Land, dest);
|
||||
AVERC(Land, src);
|
||||
|
||||
return LandIterateAndDelete(src, landFlushVisitor, dest);
|
||||
return LandFlushMacro(dest, src);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
* .trans.bufferinit: The Buffer data structure has an Init field and
|
||||
* an Init method, there's a name clash. We resolve this by calling the
|
||||
* accessor BufferGetInit.
|
||||
*
|
||||
* .critical.macros: In manual-allocation-bound programs using MVFF,
|
||||
* PoolFree and the Land generic functions are on the critical path
|
||||
* via mps_free. In non-checking varieties we provide macro
|
||||
* alternatives to these functions that call the underlying methods
|
||||
* directly, giving a few percent improvement in performance.
|
||||
*/
|
||||
|
||||
#ifndef mpm_h
|
||||
|
|
@ -224,7 +230,7 @@ extern Res PoolCreate(Pool *poolReturn, Arena arena, PoolClass klass,
|
|||
extern void PoolDestroy(Pool pool);
|
||||
extern BufferClass PoolDefaultBufferClass(Pool pool);
|
||||
extern Res PoolAlloc(Addr *pReturn, Pool pool, Size size);
|
||||
extern void PoolFree(Pool pool, Addr old, Size size);
|
||||
extern void (PoolFree)(Pool pool, Addr old, Size size);
|
||||
extern PoolGen PoolSegPoolGen(Pool pool, Seg seg);
|
||||
extern Res PoolTraceBegin(Pool pool, Trace trace);
|
||||
extern void PoolFreeWalk(Pool pool, FreeBlockVisitor f, void *p);
|
||||
|
|
@ -263,6 +269,11 @@ extern PoolDebugMixin PoolNoDebugMixin(Pool pool);
|
|||
extern BufferClass PoolNoBufferClass(void);
|
||||
extern Size PoolNoSize(Pool pool);
|
||||
|
||||
/* See .critical.macros. */
|
||||
#define PoolFreeMacro(pool, old, size) Method(Pool, pool, free)(pool, old, size)
|
||||
#if !defined(AVER_AND_CHECK_ALL)
|
||||
#define PoolFree(pool, old, size) PoolFreeMacro(pool, old, size)
|
||||
#endif /* !defined(AVER_AND_CHECK_ALL) */
|
||||
|
||||
/* Abstract Pool Classes Interface -- see <code/poolabs.c> */
|
||||
extern void PoolClassMixInBuffer(PoolClass klass);
|
||||
|
|
@ -962,22 +973,47 @@ extern Res RootsIterate(Globals arena, RootIterateFn f, void *p);
|
|||
extern Bool LandCheck(Land land);
|
||||
#define LandArena(land) ((land)->arena)
|
||||
#define LandAlignment(land) ((land)->alignment)
|
||||
extern Size LandSize(Land land);
|
||||
extern Size (LandSize)(Land land);
|
||||
extern Res LandInit(Land land, LandClass klass, Arena arena, Align alignment, void *owner, ArgList args);
|
||||
extern void LandFinish(Land land);
|
||||
extern Res LandInsert(Range rangeReturn, Land land, Range range);
|
||||
extern Res LandDelete(Range rangeReturn, Land land, Range range);
|
||||
extern Bool LandIterate(Land land, LandVisitor visitor, void *closure);
|
||||
extern Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure);
|
||||
extern Bool LandFindFirst(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool LandFindLast(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool LandFindLargest(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Res LandFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high);
|
||||
extern Res (LandInsert)(Range rangeReturn, Land land, Range range);
|
||||
extern Res (LandDelete)(Range rangeReturn, Land land, Range range);
|
||||
extern Bool (LandIterate)(Land land, LandVisitor visitor, void *closure);
|
||||
extern Bool (LandIterateAndDelete)(Land land, LandDeleteVisitor visitor, void *closure);
|
||||
extern Bool (LandFindFirst)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool (LandFindLast)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Bool (LandFindLargest)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete);
|
||||
extern Res (LandFindInZones)(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high);
|
||||
extern Res LandDescribe(Land land, mps_lib_FILE *stream, Count depth);
|
||||
extern Bool LandFlush(Land dest, Land src);
|
||||
|
||||
extern Bool LandFlushVisitor(Bool *deleteReturn, Land land, Range range, void *closure);
|
||||
extern Bool (LandFlush)(Land dest, Land src);
|
||||
extern Size LandSlowSize(Land land);
|
||||
extern Bool LandClassCheck(LandClass klass);
|
||||
|
||||
/* See .critical.macros. */
|
||||
#define LandSizeMacro(land) Method(Land, land, sizeMethod)(land)
|
||||
#define LandInsertMacro(rangeReturn, land, range) Method(Land, land, insert)(rangeReturn, land, range)
|
||||
#define LandDeleteMacro(rangeReturn, land, range) Method(Land, land, delete)(rangeReturn, land, range)
|
||||
#define LandIterateMacro(land, visitor, closure) Method(Land, land, iterate)(land, visitor, closure)
|
||||
#define LandIterateAndDeleteMacro(land, visitor, closure) Method(Land, land, iterateAndDelete)(land, visitor, closure)
|
||||
#define LandFindFirstMacro(rangeReturn, oldRangeReturn, land, size, findDelete) Method(Land, land, findFirst)(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindLastMacro(rangeReturn, oldRangeReturn, land, size, findDelete) Method(Land, land, findLast)(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindLargestMacro(rangeReturn, oldRangeReturn, land, size, findDelete) Method(Land, land, findLargest)(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindInZonesMacro(foundReturn, rangeReturn, oldRangeReturn, land, size, zoneSet, high) Method(Land, land, findInZones)(foundReturn, rangeReturn, oldRangeReturn, land, size, zoneSet, high)
|
||||
#define LandFlushMacro(dest, src) LandIterateAndDelete(src, LandFlushVisitor, dest)
|
||||
#if !defined(AVER_AND_CHECK_ALL)
|
||||
#define LandSize(land) LandSizeMacro(land)
|
||||
#define LandInsert(rangeReturn, land, range) LandInsertMacro(rangeReturn, land, range)
|
||||
#define LandDelete(rangeReturn, land, range) LandDeleteMacro(rangeReturn, land, range)
|
||||
#define LandIterate(land, visitor, closure) LandIterateMacro(land, visitor, closure)
|
||||
#define LandIterateAndDelete(land, visitor, closure) LandIterateAndDeleteMacro(land, visitor, closure)
|
||||
#define LandFindFirst(rangeReturn, oldRangeReturn, land, size, findDelete) LandFindFirstMacro(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindLast(rangeReturn, oldRangeReturn, land, size, findDelete) LandFindLastMacro(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindLargest(rangeReturn, oldRangeReturn, land, size, findDelete) LandFindLargestMacro(rangeReturn, oldRangeReturn, land, size, findDelete)
|
||||
#define LandFindInZones(foundReturn, rangeReturn, oldRangeReturn, land, size, zoneSet, high) LandFindInZonesMacro(foundReturn, rangeReturn, oldRangeReturn, land, size, zoneSet, high)
|
||||
#define LandFlush(dest, src) LandFlushMacro(dest, src)
|
||||
#endif /* !defined(AVER_AND_CHECK_ALL) */
|
||||
|
||||
DECLARE_CLASS(Inst, LandClass, InstClass);
|
||||
DECLARE_CLASS(Land, Land, Inst);
|
||||
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ BufferClass PoolDefaultBufferClass(Pool pool)
|
|||
/* PoolAlloc -- allocate a block of memory from a pool
|
||||
*
|
||||
* .alloc.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
* critical path via mps_alloc.
|
||||
*/
|
||||
|
||||
Res PoolAlloc(Addr *pReturn, Pool pool, Size size)
|
||||
|
|
@ -239,22 +239,18 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* PoolFree -- deallocate a block of memory allocated from the pool
|
||||
*
|
||||
* .free.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
/* PoolFree -- deallocate a block of memory allocated from the pool */
|
||||
|
||||
void PoolFree(Pool pool, Addr old, Size size)
|
||||
void (PoolFree)(Pool pool, Addr old, Size size)
|
||||
{
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
AVER_CRITICAL(old != NULL);
|
||||
AVERT(Pool, pool);
|
||||
AVER(old != NULL);
|
||||
/* The pool methods should check that old is in pool. */
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVER_CRITICAL(AddrIsAligned(old, pool->alignment));
|
||||
AVER_CRITICAL(PoolHasRange(pool, old, AddrAdd(old, size)));
|
||||
AVER(size > 0);
|
||||
AVER(AddrIsAligned(old, pool->alignment));
|
||||
AVER(PoolHasRange(pool, old, AddrAdd(old, size)));
|
||||
|
||||
Method(Pool, pool, free)(pool, old, size);
|
||||
PoolFreeMacro(pool, old, size);
|
||||
|
||||
EVENT3(PoolFree, pool, old, size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -591,7 +591,8 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size)
|
|||
regionSize = SizeArenaGrains(size, arena);
|
||||
res = ArenaAlloc(&base, LocusPrefDefault(), regionSize, pool);
|
||||
if (res != ResOK) {
|
||||
PoolFree(mvSpanPool(mv), (Addr)span, sizeof(MVSpanStruct));
|
||||
Pool spanPool = mvSpanPool(mv);
|
||||
PoolFree(spanPool, (Addr)span, sizeof(MVSpanStruct));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
@ -680,6 +681,7 @@ static void MVFree(Pool pool, Addr old, Size size)
|
|||
/* free space should be less than total space */
|
||||
AVER(span->free <= SpanInsideSentinels(span));
|
||||
if(span->free == SpanSize(span)) { /* the whole span is free */
|
||||
Pool spanPool;
|
||||
AVER(span->blockCount == 2);
|
||||
/* both blocks are the trivial sentinel blocks */
|
||||
AVER(span->base.limit == span->base.base);
|
||||
|
|
@ -688,7 +690,8 @@ static void MVFree(Pool pool, Addr old, Size size)
|
|||
ArenaFree(TractBase(span->tract), span->size, pool);
|
||||
RingRemove(&span->spans);
|
||||
RingFinish(&span->spans);
|
||||
PoolFree(mvSpanPool(mv), (Addr)span, sizeof(MVSpanStruct));
|
||||
spanPool = mvSpanPool(mv);
|
||||
PoolFree(spanPool, (Addr)span, sizeof(MVSpanStruct));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,9 @@
|
|||
*
|
||||
* .design: <design/poolmvff>
|
||||
*
|
||||
* NOTE
|
||||
*
|
||||
* There's potential for up to 4% speed improvement by calling Land
|
||||
* methods statically instead of indirectly via the Land abstraction
|
||||
* (thus, cbsInsert instead of LandInsert, and so on). See
|
||||
* <https://info.ravenbrook.com/mail/2014/05/13/16-38-50/0/>
|
||||
* .critical: In manual-allocation-bound programs using MVFF, many of
|
||||
* these functions are on the critical paths via mps_alloc (and then
|
||||
* PoolAlloc, MVFFAlloc) and mps_free (and then PoolFree, MVFFFree).
|
||||
*/
|
||||
|
||||
#include "cbs.h"
|
||||
|
|
@ -103,10 +100,21 @@ static void MVFFReduce(MVFF mvff)
|
|||
Size freeSize, freeLimit, targetFree;
|
||||
RangeStruct freeRange, oldFreeRange;
|
||||
Align grainSize;
|
||||
Land totalLand, freeLand;
|
||||
|
||||
AVERT(MVFF, mvff);
|
||||
AVERT_CRITICAL(MVFF, mvff);
|
||||
arena = PoolArena(MVFFPool(mvff));
|
||||
|
||||
/* Try to return memory when the amount of free memory exceeds a
|
||||
threshold fraction of the total memory. */
|
||||
|
||||
totalLand = MVFFTotalLand(mvff);
|
||||
freeLimit = (Size)(LandSize(totalLand) * mvff->spare);
|
||||
freeLand = MVFFFreeLand(mvff);
|
||||
freeSize = LandSize(freeLand);
|
||||
if (freeSize < freeLimit)
|
||||
return;
|
||||
|
||||
/* NOTE: Memory is returned to the arena in the smallest units
|
||||
possible (arena grains). There's a possibility that this could
|
||||
lead to fragmentation in the arena (because allocation is in
|
||||
|
|
@ -115,14 +123,6 @@ static void MVFFReduce(MVFF mvff)
|
|||
|
||||
grainSize = ArenaGrainSize(arena);
|
||||
|
||||
/* Try to return memory when the amount of free memory exceeds a
|
||||
threshold fraction of the total memory. */
|
||||
|
||||
freeLimit = (Size)(LandSize(MVFFTotalLand(mvff)) * mvff->spare);
|
||||
freeSize = LandSize(MVFFFreeLand(mvff));
|
||||
if (freeSize < freeLimit)
|
||||
return;
|
||||
|
||||
/* For hysteresis, return only a proportion of the free memory. */
|
||||
|
||||
targetFree = freeLimit / 2;
|
||||
|
|
@ -136,7 +136,7 @@ static void MVFFReduce(MVFF mvff)
|
|||
stored at the root node. */
|
||||
|
||||
while (freeSize > targetFree
|
||||
&& LandFindLargest(&freeRange, &oldFreeRange, MVFFFreeLand(mvff),
|
||||
&& LandFindLargest(&freeRange, &oldFreeRange, freeLand,
|
||||
grainSize, FindDeleteNONE))
|
||||
{
|
||||
RangeStruct grainRange, oldRange;
|
||||
|
|
@ -174,16 +174,16 @@ static void MVFFReduce(MVFF mvff)
|
|||
to delete from the TotalCBS we add back to the free list, which
|
||||
can't fail. */
|
||||
|
||||
res = LandDelete(&oldRange, MVFFFreeLand(mvff), &grainRange);
|
||||
res = LandDelete(&oldRange, freeLand, &grainRange);
|
||||
if (res != ResOK)
|
||||
break;
|
||||
freeSize -= RangeSize(&grainRange);
|
||||
AVER(freeSize == LandSize(MVFFFreeLand(mvff)));
|
||||
AVER(freeSize == LandSize(freeLand));
|
||||
|
||||
res = LandDelete(&oldRange, MVFFTotalLand(mvff), &grainRange);
|
||||
res = LandDelete(&oldRange, totalLand, &grainRange);
|
||||
if (res != ResOK) {
|
||||
RangeStruct coalescedRange;
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &grainRange);
|
||||
res = LandInsert(&coalescedRange, freeLand, &grainRange);
|
||||
AVER(res == ResOK);
|
||||
break;
|
||||
}
|
||||
|
|
@ -207,6 +207,7 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size)
|
|||
RangeStruct range, coalescedRange;
|
||||
Addr base;
|
||||
Res res;
|
||||
Land totalLand, freeLand;
|
||||
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
|
|
@ -236,7 +237,8 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size)
|
|||
}
|
||||
|
||||
RangeInitSize(&range, base, allocSize);
|
||||
res = LandInsert(&coalescedRange, MVFFTotalLand(mvff), &range);
|
||||
totalLand = MVFFTotalLand(mvff);
|
||||
res = LandInsert(&coalescedRange, totalLand, &range);
|
||||
if (res != ResOK) {
|
||||
/* Can't record this memory, so return it to the arena and fail. */
|
||||
ArenaFree(base, allocSize, pool);
|
||||
|
|
@ -244,7 +246,8 @@ static Res MVFFExtend(Range rangeReturn, MVFF mvff, Size size)
|
|||
}
|
||||
|
||||
DebugPoolFreeSplat(pool, RangeBase(&range), RangeLimit(&range));
|
||||
res = LandInsert(rangeReturn, MVFFFreeLand(mvff), &range);
|
||||
freeLand = MVFFFreeLand(mvff);
|
||||
res = LandInsert(rangeReturn, freeLand, &range);
|
||||
/* Insertion must succeed because it fails over to a Freelist. */
|
||||
AVER(res == ResOK);
|
||||
|
||||
|
|
@ -269,12 +272,12 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
|||
RangeStruct oldRange;
|
||||
Land land;
|
||||
|
||||
AVER(rangeReturn != NULL);
|
||||
AVERT(MVFF, mvff);
|
||||
AVER(size > 0);
|
||||
AVER(SizeIsAligned(size, PoolAlignment(MVFFPool(mvff))));
|
||||
AVER(FUNCHECK(findMethod));
|
||||
AVERT(FindDelete, findDelete);
|
||||
AVER_CRITICAL(rangeReturn != NULL);
|
||||
AVERT_CRITICAL(MVFF, mvff);
|
||||
AVER_CRITICAL(size > 0);
|
||||
AVER_CRITICAL(SizeIsAligned(size, PoolAlignment(MVFFPool(mvff))));
|
||||
AVER_CRITICAL(FUNCHECK(findMethod));
|
||||
AVERT_CRITICAL(FindDelete, findDelete);
|
||||
|
||||
land = MVFFFreeLand(mvff);
|
||||
found = (*findMethod)(rangeReturn, &oldRange, land, size, findDelete);
|
||||
|
|
@ -288,20 +291,16 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size,
|
|||
|
||||
/* We know that the found range must intersect the newly added
|
||||
* range. But it doesn't necessarily lie entirely within it. */
|
||||
AVER(found);
|
||||
AVER(RangesOverlap(rangeReturn, &newRange));
|
||||
AVER_CRITICAL(found);
|
||||
AVER_CRITICAL(RangesOverlap(rangeReturn, &newRange));
|
||||
}
|
||||
AVER(found);
|
||||
AVER_CRITICAL(found);
|
||||
|
||||
return ResOK;
|
||||
}
|
||||
|
||||
|
||||
/* MVFFAlloc -- Allocate a block
|
||||
*
|
||||
* .alloc.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
/* MVFFAlloc -- Allocate a block */
|
||||
|
||||
static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
||||
{
|
||||
|
|
@ -331,17 +330,14 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size)
|
|||
}
|
||||
|
||||
|
||||
/* MVFFFree -- free the given block
|
||||
*
|
||||
* .free.critical: In manual-allocation-bound programs this is on the
|
||||
* critical path.
|
||||
*/
|
||||
/* MVFFFree -- free the given block */
|
||||
|
||||
static void MVFFFree(Pool pool, Addr old, Size size)
|
||||
{
|
||||
Res res;
|
||||
RangeStruct range, coalescedRange;
|
||||
MVFF mvff;
|
||||
Land freeLand;
|
||||
|
||||
AVERT_CRITICAL(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
|
|
@ -352,7 +348,8 @@ static void MVFFFree(Pool pool, Addr old, Size size)
|
|||
AVER_CRITICAL(size > 0);
|
||||
|
||||
RangeInitSize(&range, old, SizeAlignUp(size, PoolAlignment(pool)));
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &range);
|
||||
freeLand = MVFFFreeLand(mvff);
|
||||
res = LandInsert(&coalescedRange, freeLand, &range);
|
||||
/* Insertion must succeed because it fails over to a Freelist. */
|
||||
AVER_CRITICAL(res == ResOK);
|
||||
MVFFReduce(mvff);
|
||||
|
|
@ -399,6 +396,7 @@ static void MVFFBufferEmpty(Pool pool, Buffer buffer,
|
|||
Res res;
|
||||
MVFF mvff;
|
||||
RangeStruct range, coalescedRange;
|
||||
Land freeLand;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
|
|
@ -410,7 +408,8 @@ static void MVFFBufferEmpty(Pool pool, Buffer buffer,
|
|||
if (RangeIsEmpty(&range))
|
||||
return;
|
||||
|
||||
res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &range);
|
||||
freeLand = MVFFFreeLand(mvff);
|
||||
res = LandInsert(&coalescedRange, freeLand, &range);
|
||||
AVER(res == ResOK);
|
||||
MVFFReduce(mvff);
|
||||
}
|
||||
|
|
@ -618,18 +617,20 @@ static void MVFFFinish(Inst inst)
|
|||
Pool pool = MustBeA(AbstractPool, inst);
|
||||
MVFF mvff = MustBeA(MVFFPool, pool);
|
||||
Bool b;
|
||||
Land totalLand;
|
||||
|
||||
AVERT(MVFF, mvff);
|
||||
mvff->sig = SigInvalid;
|
||||
|
||||
b = LandIterateAndDelete(MVFFTotalLand(mvff), mvffFinishVisitor, pool);
|
||||
totalLand = MVFFTotalLand(mvff);
|
||||
b = LandIterateAndDelete(totalLand, mvffFinishVisitor, pool);
|
||||
AVER(b);
|
||||
AVER(LandSize(MVFFTotalLand(mvff)) == 0);
|
||||
AVER(LandSize(totalLand) == 0);
|
||||
|
||||
LandFinish(MVFFFreeLand(mvff));
|
||||
LandFinish(MVFFFreeSecondary(mvff));
|
||||
LandFinish(MVFFFreePrimary(mvff));
|
||||
LandFinish(MVFFTotalLand(mvff));
|
||||
LandFinish(totalLand);
|
||||
PoolFinish(MVFFBlockPool(mvff));
|
||||
NextMethod(Inst, MVFFPool, finish)(inst);
|
||||
}
|
||||
|
|
@ -654,12 +655,14 @@ static PoolDebugMixin MVFFDebugMixin(Pool pool)
|
|||
static Size MVFFTotalSize(Pool pool)
|
||||
{
|
||||
MVFF mvff;
|
||||
Land totalLand;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return LandSize(MVFFTotalLand(mvff));
|
||||
totalLand = MVFFTotalLand(mvff);
|
||||
return LandSize(totalLand);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -668,12 +671,14 @@ static Size MVFFTotalSize(Pool pool)
|
|||
static Size MVFFFreeSize(Pool pool)
|
||||
{
|
||||
MVFF mvff;
|
||||
Land freeLand;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
mvff = PoolMVFF(pool);
|
||||
AVERT(MVFF, mvff);
|
||||
|
||||
return LandSize(MVFFFreeLand(mvff));
|
||||
freeLand = MVFFFreeLand(mvff);
|
||||
return LandSize(freeLand);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -798,9 +803,9 @@ static Bool MVFFCheck(MVFF mvff)
|
|||
CHECKD(CBS, &mvff->freeCBSStruct);
|
||||
CHECKD(Freelist, &mvff->flStruct);
|
||||
CHECKD(Failover, &mvff->foStruct);
|
||||
CHECKL(LandSize(MVFFTotalLand(mvff)) >= LandSize(MVFFFreeLand(mvff)));
|
||||
CHECKL(SizeIsAligned(LandSize(MVFFFreeLand(mvff)), PoolAlignment(MVFFPool(mvff))));
|
||||
CHECKL(SizeIsArenaGrains(LandSize(MVFFTotalLand(mvff)), PoolArena(MVFFPool(mvff))));
|
||||
CHECKL((LandSize)(MVFFTotalLand(mvff)) >= (LandSize)(MVFFFreeLand(mvff)));
|
||||
CHECKL(SizeIsAligned((LandSize)(MVFFFreeLand(mvff)), PoolAlignment(MVFFPool(mvff))));
|
||||
CHECKL(SizeIsArenaGrains((LandSize)(MVFFTotalLand(mvff)), PoolArena(MVFFPool(mvff))));
|
||||
CHECKL(BoolCheck(mvff->slotHigh));
|
||||
CHECKL(BoolCheck(mvff->firstFit));
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@
|
|||
* .note.stack: It's important that the MPS have a bounded stack size,
|
||||
* and this is a problem for tree algorithms. Basically, we have to
|
||||
* avoid recursion. See design.mps.sp.sol.depth.no-recursion.
|
||||
*
|
||||
* .critical: In manual-allocation-bound programs using MVFF, many of
|
||||
* these functions are on the critical paths via mps_alloc (and then
|
||||
* PoolAlloc, MVFFAlloc, failoverFind*, cbsFind*, SplayTreeFind*) and
|
||||
* mps_free (and then MVFFFree, failoverInsert, cbsInsert,
|
||||
* SplayTreeInsert).
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -506,6 +512,7 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
|||
SplayTree splay, TreeKey key,
|
||||
TreeCompareFunction compare)
|
||||
{
|
||||
SplayUpdateNodeFunction updateNode;
|
||||
Tree middle, leftLast, rightFirst;
|
||||
Compare cmp;
|
||||
|
||||
|
|
@ -513,6 +520,7 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
|||
AVER_CRITICAL(FUNCHECK(compare));
|
||||
AVER_CRITICAL(!SplayTreeIsEmpty(splay));
|
||||
|
||||
updateNode = splay->updateNode;
|
||||
leftLast = TreeEMPTY;
|
||||
rightFirst = TreeEMPTY;
|
||||
middle = SplayTreeRoot(splay);
|
||||
|
|
@ -540,7 +548,7 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
|||
if (!TreeHasLeft(middle))
|
||||
goto stop;
|
||||
middle = SplayZigZigRev(middle, &rightFirst);
|
||||
splay->updateNode(splay, TreeRight(rightFirst));
|
||||
updateNode(splay, TreeRight(rightFirst));
|
||||
break;
|
||||
case CompareGREATER:
|
||||
if (!TreeHasRight(middle))
|
||||
|
|
@ -565,7 +573,7 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn,
|
|||
if (!TreeHasRight(middle))
|
||||
goto stop;
|
||||
middle = SplayZagZagRev(middle, &leftLast);
|
||||
splay->updateNode(splay, TreeLeft(leftLast));
|
||||
updateNode(splay, TreeLeft(leftLast));
|
||||
break;
|
||||
case CompareLESS:
|
||||
if (!TreeHasLeft(middle))
|
||||
|
|
@ -589,13 +597,17 @@ stop:
|
|||
|
||||
static Tree SplayUpdateLeftSpine(SplayTree splay, Tree node, Tree child)
|
||||
{
|
||||
SplayUpdateNodeFunction updateNode;
|
||||
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVERT_CRITICAL(Tree, node);
|
||||
AVERT_CRITICAL(Tree, child);
|
||||
|
||||
updateNode = splay->updateNode;
|
||||
while(node != TreeEMPTY) {
|
||||
Tree parent = TreeLeft(node);
|
||||
TreeSetLeft(node, child); /* un-reverse pointer */
|
||||
splay->updateNode(splay, node);
|
||||
updateNode(splay, node);
|
||||
child = node;
|
||||
node = parent;
|
||||
}
|
||||
|
|
@ -606,13 +618,17 @@ static Tree SplayUpdateLeftSpine(SplayTree splay, Tree node, Tree child)
|
|||
|
||||
static Tree SplayUpdateRightSpine(SplayTree splay, Tree node, Tree child)
|
||||
{
|
||||
SplayUpdateNodeFunction updateNode;
|
||||
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVERT_CRITICAL(Tree, node);
|
||||
AVERT_CRITICAL(Tree, child);
|
||||
|
||||
updateNode = splay->updateNode;
|
||||
while (node != TreeEMPTY) {
|
||||
Tree parent = TreeRight(node);
|
||||
TreeSetRight(node, child); /* un-reverse pointer */
|
||||
splay->updateNode(splay, node);
|
||||
updateNode(splay, node);
|
||||
child = node;
|
||||
node = parent;
|
||||
}
|
||||
|
|
@ -725,7 +741,6 @@ static Compare SplaySplay(SplayTree splay, TreeKey key,
|
|||
|
||||
|
||||
/* SplayTreeInsert -- insert a node into a splay tree
|
||||
*
|
||||
*
|
||||
* This function is used to insert a node into the tree. Splays the
|
||||
* tree at the node's key. If an attempt is made to insert a node that
|
||||
|
|
@ -915,10 +930,9 @@ Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn,
|
|||
Count count = SplayDebugCount(splay);
|
||||
#endif
|
||||
|
||||
|
||||
AVERT(SplayTree, splay);
|
||||
AVER(leftReturn != NULL);
|
||||
AVER(rightReturn != NULL);
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVER_CRITICAL(leftReturn != NULL);
|
||||
AVER_CRITICAL(rightReturn != NULL);
|
||||
|
||||
if (SplayTreeIsEmpty(splay)) {
|
||||
*leftReturn = *rightReturn = TreeEMPTY;
|
||||
|
|
@ -936,14 +950,14 @@ Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn,
|
|||
break;
|
||||
|
||||
case CompareLESS:
|
||||
AVER(!TreeHasLeft(stateStruct.middle));
|
||||
AVER_CRITICAL(!TreeHasLeft(stateStruct.middle));
|
||||
*rightReturn = stateStruct.middle;
|
||||
*leftReturn = stateStruct.leftLast;
|
||||
found = TRUE;
|
||||
break;
|
||||
|
||||
case CompareGREATER:
|
||||
AVER(!TreeHasRight(stateStruct.middle));
|
||||
AVER_CRITICAL(!TreeHasRight(stateStruct.middle));
|
||||
*leftReturn = stateStruct.middle;
|
||||
*rightReturn = stateStruct.rightFirst;
|
||||
found = TRUE;
|
||||
|
|
@ -1101,8 +1115,8 @@ static Compare SplayFindFirstCompare(Tree node, TreeKey key)
|
|||
void *testClosure;
|
||||
SplayTree splay;
|
||||
|
||||
AVERT(Tree, node);
|
||||
AVER(key != NULL);
|
||||
AVERT_CRITICAL(Tree, node);
|
||||
AVER_CRITICAL(key != NULL);
|
||||
|
||||
/* Lift closure values into variables so that they aren't aliased by
|
||||
calls to the test functions. */
|
||||
|
|
@ -1140,8 +1154,8 @@ static Compare SplayFindLastCompare(Tree node, TreeKey key)
|
|||
void *testClosure;
|
||||
SplayTree splay;
|
||||
|
||||
AVERT(Tree, node);
|
||||
AVER(key != NULL);
|
||||
AVERT_CRITICAL(Tree, node);
|
||||
AVER_CRITICAL(key != NULL);
|
||||
|
||||
/* Lift closure values into variables so that they aren't aliased by
|
||||
calls to the test functions. */
|
||||
|
|
@ -1195,10 +1209,10 @@ Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay,
|
|||
SplayFindClosureStruct closureStruct;
|
||||
Bool found;
|
||||
|
||||
AVER(nodeReturn != NULL);
|
||||
AVERT(SplayTree, splay);
|
||||
AVER(FUNCHECK(testNode));
|
||||
AVER(FUNCHECK(testTree));
|
||||
AVER_CRITICAL(nodeReturn != NULL);
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVER_CRITICAL(FUNCHECK(testNode));
|
||||
AVER_CRITICAL(FUNCHECK(testTree));
|
||||
|
||||
if (SplayTreeIsEmpty(splay) ||
|
||||
!testTree(splay, SplayTreeRoot(splay), testClosure))
|
||||
|
|
@ -1258,10 +1272,10 @@ Bool SplayFindLast(Tree *nodeReturn, SplayTree splay,
|
|||
SplayFindClosureStruct closureStruct;
|
||||
Bool found;
|
||||
|
||||
AVER(nodeReturn != NULL);
|
||||
AVERT(SplayTree, splay);
|
||||
AVER(FUNCHECK(testNode));
|
||||
AVER(FUNCHECK(testTree));
|
||||
AVER_CRITICAL(nodeReturn != NULL);
|
||||
AVERT_CRITICAL(SplayTree, splay);
|
||||
AVER_CRITICAL(FUNCHECK(testNode));
|
||||
AVER_CRITICAL(FUNCHECK(testTree));
|
||||
|
||||
if (SplayTreeIsEmpty(splay) ||
|
||||
!testTree(splay, SplayTreeRoot(splay), testClosure))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue