diff --git a/mps/code/arena.c b/mps/code/arena.c
index 1d1647552f2..bb2a060b27c 100644
--- a/mps/code/arena.c
+++ b/mps/code/arena.c
@@ -9,7 +9,6 @@
#include "poolmv.h"
#include "mpm.h"
#include "cbs.h"
-#include "zonedcbs.h"
#include "bt.h"
#include "poolmfs.h"
#include "mpscmfs.h"
@@ -155,7 +154,7 @@ Bool ArenaCheck(Arena arena)
CHECKL(BoolCheck(arena->hasFreeCBS));
if (arena->hasFreeCBS)
- ZonedCBSCheck(ArenaZonedCBS(arena));
+ CBSCheck(ArenaZonedCBS(arena));
return TRUE;
}
@@ -221,11 +220,18 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment)
if (res != ResOK)
goto failMFSInit;
- res = ZonedCBSInit(ArenaZonedCBS(arena), arena, ArenaCBSBlockPool(arena),
- ArenaAlign(arena));
+ /* Initialise the freeCBS. */
+ MPS_ARGS_BEGIN(cbsiArgs) {
+ MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
+ MPS_ARGS_DONE(cbsiArgs);
+ res = CBSInit(arena, ArenaZonedCBS(arena), arena, alignment, TRUE, TRUE, cbsiArgs);
+ } MPS_ARGS_END(cbsiArgs);
+ AVER(res == ResOK); /* no allocation, no failure expected */
if (res != ResOK)
goto failCBSInit;
-
+ /* Note that although freeCBS is initialised, it doesn't have any memory
+ for its blocks, so hasFreeCBS remains FALSE until later. */
+
/* initialize the reservoir, */
res = ReservoirInit(&arena->reservoirStruct, arena);
if (res != ResOK)
@@ -235,7 +241,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment)
return ResOK;
failReservoirInit:
- ZonedCBSFinish(ArenaZonedCBS(arena));
+ CBSFinish(ArenaZonedCBS(arena));
failCBSInit:
PoolFinish(ArenaCBSBlockPool(arena));
failMFSInit:
@@ -364,7 +370,7 @@ void ArenaDestroy(Arena arena)
containing CBS blocks might be allocated in those chunks. */
AVER(arena->hasFreeCBS);
arena->hasFreeCBS = FALSE;
- ZonedCBSFinish(ArenaZonedCBS(arena));
+ CBSFinish(ArenaZonedCBS(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
that would use the ZonedCBS. */
@@ -675,7 +681,7 @@ static void arenaExcludePage(Arena arena, Range pageRange)
RangeStruct oldRange;
Res res;
- res = ZonedCBSDelete(&oldRange, ArenaZonedCBS(arena), pageRange);
+ res = CBSDelete(&oldRange, ArenaZonedCBS(arena), pageRange);
AVER(res == ResOK); /* we just gave memory to the CBSs */
}
@@ -696,7 +702,7 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
AVERT(Arena, arena);
AVERT(Range, range);
- res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), range);
+ res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), range);
if (res == ResLIMIT) { /* freeCBS MFS pool ran out of blocks */
RangeStruct pageRange;
@@ -704,8 +710,8 @@ static Res arenaCBSInsert(Range rangeReturn, Arena arena, Range range)
if (res != ResOK)
return res;
/* Must insert before exclude so that we can bootstrap when the
- ZonedCBS is empty. */
- res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), range);
+ zoned CBS is empty. */
+ res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), range);
AVER(res == ResOK); /* we just gave memory to the CBSs */
arenaExcludePage(arena, &pageRange);
}
@@ -752,7 +758,7 @@ static void arenaCBSInsertSteal(Range rangeReturn, Arena arena, Range rangeIO)
MFSExtend(ArenaCBSBlockPool(arena), pageBase, ArenaAlign(arena));
/* Try again. */
- res = ZonedCBSInsert(rangeReturn, ArenaZonedCBS(arena), rangeIO);
+ res = CBSInsert(rangeReturn, ArenaZonedCBS(arena), rangeIO);
AVER(res == ResOK); /* we just gave memory to the CBS */
}
@@ -803,7 +809,7 @@ void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit)
Res res;
RangeInit(&range, base, limit);
- res = ZonedCBSDelete(&oldRange, ArenaZonedCBS(arena), &range);
+ res = CBSDelete(&oldRange, ArenaZonedCBS(arena), &range);
/* Shouldn't be any other kind of failure because we were only deleting
a non-coalesced block. See .chunk.no-coalesce. */
@@ -823,6 +829,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
Count pages;
Res res;
FindDelete fd;
+ CBSFindInZonesMethod find;
AVER(tractReturn != NULL);
/* ZoneSet is arbitrary */
@@ -834,8 +841,8 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
/* Step 1. Find a range of address space. */
fd = high ? FindDeleteHIGH : FindDeleteLOW;
- res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena),
- zones, size, fd, high);
+ find = high ? CBSFindLastInZones : CBSFindFirstInZones;
+ res = find(&range, &oldRange, ArenaZonedCBS(arena), size, arena, zones);
if (res == ResLIMIT) { /* found block, but couldn't store info */
RangeStruct pageRange;
@@ -843,8 +850,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
if (res != ResOK) /* disasterously short on memory */
return res;
arenaExcludePage(arena, &pageRange);
- res = ZonedCBSFind(&range, &oldRange, ArenaZonedCBS(arena),
- zones, size, fd, high);
+ res = find(&range, &oldRange, ArenaZonedCBS(arena), size, arena, zones);
AVER(res != ResLIMIT);
}
@@ -876,7 +882,7 @@ static Res arenaAllocFromCBS(Tract *tractReturn, ZoneSet zones, Bool high,
failMark:
NOTREACHED; /* FIXME */
{
- Res insertRes = ZonedCBSInsert(&oldRange, ArenaZonedCBS(arena), &range);
+ Res insertRes = CBSInsert(&oldRange, ArenaZonedCBS(arena), &range);
AVER(insertRes == ResOK); /* We only just deleted it. */
/* If the insert does fail, we lose some address space permanently. */
}
diff --git a/mps/code/cbs.c b/mps/code/cbs.c
index dc6fcfc75eb..fe07f6aff27 100644
--- a/mps/code/cbs.c
+++ b/mps/code/cbs.c
@@ -70,6 +70,7 @@ Bool CBSCheck(CBS cbs)
CHECKL(SplayTreeCheck(splayTreeOfCBS(cbs)));
/* nothing to check about splayTreeSize */
CHECKD(Pool, cbs->blockPool);
+ CHECKU(Arena, cbs->arena);
CHECKL(BoolCheck(cbs->fastFind));
CHECKL(BoolCheck(cbs->inCBS));
CHECKL(BoolCheck(cbs->ownPool));
@@ -198,6 +199,48 @@ static void cbsUpdateNode(SplayTree tree, SplayNode node,
}
+/* cbsUpdateZonedNode -- update size and zone info after restructuring */
+
+static void cbsUpdateZonedNode(SplayTree tree, SplayNode node,
+ SplayNode leftChild, SplayNode rightChild)
+{
+ Size maxSize;
+ ZoneSet zones;
+ CBSBlock block;
+ Arena arena;
+
+ AVERT(SplayTree, tree);
+ AVERT(SplayNode, node);
+ if (leftChild != NULL)
+ AVERT(SplayNode, leftChild);
+ if (rightChild != NULL)
+ AVERT(SplayNode, rightChild);
+ AVER(cbsOfSplayTree(tree)->fastFind);
+
+ block = cbsBlockOfSplayNode(node);
+ maxSize = CBSBlockSize(block);
+ arena = cbsOfSplayTree(tree)->arena;
+ zones = ZoneSetOfRange(arena, CBSBlockBase(block), CBSBlockLimit(block));
+
+ if (leftChild != NULL) {
+ Size size = cbsBlockOfSplayNode(leftChild)->maxSize;
+ if (size > maxSize)
+ maxSize = size;
+ zones = ZoneSetUnion(zones, cbsBlockOfSplayNode(leftChild)->zones);
+ }
+
+ if (rightChild != NULL) {
+ Size size = cbsBlockOfSplayNode(rightChild)->maxSize;
+ if (size > maxSize)
+ maxSize = size;
+ zones = ZoneSetUnion(zones, cbsBlockOfSplayNode(rightChild)->zones);
+ }
+
+ block->maxSize = maxSize;
+ block->zones = zones;
+}
+
+
/* CBSInit -- Initialise a CBS structure
*
* See .
@@ -207,15 +250,21 @@ ARG_DEFINE_KEY(cbs_extend_by, Size);
ARG_DEFINE_KEY(cbs_block_pool, Pool);
Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment,
- Bool fastFind, ArgList args)
+ Bool fastFind, Bool zoned, ArgList args)
{
Size extendBy = CBS_EXTEND_BY_DEFAULT;
Bool extendSelf = TRUE;
ArgStruct arg;
Res res;
Pool blockPool = NULL;
+ SplayUpdateNodeMethod update;
AVERT(Arena, arena);
+ AVER(cbs != NULL);
+ AVER(AlignCheck(alignment));
+ AVER(BoolCheck(fastFind));
+ AVER(BoolCheck(zoned));
+
if (ArgPick(&arg, args, CBSBlockPool))
blockPool = arg.val.pool;
@@ -224,8 +273,15 @@ Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment,
if (ArgPick(&arg, args, MFSExtendSelf))
extendSelf = arg.val.b;
- SplayTreeInit(splayTreeOfCBS(cbs), &cbsSplayCompare,
- fastFind ? &cbsUpdateNode : NULL);
+ update = NULL;
+ if (fastFind)
+ update = cbsUpdateNode;
+ if (zoned) {
+ AVER(fastFind);
+ update = cbsUpdateZonedNode;
+ }
+
+ SplayTreeInit(splayTreeOfCBS(cbs), cbsSplayCompare, update);
if (blockPool != NULL) {
cbs->blockPool = blockPool;
@@ -245,7 +301,9 @@ Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment,
cbs->splayTreeSize = 0;
+ cbs->arena = arena;
cbs->fastFind = fastFind;
+ cbs->zoned = zoned;
cbs->alignment = alignment;
cbs->inCBS = TRUE;
@@ -812,6 +870,20 @@ static Bool cbsTestNodeInZones(SplayTree tree, SplayNode node,
closure->arena, closure->zoneSet, closure->size);
}
+static Bool cbsTestTreeInZones(SplayTree tree, SplayNode node,
+ void *closureP, Size closureSize)
+{
+ CBSBlock block = cbsBlockOfSplayNode(node);
+ cbsTestNodeInZonesClosure closure = closureP;
+
+ UNUSED(tree);
+ AVER(closureSize == sizeof(cbsTestNodeInZonesClosureStruct));
+ UNUSED(closureSize);
+
+ return block->maxSize >= closure->size &&
+ ZoneSetInter(block->zones, closure->zoneSet) != ZoneSetEMPTY;
+}
+
static Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn,
CBS cbs, Size size,
Arena arena, ZoneSet zoneSet,
@@ -855,7 +927,7 @@ static Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn,
closure.size = size;
if (splayFind(&node, splayTreeOfCBS(cbs),
&cbsTestNodeInZones,
- &cbsTestTree,
+ &cbsTestTreeInZones,
&closure, sizeof(closure))) {
CBSBlock block = cbsBlockOfSplayNode(node);
RangeStruct rangeStruct, oldRangeStruct;
diff --git a/mps/code/cbs.h b/mps/code/cbs.h
index 4ee9ebb3657..e2141a30351 100644
--- a/mps/code/cbs.h
+++ b/mps/code/cbs.h
@@ -16,6 +16,10 @@
#include "splay.h"
+/* TODO: There ought to be different levels of CBS block with inheritance
+ so that CBSs without fastFind don't allocate the maxSize and zones fields,
+ and CBSs without zoned don't allocate the zones field. */
+
typedef struct CBSBlockStruct *CBSBlock;
typedef struct CBSBlockStruct {
SplayNodeStruct splayNode;
@@ -36,8 +40,8 @@ extern const struct mps_key_s _mps_key_cbs_block_pool;
#define CBSBlockPool (&_mps_key_cbs_block_pool)
#define CBSBlockPool_FIELD pool
-extern Res CBSInit(Arena arena, CBS cbs, void *owner,
- Align alignment, Bool fastFind, ArgList args);
+extern Res CBSInit(Arena arena, CBS cbs, void *owner, Align alignment,
+ Bool fastFind, Bool zoned, ArgList args);
extern void CBSFinish(CBS cbs);
extern Res CBSInsert(Range rangeReturn, CBS cbs, Range range);
diff --git a/mps/code/config.h b/mps/code/config.h
index 8e3004a81b1..348585ba321 100644
--- a/mps/code/config.h
+++ b/mps/code/config.h
@@ -307,12 +307,9 @@
/* @@@@ knows the implementation of ZoneSets */
/* FIXME: There's no particular reason to think this will avoid GC segments. */
-/* .segpref.default: For EPcore, non-DL segments should be placed high */
-/* to reduce fragmentation of DL pools (see request.epcore.170193_). */
-/* .. _request.epcore.170193: https://info.ravenbrook.com/project/mps/import/2001-11-05/mmprevol/request/epcore/170193 */
#define SegPrefDEFAULT { \
SegPrefSig, /* sig */ \
- TRUE, /* high */ \
+ FALSE, /* high */ \
ArenaDefaultZONESET, /* zoneSet */ \
ZoneSetEMPTY, /* avoid */ \
}
diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h
index 4c0747e3b9c..0b02fbbb10d 100644
--- a/mps/code/mpmst.h
+++ b/mps/code/mpmst.h
@@ -614,9 +614,11 @@ typedef struct GlobalsStruct {
typedef struct CBSStruct {
SplayTreeStruct splayTree;
STATISTIC_DECL(Count splayTreeSize);
+ Arena arena;
Pool blockPool;
Align alignment;
- Bool fastFind;
+ Bool fastFind; /* maintain and use size property? */
+ Bool zoned; /* maintain and use zone property? */
Bool inCBS; /* prevent reentrance */
Bool ownPool; /* did we create blockPool? */
/* meters for sizes of search structures at each op */
@@ -677,7 +679,7 @@ typedef struct mps_arena_s {
Bool hasFreeCBS; /* Is freeCBS available? */
MFSStruct zonedCBSBlockPoolStruct;
- ZonedCBSStruct zonedCBSStruct;
+ CBSStruct zonedCBSStruct;
ZoneSet freeZones; /* zones not yet allocated */
/* locus fields () */
diff --git a/mps/code/mps.c b/mps/code/mps.c
index 85c34f81359..329c67de9a4 100644
--- a/mps/code/mps.c
+++ b/mps/code/mps.c
@@ -74,7 +74,6 @@
#include "range.c"
#include "freelist.c"
#include "sa.c"
-#include "zonedcbs.c"
/* Additional pool classes */
diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj
index 69b47b767dc..9524465561a 100644
--- a/mps/code/mps.xcodeproj/project.pbxproj
+++ b/mps/code/mps.xcodeproj/project.pbxproj
@@ -1250,8 +1250,6 @@
3114A6BA156E9768001E0AA3 /* walkt0.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = walkt0.c; sourceTree = ""; };
3114A6C6156E9815001E0AA3 /* mpseventcnv */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mpseventcnv; sourceTree = BUILT_PRODUCTS_DIR; };
3114A6D0156E9829001E0AA3 /* eventcnv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eventcnv.c; sourceTree = ""; };
- 3115E70118BED7E000385449 /* zonedcbs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = zonedcbs.h; sourceTree = ""; };
- 3115E70218BEDA1100385449 /* zonedcbs.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = zonedcbs.c; sourceTree = ""; };
31160D921899540D0071EB17 /* abq.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = abq.txt; path = ../design/abq.txt; sourceTree = ""; };
31160D931899540D0071EB17 /* alloc-frame.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = "alloc-frame.txt"; path = "../design/alloc-frame.txt"; sourceTree = ""; };
31160D941899540D0071EB17 /* arena.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = arena.txt; path = ../design/arena.txt; sourceTree = ""; };
@@ -2137,8 +2135,6 @@
31EEAC0E156AB27B00714D05 /* walk.c */,
3112ED3A18ABC57F00CC531A /* sa.h */,
3112ED3B18ABC75200CC531A /* sa.c */,
- 3115E70118BED7E000385449 /* zonedcbs.h */,
- 3115E70218BEDA1100385449 /* zonedcbs.c */,
);
name = "MPM Core";
sourceTree = "";
diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c
index 16f11060e05..7c616bcfcfa 100644
--- a/mps/code/poolmv2.c
+++ b/mps/code/poolmv2.c
@@ -269,7 +269,7 @@ static Res MVTInit(Pool pool, ArgList args)
if (abqDepth < 3)
abqDepth = 3;
- res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, align, FALSE, args);
+ res = CBSInit(arena, MVTCBS(mvt), (void *)mvt, align, FALSE, FALSE, args);
if (res != ResOK)
goto failCBS;
diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c
index 8ed836ea247..79666896b1a 100644
--- a/mps/code/poolmvff.c
+++ b/mps/code/poolmvff.c
@@ -602,7 +602,7 @@ static Res MVFFInit(Pool pool, ArgList args)
if (res != ResOK)
goto failInit;
- res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, align, TRUE, args);
+ res = CBSInit(arena, CBSOfMVFF(mvff), (void *)mvff, align, TRUE, FALSE, args);
if (res != ResOK)
goto failInit;
diff --git a/mps/code/zonedcbs.c b/mps/code/zonedcbs.c
deleted file mode 100644
index 1a668642484..00000000000
--- a/mps/code/zonedcbs.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/* zonedcbs.c: ZONED COALESCING BLOCK STRUCTURE IMPLEMENTATION
- *
- * $Id$
- * Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
- *
- * A Zone CBS is like a CBS but allows for efficient allocation in zones.
- * Allocation in zones gives control over some parts of an object's address,
- * so that we can later apply fast filters on the critical path.
- * The Zone CBS is mainly used by the arena to allocate blocks to pools.
- *
- * Can be stressed by setting a small arena size.
- *
- * This code is essentially an optimisation of CBSFindFirstInZones, but
- * doesn't have quite the same effect. FIXME: Be clearer.
- */
-
-#include "zonedcbs.h"
-#include "mpm.h"
-#include "cbs.h"
-
-
-#define ZonedCBSBlockPool(zcbs) RVALUE((zcbs)->blockPool)
-#define ZonedCBSFreeCBS(zcbs) (&(zcbs)->freeStruct)
-#define ZonedCBSZoneCBS(zcbs, z) (&(zcbs)->zoneStruct[z])
-#define ZonedCBSNZones(zcbs) NELEMS((zcbs)->zoneStruct)
-
-
-/* ZonedCBSCheck -- check consistency of zoned CBS structure */
-
-Bool ZonedCBSCheck(ZonedCBS zcbs)
-{
- Index i;
-
- CHECKS(ZonedCBS, zcbs);
- CHECKU(Arena, zcbs->arena);
- CHECKD(Pool, ZonedCBSBlockPool(zcbs));
- CHECKD(CBS, ZonedCBSFreeCBS(zcbs));
- CHECKL(ZonedCBSNZones(zcbs) == sizeof(ZoneSet) * CHAR_BIT);
- CHECKL(ZonedCBSNZones(zcbs) == NELEMS(zcbs->zoneStruct));
- for (i = 0; i < ZonedCBSNZones(zcbs); ++i)
- CHECKD(CBS, ZonedCBSZoneCBS(zcbs, i));
-
- /* TODO: Thorough check summing CBSs against totals. The sum of the
- sizes of the contents of the zone CBSs and the freeCBS should equal
- the total allocatable free space in the chunks. The CBS ADT
- probably ought to maintain totals like this too. */
-
- return TRUE;
-}
-
-
-/* ZonedCBSInit -- initialise a Zoned CBS */
-
-Res ZonedCBSInit(ZonedCBS zcbs, Arena arena, Pool blockPool, Align alignment)
-{
- Index i;
- Res res;
-
- AVER(zcbs != NULL);
- AVERT(Pool, blockPool);
-
- zcbs->arena = arena;
- zcbs->blockPool = blockPool;
-
- /* Initialise the freeCBS. */
- MPS_ARGS_BEGIN(cbsiArgs) {
- MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, blockPool);
- MPS_ARGS_DONE(cbsiArgs);
- res = CBSInit(arena, ZonedCBSFreeCBS(zcbs), zcbs, alignment, TRUE, cbsiArgs);
- } MPS_ARGS_END(cbsiArgs);
- AVER(res == ResOK); /* no allocation, no failure expected */
- if (res != ResOK)
- goto failCBSInit;
- /* Note that although freeCBS is initialised, it doesn't have any memory
- for its blocks, so hasFreeCBS remains FALSE until later. */
-
- /* Initialise the zoneCBSs. */
- for (i = 0; i < NELEMS(zcbs->zoneStruct); ++i) {
- MPS_ARGS_BEGIN(cbsiArgs) {
- MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, blockPool);
- MPS_ARGS_DONE(cbsiArgs);
- res = CBSInit(arena, ZonedCBSZoneCBS(zcbs, i), arena, alignment, TRUE, cbsiArgs);
- } MPS_ARGS_END(cbsiArgs);
- AVER(res == ResOK); /* no allocation, no failure expected */
- if (res != ResOK)
- goto failZoneCBSInit;
- }
-
- zcbs->sig = ZonedCBSSig;
- AVERT(ZonedCBS, zcbs);
-
- return ResOK;
-
-failZoneCBSInit:
- while (i > 0) {
- --i;
- CBSFinish(ZonedCBSZoneCBS(zcbs, i));
- }
- CBSFinish(ZonedCBSFreeCBS(zcbs));
-failCBSInit:
- return res;
-}
-
-
-/* ZonedCBSFinish -- finish the zoned CBS */
-
-void ZonedCBSFinish(ZonedCBS zcbs)
-{
- Index i;
-
- AVERT(ZonedCBS, zcbs);
-
- zcbs->sig = SigInvalid;
-
- /* FIXME: Should be asserting that CBSs are empty? Could iterate over
- chunks and remove their ranges to make sure things are consistent. */
-
- for (i = 0; i < ZonedCBSNZones(zcbs); ++i)
- CBSFinish(ZonedCBSZoneCBS(zcbs, i));
- CBSFinish(ZonedCBSFreeCBS(zcbs));
-}
-
-
-/* ZonedCBSInsert -- insert a range into the zoned CBS
- *
- * We just insert it into the free CBS. It will get split up and cached
- * in the zoned CBSs by ZonedCBSFindFirst and ZonedCBSFindLast.
- */
-
-Res ZonedCBSInsert(Range rangeReturn, ZonedCBS zcbs, Range range)
-{
- ZoneSet zs;
-
- AVERT(ZonedCBS, zcbs);
-
- /* TODO: Consider moving empty zone stripes back to freeCBS. At the
- moment we do not do this, partly for simplicity, and partly to
- keep large objects apart from smaller ones, at the possible cost
- of address space fragmentation. We probably do not want to do it
- eagerly in any case, but lazily if we're unable to find address
- space, even though that reduces first-fit. */
-
- zs = ZoneSetOfRange(zcbs->arena, RangeBase(range), RangeLimit(range));
- if (ZoneSetIsSingle(zs)) {
- Index zone = AddrZone(zcbs->arena, RangeBase(range));
- CBS zoneCBS = ZonedCBSZoneCBS(zcbs, zone);
- return CBSInsert(rangeReturn, zoneCBS, range);
- }
-
- return CBSInsert(rangeReturn, ZonedCBSFreeCBS(zcbs), range);
-}
-
-
-/* ZonedCBSDelete -- delete a range from the zoned CBS
- *
- * The range may be split between the zone CBSs and the free CBS on zone
- * stripe boundaries, in which case we have to iterate.
- *
- * .delete.exists: The range must exist in the zoned CBS. To make the
- * zoned CBS more general we'd need to unwind the error case where we
- * found a hole, putting the range we'd already found back. This isn't
- * required by the arena.
- *
- * FIXME: Document guarantees about res.
- */
-
-Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range)
-{
- Res res;
- ZoneSet zs;
- Addr base, limit;
-
- AVER(oldRange != NULL);
- AVERT(ZonedCBS, zcbs);
- AVERT(Range, range);
-
- zs = ZoneSetOfRange(zcbs->arena, RangeBase(range), RangeLimit(range));
- if (ZoneSetIsSingle(zs)) {
- Index zone = AddrZone(zcbs->arena, RangeBase(range));
- CBS zoneCBS = ZonedCBSZoneCBS(zcbs, zone);
- res = CBSDelete(oldRange, zoneCBS, range);
- if (res != ResFAIL) /* block was in zone CBS */
- return res;
- }
-
- res = CBSDelete(oldRange, ZonedCBSFreeCBS(zcbs), range);
- if (res != ResFAIL) /* block was in free CBS */
- return res;
-
- /* The range may be divided between the free CBS and zone CBSs. */
- base = RangeBase(range);
- limit = RangeLimit(range);
- while (base < limit) {
- Addr stripeLimit;
- CBS zoneCBS;
- RangeStruct stripe, oldStripe;
- Index zone;
-
- stripeLimit = AddrAlignUp(AddrAdd(base, 1), ArenaStripeSize(zcbs->arena));
- if (stripeLimit > limit)
- stripeLimit = limit;
-
- zone = AddrZone(zcbs->arena, base);
- AVER(AddrZone(zcbs->arena, AddrSub(stripeLimit, 1)) == zone);
- zoneCBS = ZonedCBSZoneCBS(zcbs, zone);
-
- RangeInit(&stripe, base, stripeLimit);
- res = CBSDelete(&oldStripe, ZonedCBSFreeCBS(zcbs), &stripe);
-
- /* Optimisation: delete and skip over the rest of the block we
- found in the free CBS, up to the next block that's in a zone CBS
- (or the end). */
- if (res == ResOK && !RangesEqual(&oldStripe, &stripe)) {
- Addr skipLimit = RangeLimit(&oldStripe);
- if (skipLimit > limit)
- skipLimit = limit;
- if (stripeLimit < skipLimit) {
- RangeStruct restOfBlock;
- RangeInit(&restOfBlock, stripeLimit, skipLimit);
- res = CBSDelete(&oldStripe, ZonedCBSFreeCBS(zcbs), &restOfBlock);
- AVER(res == ResOK); /* FIXME: is this right? */
- AVER(RangesEqual(&oldStripe, &restOfBlock));
- base = skipLimit;
- continue;
- }
- }
-
- if (res == ResFAIL) {
- res = CBSDelete(&oldStripe, zoneCBS, &stripe);
- AVER(res != ResFAIL); /* .delete.exists */
- AVER(RangesEqual(&oldStripe, &stripe));
- }
-
- AVER(res == ResOK); /* FIXME: end of range, shouldn't fail? */
-
- base = stripeLimit;
- }
-
- /* Shouldn't be any other kind of failure. */
- AVER(res == ResOK);
- return ResOK;
-}
-
-
-/* ZonedCBSFindFirst, ZonedCBSFindLast -- find a range in the zoned CBS */
-
-
-static Res ZonedCBSFindInZones(Range rangeReturn,
- Range oldRangeReturn,
- ZonedCBS zcbs,
- ZoneSet zones,
- Size size,
- FindDelete findDelete,
- Bool high)
-{
- Index i;
- CBSFindMethod find = high ? CBSFindLast : CBSFindFirst;
-
- /* We could check zoneCBS if size > stripeSize to avoid looking in the
- zoneCBSs, but this probably isn't a win for arena allocation. */
-
- /* TODO: Does "high" really make sense for zone stripes? */
- /* TODO: How do we disable zones anyway? Just make zoneShift = WORD_WIDTH?
- DL points out that if we had two zones, they'd both be blacklisted. */
-
- /* Even though we have no guarantee that zone zero is at the bottom end
- of anything, it makes sense to reverse the search when "high" is set,
- because the point of it (presumably) is to separate memory usage into
- two sets (high and low) that avoid interference. */
-
- /* TODO: Consider masking zones against a ZoneSet of non-empty zone CBSs */
-
- /* TODO: ZONESET_FOR using __builtin_ffsl or similar. */
-
- for (i = 0; i < ZonedCBSNZones(zcbs); ++i) {
- Index zone = high ? ZonedCBSNZones(zcbs) - i - 1 : i;
- if (ZoneSetIsMember(zones, zone) &&
- find(rangeReturn, oldRangeReturn, ZonedCBSZoneCBS(zcbs, zone),
- size, findDelete))
- return ResOK;
- }
-
- return ResRESOURCE;
-}
-
-static Res ZonedCBSFindInFree(Range rangeReturn,
- Range oldRangeReturn,
- ZonedCBS zcbs,
- ZoneSet zones,
- Size size,
- FindDelete findDelete,
- Bool high)
-{
- CBSFindInZonesMethod find = high ? CBSFindLastInZones : CBSFindFirstInZones;
-
- UNUSED(findDelete); /* FIXME: why is this so? */
-
- return find(rangeReturn, oldRangeReturn, ZonedCBSFreeCBS(zcbs), size,
- zcbs->arena, zones);
-}
-
-Res ZonedCBSFind(Range rangeReturn,
- Range oldRangeReturn,
- ZonedCBS zcbs,
- ZoneSet zones,
- Size size,
- FindDelete findDelete,
- Bool high)
-{
- RangeStruct restRange;
- Addr allocLimit, stripeLimit, oldLimit, limit;
- Res res;
-
- AVER(rangeReturn != NULL);
- AVER(oldRangeReturn != NULL);
- AVERT(ZonedCBS, zcbs);
- AVER(size > 0);
- /* ZoneSet arbitrary. TODO: Make a ZoneSetCheck anyway. */
- AVER(BoolCheck(high));
-
- /* TODO: Consider the other FindDelete cases. */
- AVER(findDelete == FindDeleteLOW || findDelete == FindDeleteHIGH);
- AVER((findDelete == FindDeleteHIGH) == high);
-
- res = ZonedCBSFindInZones(rangeReturn, oldRangeReturn,
- zcbs, zones, size,
- findDelete, high);
- if (res != ResRESOURCE)
- return res;
-
- res = ZonedCBSFindInFree(rangeReturn, oldRangeReturn,
- zcbs, zones, size,
- findDelete, high);
- if (res != ResOK)
- return res;
-
- /* TODO: We may have failed to find because the address space is
- fragmented between the zone CBSs and the free CBS. This isn't
- a very important case for the arena, but it does make the Zone CBS
- technically incorrect as a representation of a set of ranges.
- Flush the zone CBSs back to the free CBS? */
-
- /* Add the rest of the zone stripe to the zoneCBS so that subsequent
- allocations in the zone are fast. This is what the ZonedCBS is
- all about! */
-
- allocLimit = RangeLimit(rangeReturn);
- stripeLimit = AddrAlignUp(allocLimit, ArenaStripeSize(zcbs->arena));
- oldLimit = RangeLimit(oldRangeReturn);
- limit = oldLimit < stripeLimit ? oldLimit : stripeLimit;
- RangeInit(&restRange, allocLimit, limit);
- AVER(RangesNest(oldRangeReturn, &restRange));
-
- if (allocLimit < limit) {
- Index zone;
- CBS zoneCBS;
- RangeStruct oldRange;
-
- res = CBSDelete(&oldRange, ZonedCBSFreeCBS(zcbs), &restRange);
- AVER(res == ResOK); /* we should just be bumping up a base */
- zone = AddrZone(zcbs->arena, RangeBase(&restRange));
- zoneCBS = ZonedCBSZoneCBS(zcbs, zone);
-
- res = CBSInsert(&oldRange, zoneCBS, &restRange);
- AVER(res != ResOK || RangesEqual(&oldRange, &restRange)); /* shouldn't coalesce */
- if (res != ResOK) { /* disasterously short on memory, so put it back */
- res = CBSInsert(&oldRange, ZonedCBSFreeCBS(zcbs), &restRange);
- AVER(res == ResOK); /* should just be lowering a base */
- }
- }
-
- return ResOK;
-}
-
-/*
-Res ZonedCBSFindFirst(Range rangeReturn, Range oldRangeReturn,
- ZonedCBS zcbs, ZoneSet zones,
- Size size, FindDelete findDelete)
-{
- return ZonedCBSFind(rangeReturn, oldRangeReturn, zcbs, zones, size,
- findDelete, FALSE);
-}
-
-Bool ZonedCBSFindLast(Range rangeReturn, Range oldRangeReturn,
- ZonedCBS zcbs, ZoneSet zones,
- Size size, FindDelete findDelete)
-{
- return ZonedCBSFind(rangeReturn, oldRangeReturn, zcbs, zones, size,
- findDelete, TRUE);
-}
-*/
-
-
-/* C. COPYRIGHT AND LICENSE
- *
- * Copyright (C) 2014 Ravenbrook Limited .
- * All rights reserved. This is an open source license. Contact
- * Ravenbrook for commercial licensing options.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Redistributions in any form must be accompanied by information on how
- * to obtain complete source code for this software and any accompanying
- * software that uses this software. The source code must either be
- * included in the distribution or be available for no more than the cost
- * of distribution plus a nominal fee, and must be freely redistributable
- * under reasonable conditions. For an executable file, complete source
- * code means the source code for all modules it contains. It does not
- * include source code for modules or files that typically accompany the
- * major components of the operating system on which the executable file
- * runs.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
diff --git a/mps/code/zonedcbs.h b/mps/code/zonedcbs.h
deleted file mode 100644
index bc7e3dc39af..00000000000
--- a/mps/code/zonedcbs.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* zonedcbs.h: ZONE COALESCING BLOCK STRUCTURE INTERFACE
- *
- * $Id$
- * Copyright (c) 2014 Ravenbrook Limited. See end of file for license.
- *
- * A Zone CBS is like a CBS but allows for efficient allocation in zones.
- * Allocation in zones gives control over some parts of an object's address,
- * so that we can later apply fast filters on the critical path.
- * The Zone CBS is mainly used by the arena to allocate blocks to pools.
- */
-
-#ifndef zonedcbs_h
-#define zonedcbs_h
-
-#include "mpm.h"
-#include "range.h"
-
-
-typedef struct ZonedCBSStruct *ZonedCBS;
-
-/* ZoneCBSStruct is in mpmst.h because it is inlined in the ArenaStruct. */
-
-
-/* Basically the same interface as for CBS. See . */
-
-extern Res ZonedCBSInit(ZonedCBS zcbs, Arena arena, Pool blockPool,
- Align alignment);
-extern void ZonedCBSFinish(ZonedCBS zcbs);
-extern Bool ZonedCBSCheck(ZonedCBS zcbs);
-
-extern Res ZonedCBSInsert(Range rangeReturn, ZonedCBS zcbs, Range range);
-extern Res ZonedCBSDelete(Range oldRange, ZonedCBS zcbs, Range range);
-
-extern Res ZonedCBSFind(Range rangeReturn,
- Range oldRangeReturn,
- ZonedCBS zcbs,
- ZoneSet zones,
- Size size,
- FindDelete findDelete,
- Bool high);
-
-/*
-extern Bool ZonedCBSFindFirst(Range rangeReturn, Range oldRangeReturn,
- ZonedCBS zcbs, ZoneSet zones,
- Size size, FindDelete findDelete);
-extern Bool ZonedCBSFindLast(Range rangeReturn, Range oldRangeReturn,
- ZonedCBS zcbs, ZoneSet zones,
- Size size, FindDelete findDelete);
- */
-
-
-#endif /* zonedcbs_h */
-
-/* C. COPYRIGHT AND LICENSE
- *
- * Copyright (C) 2014 Ravenbrook Limited .
- * All rights reserved. This is an open source license. Contact
- * Ravenbrook for commercial licensing options.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Redistributions in any form must be accompanied by information on how
- * to obtain complete source code for this software and any accompanying
- * software that uses this software. The source code must either be
- * included in the distribution or be available for no more than the cost
- * of distribution plus a nominal fee, and must be freely redistributable
- * under reasonable conditions. For an executable file, complete source
- * code means the source code for all modules it contains. It does not
- * include source code for modules or files that typically accompany the
- * major components of the operating system on which the executable file
- * runs.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */