diff --git a/mps/code/arena.c b/mps/code/arena.c index ce51bcc7e1d..e01adf8dea8 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -333,7 +333,11 @@ void ArenaDestroy(Arena arena) } arena->freeCBS.blockPoolStruct.tractList = NULL; } - + + /* FIXME: Chunks remove their address ranges from the CBS when destroyed, + so this is too early. On the other hand, destroying all the chunks + also destroys the CBS's own memory, which might be scattered across + chunks by this time, so perhaps this can't be torn down neatly. */ CBSFinish(&arena->freeCBS); /* Call class-specific finishing. This will call ArenaFinish. */ @@ -638,6 +642,29 @@ Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit) } +/* ArenaFreeCBSDelete -- remove a block from free CBS, extending pool if necessary + * + * See ArenaFreeCBSInsert. + */ + +void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit) +{ + RangeStruct range; + Res res; + Count nodes; + + RangeInit(&range, base, limit); + nodes = arena->freeCBS.splayTreeSize; + res = CBSDelete(&range, &arena->freeCBS, &range); + + /* This should never fail because it is only used to delete whole chunks + that are represented by single nodes in the CBS tree. */ + /* FIXME: Need a better way of checking this. */ + STATISTIC_STAT(AVER(arena->freeCBS.splayTreeSize == nodes - 1)); + AVER(res == ResOK); +} + + /* arenaAllocFromCBS -- allocate memory using the free CBS * * The free CBS contains all the free address space we have in chunks, diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 8bb9159c82c..566697138f5 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -333,6 +333,7 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size) /* Add the chunk's free address space to the arena's freeCBS, so that we can allocate from it. */ + /* FIXME: Should be in generic ChunkInit so other arenas get the effect. */ { Arena arena = VMArena2Arena(vmArena); Chunk chunk = VMChunk2Chunk(vmChunk); @@ -419,6 +420,11 @@ static void vmChunkDestroy(Chunk chunk) AVER(BTIsSetRange(vmChunk->noSparePages, 0, chunk->pageTablePages)); AVER(BTIsResRange(vmChunk->pageTableMapped, 0, chunk->pageTablePages)); + /* FIXME: Should be in generic ChunkFinish so other arenas get the effect. */ + ArenaFreeCBSDelete(ChunkArena(chunk), + PageIndexBase(chunk, chunk->allocBase), + chunk->limit); + vmChunk->sig = SigInvalid; vm = vmChunk->vm; ChunkFinish(chunk); diff --git a/mps/code/mpm.h b/mps/code/mpm.h index bc7b353be57..c20cad6b969 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -490,6 +490,7 @@ extern Res ArenaDescribe(Arena arena, mps_lib_FILE *stream); extern Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream); extern Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context); extern Res ArenaFreeCBSInsert(Arena arena, Addr base, Addr limit); +extern void ArenaFreeCBSDelete(Arena arena, Addr base, Addr limit); extern Bool GlobalsCheck(Globals arena); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 641143ca561..0814930d2b5 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -614,7 +614,7 @@ typedef struct GlobalsStruct { typedef struct CBSStruct { SplayTreeStruct splayTree; - Count splayTreeSize; + STATISTIC_DECL(Count splayTreeSize); MFSStruct blockPoolStruct; /* FIXME: ref to why this is inlined */ Align alignment; Bool fastFind;