1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-25 00:07:09 -07:00

New function arenachunktreetraverse ensures that calls to chunkofaddr are reliably detected.

Copied from Perforce
 Change: 186550
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-06-12 20:28:50 +01:00
parent 9aa93127ba
commit 2fa5f5688d
6 changed files with 52 additions and 11 deletions

View file

@ -147,8 +147,7 @@ Bool ArenaCheck(Arena arena)
if (arena->primary != NULL) {
CHECKD(Chunk, arena->primary);
}
/* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */
CHECKL(TreeCheck(ArenaChunkTree(arena)));
/* Can't check chunkTree, it might be bad during ArenaChunkTreeTraverse. */
/* nothing to check for chunkSerial */
CHECKL(LocusCheck(arena));
@ -570,8 +569,7 @@ Res ArenaDescribeTracts(Arena arena, mps_lib_FILE *stream, Count depth)
cl.stream = stream;
cl.res = ResOK;
(void)TreeTraverse(ArenaChunkTree(arena), ChunkCompare, ChunkKey,
arenaDescribeTractsInChunk, &cl, depth);
(void)ArenaChunkTreeTraverse(arena, arenaDescribeTractsInChunk, &cl, depth);
return cl.res;
}
@ -635,6 +633,34 @@ Res ControlDescribe(Arena arena, mps_lib_FILE *stream, Count depth)
}
/* ArenaChunkTreeTraverse -- call visitor for each chunk */
Bool ArenaChunkTreeTraverse(Arena arena, TreeVisitor visitor,
void *closureP, Size closureS)
{
Bool b;
Tree tree;
AVERT(Arena, arena);
AVER(FUNCHECK(visitor));
/* closureP and closureS are arbitrary. */
/* During TreeTraverse, the tree is invalid, so temporarily set
* arena->chunkTree to an invalid value, to ensure that if someone
* calls ChunkOfAddr while we are iterating this results in an
* assertion failure (in checking varieties) or a segfault, rather
* than a silent failure to find the chunk.
*/
tree = ArenaChunkTree(arena);
arena->chunkTree = TreeBAD;
b = TreeTraverse(tree, ChunkCompare, ChunkKey, visitor, closureP, closureS);
arena->chunkTree = tree;
return b;
}
/* ArenaChunkInsert -- insert chunk into arena's chunk tree */
void ArenaChunkInsert(Arena arena, Tree tree) {
@ -681,6 +707,7 @@ static Bool arenaAllocPageInChunk(Tree tree, void *closureP, Size closureS)
AVER(closureP != NULL);
cl = closureP;
AVER(cl->arena == ChunkArena(chunk));
AVER(closureS == UNUSED_SIZE);
UNUSED(closureS);
/* Already searched in arenaAllocPage. */
@ -725,12 +752,12 @@ static Res arenaAllocPage(Addr *baseReturn, Arena arena, Pool pool)
/* Favour the primary chunk, because pages allocated this way aren't
currently freed, and we don't want to prevent chunks being destroyed. */
/* TODO: Consider how the ArenaCBSBlockPool might free pages. */
if (!arenaAllocPageInChunk(&arena->primary->chunkTree, &closure, 0))
if (!arenaAllocPageInChunk(&arena->primary->chunkTree, &closure, UNUSED_SIZE))
goto found;
closure.avoid = arena->primary;
if (!TreeTraverse(ArenaChunkTree(arena), ChunkCompare, ChunkKey,
arenaAllocPageInChunk, &closure, 0))
if (!ArenaChunkTreeTraverse(arena, arenaAllocPageInChunk,
&closure, UNUSED_SIZE))
goto found;
AVER(closure.res != ResOK);

View file

@ -349,6 +349,7 @@ static Bool clientArenaReservedVisitor(Tree tree, void *closureP, Size closureS)
AVERT(Chunk, chunk);
AVER(closureP != 0);
size = closureP;
AVER(closureS == UNUSED_SIZE);
UNUSED(closureS);
*size += ChunkSize(chunk);
@ -361,8 +362,8 @@ static Size ClientArenaReserved(Arena arena)
AVERT(Arena, arena);
(void)TreeTraverse(ArenaChunkTree(arena), ChunkCompare, ChunkKey,
clientArenaReservedVisitor, &size, 0);
(void)ArenaChunkTreeTraverse(arena, clientArenaReservedVisitor,
&size, UNUSED_SIZE);
return size;
}

View file

@ -642,6 +642,7 @@ static Bool vmArenaReservedVisitor(Tree tree, void *closureP, Size closureS)
AVERT(Chunk, chunk);
AVER(closureP != 0);
size = closureP;
AVER(closureS == UNUSED_SIZE);
UNUSED(closureS);
*size += VMReserved(Chunk2VMChunk(chunk)->vm);
@ -655,8 +656,8 @@ static Size VMArenaReserved(Arena arena)
AVERT(Arena, arena);
(void)TreeTraverse(ArenaChunkTree(arena), ChunkCompare, ChunkKey,
vmArenaReservedVisitor, &size, 0);
(void)ArenaChunkTreeTraverse(arena, vmArenaReservedVisitor,
&size, UNUSED_SIZE);
return size;
}

View file

@ -557,6 +557,7 @@ extern Res ArenaStartCollect(Globals globals, int why);
extern Res ArenaCollect(Globals globals, int why);
extern Bool ArenaHasAddr(Arena arena, Addr addr);
extern Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr);
extern Bool ArenaChunkTreeTraverse(Arena arena, TreeVisitor visitor, void *closureP, Size closureS);
extern void ArenaChunkInsert(Arena arena, Tree tree);
extern void ArenaSetEmergency(Arena arena, Bool emergency);

View file

@ -24,6 +24,7 @@ SRCID(tree, "$Id$");
Bool TreeCheck(Tree tree)
{
if (tree != TreeEMPTY) {
CHECKL(tree != TreeBAD);
CHECKL(tree != NULL);
CHECKL(tree->left == TreeEMPTY || tree->left != NULL);
CHECKL(tree->right == TreeEMPTY || tree->right != NULL);

View file

@ -64,6 +64,16 @@ typedef TreeKey (*TreeKeyMethod)(Tree tree);
#define TreeEMPTY ((Tree)0)
/* TreeBAD -- an invalid tree
*
* TreeBAD is a value that's not equal to any tree (not even to
* the empty tree).
*/
#define TreeBAD ((Tree)7)
extern Bool TreeCheck(Tree tree);
extern Bool TreeCheckLeaf(Tree tree);
extern Count TreeDebugCount(Tree tree, TreeCompare compare, TreeKeyMethod key);