Bug 1034225 - Avoid purging the free lists every iteration in PJS by checking if the current arena is in use. r=terrence

This commit is contained in:
Emanuel Hoogeveen 2014-07-04 04:19:00 -04:00
parent 0f180be3a2
commit 4044473c48
2 changed files with 23 additions and 10 deletions

View File

@ -419,6 +419,7 @@ void
ForkJoinNursery::forwardFromTenured(ForkJoinNurseryCollectionTracer *trc)
{
JSObject *objs[ArenaCellCount];
ArenaLists &lists = tenured_->arenas;
for (size_t k=0; k < FINALIZE_LIMIT; k++) {
AllocKind kind = (AllocKind)k;
if (!IsFJNurseryAllocable(kind))
@ -429,22 +430,21 @@ ForkJoinNursery::forwardFromTenured(ForkJoinNurseryCollectionTracer *trc)
// handled.
JS_ASSERT(kind <= FINALIZE_OBJECT_LAST);
// Clear the free list that we're currently allocating out of.
lists.purge(kind);
// Since we only purge once, there must not currently be any partially
// full arenas left to allocate out of, or we would break out early.
JS_ASSERT(!lists.getArenaAfterCursor(kind));
ArenaIter ai;
ai.init(const_cast<Allocator *>(tenured_), kind);
for (; !ai.done(); ai.next()) {
// Do the walk in two steps to avoid problems resulting from allocating
// into the arena that's being walked: ArenaCellIter is not safe for that.
// It can happen during evacuation.
//
// ArenaCellIterUnderFinalize requires any free list to be flushed into
// its arena, and since we may allocate within traceObject() we must
// purge before each arena scan. This is probably not very expensive,
// it's constant work, and inlined.
//
if (isEvacuating_ && lists.arenaIsInUse(ai.get(), kind))
break;
// Use ArenaCellIterUnderFinalize, not ...UnderGC, because that side-steps
// some assertions in the latter that are wrong for PJS collection.
size_t numObjs = 0;
tenured_->arenas.purge(kind);
for (ArenaCellIterUnderFinalize i(ai.get()); !i.done(); i.next())
objs[numObjs++] = i.get<JSObject>();
for (size_t i=0; i < numObjs; i++)

View File

@ -667,6 +667,10 @@ class ArenaLists
return arenaListsToSweep[thingKind];
}
ArenaHeader *getArenaAfterCursor(AllocKind thingKind) const {
return arenaLists[thingKind].arenaAfterCursor();
}
bool arenaListsAreEmpty() const {
for (size_t i = 0; i != FINALIZE_LIMIT; ++i) {
/*
@ -780,6 +784,15 @@ class ArenaLists
return false;
}
/* Check if |aheader|'s arena is in use. */
bool arenaIsInUse(ArenaHeader *aheader, AllocKind kind) const {
JS_ASSERT(aheader);
const FreeList &freeList = freeLists[kind];
if (freeList.isEmpty())
return false;
return aheader == freeList.arenaHeader();
}
MOZ_ALWAYS_INLINE void *allocateFromFreeList(AllocKind thingKind, size_t thingSize) {
return freeLists[thingKind].allocate(thingSize);
}