Bug 780653 - Make CellIter work during incremental sweeping (r=jonco)

This commit is contained in:
Bill McCloskey 2012-08-09 11:16:33 -07:00
Родитель 7fab12d963
Коммит 194848904e
2 изменённых файлов: 73 добавлений и 34 удалений

Просмотреть файл

@ -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) {
/*

Просмотреть файл

@ -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 <class ArenaOp, class CellOp>
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<Cell *>(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<Cell *>(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 <class ArenaOp, class CellOp>
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) {}