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:
parent
9aa93127ba
commit
2fa5f5688d
6 changed files with 52 additions and 11 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue