From 194848904e67ba3d2718dba2670da1e2dc011cdd Mon Sep 17 00:00:00 2001 From: Bill McCloskey Date: Thu, 9 Aug 2012 11:16:33 -0700 Subject: [PATCH] Bug 780653 - Make CellIter work during incremental sweeping (r=jonco) --- js/src/jsgc.h | 4 ++ js/src/jsgcinlines.h | 103 +++++++++++++++++++++++++++++-------------- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 6b7c378624f1..c0d8ff2bb6f3 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -252,6 +252,10 @@ struct ArenaLists { return arenaLists[thingKind].head; } + ArenaHeader *getFirstArenaToSweep(AllocKind thingKind) const { + return arenaListsToSweep[thingKind]; + } + bool arenaListsAreEmpty() const { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { /* diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 03f8e9828b17..cbcc0e071906 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -182,44 +182,61 @@ GCPoke(JSRuntime *rt, Value oldval) #endif } -/* - * Invoke ArenaOp and CellOp on every arena and cell in a compartment which - * have the specified thing kind. - */ -template -void -ForEachArenaAndCell(JSCompartment *compartment, AllocKind thingKind, - ArenaOp arenaOp, CellOp cellOp) +class ArenaIter { - size_t thingSize = Arena::thingSize(thingKind); - ArenaHeader *aheader = compartment->arenas.getFirstArena(thingKind); + ArenaHeader *aheader; + ArenaHeader *remainingHeader; - for (; aheader; aheader = aheader->next) { - Arena *arena = aheader->getArena(); - arenaOp(arena); - FreeSpan firstSpan(aheader->getFirstFreeSpan()); - const FreeSpan *span = &firstSpan; + public: + ArenaIter() { + init(); + } - for (uintptr_t thing = arena->thingsStart(thingKind); ; thing += thingSize) { - JS_ASSERT(thing <= arena->thingsEnd()); - if (thing == span->first) { - if (!span->hasNext()) - break; - thing = span->last; - span = span->nextSpan(); - } else { - Cell *t = reinterpret_cast(thing); - cellOp(t); - } + ArenaIter(JSCompartment *comp, AllocKind kind) { + init(comp, kind); + } + + void init() { + aheader = NULL; + remainingHeader = NULL; + } + + void init(ArenaHeader *aheaderArg) { + aheader = aheaderArg; + remainingHeader = NULL; + } + + void init(JSCompartment *comp, AllocKind kind) { + aheader = comp->arenas.getFirstArena(kind); + remainingHeader = comp->arenas.getFirstArenaToSweep(kind); + if (!aheader) { + aheader = remainingHeader; + remainingHeader = NULL; } } -} + + bool done() { + return !aheader; + } + + ArenaHeader *get() { + return aheader; + } + + void next() { + aheader = aheader->next; + if (!aheader) { + aheader = remainingHeader; + remainingHeader = NULL; + } + } +}; class CellIterImpl { size_t firstThingOffset; size_t thingSize; - ArenaHeader *aheader; + ArenaIter aiter; FreeSpan firstSpan; const FreeSpan *span; uintptr_t thing; @@ -239,15 +256,15 @@ class CellIterImpl } void init(ArenaHeader *singleAheader) { - aheader = singleAheader; - initSpan(aheader->compartment, aheader->getAllocKind()); + initSpan(singleAheader->compartment, singleAheader->getAllocKind()); + aiter.init(singleAheader); next(); - aheader = NULL; + aiter.init(); } void init(JSCompartment *comp, AllocKind kind) { initSpan(comp, kind); - aheader = comp->arenas.getFirstArena(kind); + aiter.init(comp, kind); next(); } @@ -275,14 +292,15 @@ class CellIterImpl span = span->nextSpan(); break; } - if (!aheader) { + if (aiter.done()) { cell = NULL; return; } + ArenaHeader *aheader = aiter.get(); firstSpan = aheader->getFirstFreeSpan(); span = &firstSpan; thing = aheader->arenaAddress() | firstThingOffset; - aheader = aheader->next; + aiter.next(); } cell = reinterpret_cast(thing); thing += thingSize; @@ -350,6 +368,23 @@ class CellIter : public CellIterImpl } }; +/* + * Invoke ArenaOp and CellOp on every arena and cell in a compartment which + * have the specified thing kind. + */ +template +void +ForEachArenaAndCell(JSCompartment *compartment, AllocKind thingKind, + ArenaOp arenaOp, CellOp cellOp) +{ + for (ArenaIter aiter(compartment, thingKind); !aiter.done(); aiter.next()) { + ArenaHeader *aheader = aiter.get(); + arenaOp(aheader->getArena()); + for (CellIterUnderGC iter(aheader); !iter.done(); iter.next()) + cellOp(iter.getCell()); + } +} + /* Signatures for ArenaOp and CellOp above. */ inline void EmptyArenaOp(Arena *arena) {}