1
Fork 0
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:
Gareth Rees 2018-07-05 12:54:16 +01:00
commit 2b469ef694
10 changed files with 313 additions and 245 deletions

View file

@ -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);
}

View file

@ -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));

View file

@ -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) \

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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));
}
}

View file

@ -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;

View file

@ -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))