diff --git a/mps/code/arena.c b/mps/code/arena.c index fee56d6378a..e4e7c5e1973 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -164,7 +164,7 @@ Bool ArenaCheck(Arena arena) if (arena->primary != NULL) { CHECKD(Chunk, arena->primary); } - CHECKD_NOSIG(Ring, &arena->chunkRing); + CHECKD_NOSIG(Ring, ArenaChunkRing(arena)); /* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */ CHECKL(TreeCheck(ArenaChunkTree(arena))); /* TODO: check that the chunkRing and chunkTree have identical members */ @@ -225,7 +225,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args) arena->zoned = zoned; arena->primary = NULL; - RingInit(&arena->chunkRing); + RingInit(ArenaChunkRing(arena)); arena->chunkTree = TreeEMPTY; arena->chunkSerial = (Serial)0; @@ -372,7 +372,7 @@ void ArenaFinish(Arena arena) arena->sig = SigInvalid; GlobalsFinish(ArenaGlobals(arena)); LocusFinish(arena); - RingFinish(&arena->chunkRing); + RingFinish(ArenaChunkRing(arena)); AVER(ArenaChunkTree(arena) == TreeEMPTY); } @@ -587,7 +587,7 @@ Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResFAIL; - RING_FOR(node, &arena->chunkRing, next) { + RING_FOR(node, ArenaChunkRing(arena), next) { Chunk chunk = RING_ELT(Chunk, arenaRing, node); res = arenaDescribeTractsInChunk(chunk, stream, depth); if (res != ResOK) @@ -678,7 +678,7 @@ void ArenaChunkInsert(Arena arena, Chunk chunk) { AVER(updatedTree); TreeBalance(&updatedTree); arena->chunkTree = updatedTree; - RingAppend(&arena->chunkRing, &chunk->arenaRing); + RingAppend(ArenaChunkRing(arena), &chunk->arenaRing); arena->reserved += ChunkReserved(chunk); @@ -707,7 +707,7 @@ void ArenaChunkRemoved(Arena arena, Chunk chunk) if (chunk == arena->primary) { /* The primary chunk must be the last chunk to be removed. */ - AVER(RingIsSingle(&arena->chunkRing)); + AVER(RingIsSingle(ArenaChunkRing(arena))); AVER(arena->reserved == 0); arena->primary = NULL; } @@ -762,7 +762,7 @@ static Res arenaAllocPage(Addr *baseReturn, Arena arena, Pool pool) res = arenaAllocPageInChunk(baseReturn, arena->primary, pool); if (res != ResOK) { Ring node, next; - RING_FOR(node, &arena->chunkRing, next) { + RING_FOR(node, ArenaChunkRing(arena), next) { Chunk chunk = RING_ELT(Chunk, arenaRing, node); if (chunk != arena->primary) { res = arenaAllocPageInChunk(baseReturn, chunk, pool); diff --git a/mps/code/gcbench.c b/mps/code/gcbench.c index 2ae97104930..7aa28eb4561 100644 --- a/mps/code/gcbench.c +++ b/mps/code/gcbench.c @@ -248,8 +248,7 @@ static void arena_setup(gcthread_fn_t fn, } MPS_ARGS_END(args); watch(fn, name); mps_arena_park(arena); - printf("%u chunks\n", (unsigned)TreeDebugCount(ArenaChunkTree(arena), - ChunkCompare, ChunkKey)); + printf("%u chunks\n", (unsigned)RingLength(ArenaChunkRing(arena))); mps_pool_destroy(pool); mps_fmt_destroy(format); if (ngen > 0) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index a5ac16b41a2..6f34cd4e020 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -528,6 +528,7 @@ extern Ring GlobalsRememberedSummaryRing(Globals); #define ArenaGreyRing(arena, rank) (&(arena)->greyRing[rank]) #define ArenaPoolRing(arena) (&ArenaGlobals(arena)->poolRing) #define ArenaChunkTree(arena) RVALUE((arena)->chunkTree) +#define ArenaChunkRing(arena) RVALUE(&(arena)->chunkRing) extern Bool ArenaGrainSizeCheck(Size size); #define AddrArenaGrainUp(addr, arena) AddrAlignUp(addr, ArenaGrainSize(arena)) diff --git a/mps/code/ring.c b/mps/code/ring.c index 2f4be5066f2..9ceeecfa232 100644 --- a/mps/code/ring.c +++ b/mps/code/ring.c @@ -65,14 +65,14 @@ Bool RingIsSingle(Ring ring) * See */ -Size RingLength(Ring ring) +Count RingLength(Ring ring) { - Size size = 0; + Count length = 0; Ring node, next; AVERT(Ring, ring); RING_FOR(node, ring, next) - ++ size; - return size; + ++ length; + return length; } diff --git a/mps/code/ring.h b/mps/code/ring.h index 9cb915f4bf4..c7d154dbe5c 100644 --- a/mps/code/ring.h +++ b/mps/code/ring.h @@ -30,7 +30,7 @@ typedef struct RingStruct { /* double-ended queue structure */ extern Bool RingCheck(Ring ring); extern Bool RingCheckSingle(Ring ring); extern Bool RingIsSingle(Ring ring); -extern Size RingLength(Ring ring); +extern Count RingLength(Ring ring); /* .ring.init: See */ extern void (RingInit)(Ring ring); diff --git a/mps/design/ring.txt b/mps/design/ring.txt index c0f4d9adfd4..1935cd02b29 100644 --- a/mps/design/ring.txt +++ b/mps/design/ring.txt @@ -112,7 +112,7 @@ additionally checks that ``ring`` is a singleton (see _`.is.single`: Return ``TRUE`` if ``ring`` is a singleton (see `.def.singleton`_). -``Size RingLength(Ring ring)`` +``Count RingLength(Ring ring)`` _`.length`: Return the number of elements in the ring, not counting ``ring`` itself. This therefore returns 0 for singleton rings, and for diff --git a/mps/test/function/232.c b/mps/test/function/232.c new file mode 100644 index 00000000000..398f1586dd9 --- /dev/null +++ b/mps/test/function/232.c @@ -0,0 +1,59 @@ +/* +TEST_HEADER + id = $Id: //info.ravenbrook.com/project/mps/branch/2015-08-11/compact/test/function/229.c#1 $ + summary = test arena extension and compaction + language = c + link = testlib.o + parameters = SIZE=1024*1024 ITERATIONS=100 +END_HEADER +*/ + +#include "mpm.h" +#include "mpscmvff.h" +#include "testlib.h" + +static void check_chunks(mps_arena_t arena, unsigned expected) +{ + unsigned chunks = (unsigned)RingLength(ArenaChunkRing((Arena)arena)); + asserts(chunks == expected, "expected %u chunks, got %u", expected, chunks); +} + +static void test(void) +{ + mps_arena_t arena; + mps_pool_t pool; + mps_addr_t block[ITERATIONS]; + unsigned i; + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, SIZE); + die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); + } MPS_ARGS_END(args); + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_SPARE, 0); + die(mps_pool_create_k(&pool, arena, mps_class_mvff(), args), "pool_create"); + } MPS_ARGS_END(args); + check_chunks(arena, 1); + + for (i = 0; i < ITERATIONS; ++i) { + die(mps_alloc(&block[i], pool, SIZE), "mps_alloc"); + check_chunks(arena, i + 2); + } + + for (i = ITERATIONS; i > 0; --i) { + mps_free(pool, block[i - 1], SIZE); + mps_arena_collect(arena); /* ensure ArenaCompact called via TraceReclaim */ + check_chunks(arena, i); + } + + mps_pool_destroy(pool); + mps_arena_destroy(arena); +} + +int main(void) +{ + easy_tramp(test); + pass(); + return 0; +} diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing index fde2ca5de8d..b29ffc686cd 100644 --- a/mps/test/testsets/passing +++ b/mps/test/testsets/passing @@ -168,4 +168,5 @@ function/224.c % 225 -- no such test function/226.c function/227.c -function/229.c \ No newline at end of file +function/229.c +function/232.c