Bug 988326 - Start GC arenas in the decommitted state; r=jonco

This commit is contained in:
Terrence Cole 2014-03-26 13:12:45 -04:00
parent cb76231d6b
commit 8ef475634e
2 changed files with 21 additions and 19 deletions

View File

@ -18,6 +18,7 @@
#include "jsutil.h"
#include "ds/BitArray.h"
#include "gc/Memory.h"
#include "js/HeapAPI.h"
struct JSCompartment;
@ -808,6 +809,16 @@ struct Chunk
static Chunk *allocate(JSRuntime *rt);
void decommitAllArenas(JSRuntime *rt) {
decommittedArenas.clear(true);
MarkPagesUnused(rt, &arenas[0], ArenasPerChunk * ArenaSize);
info.freeArenasHead = nullptr;
info.lastDecommittedArenaOffset = 0;
info.numArenasFree = ArenasPerChunk;
info.numArenasFreeCommitted = 0;
}
/* Must be called with the GC lock taken. */
static inline void release(JSRuntime *rt, Chunk *chunk);
static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead);

View File

@ -667,8 +667,7 @@ ChunkPool::get(JSRuntime *rt)
chunk = Chunk::allocate(rt);
if (!chunk)
return nullptr;
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
JS_ASSERT(chunk->info.numArenasFreeCommitted == 0);
}
JS_ASSERT(chunk->unused());
JS_ASSERT(!rt->gcChunkSet.has(chunk));
@ -805,25 +804,16 @@ Chunk::init(JSRuntime *rt)
*/
bitmap.clear();
/* Initialize the arena tracking bitmap. */
decommittedArenas.clear(false);
/*
* Decommit the arenas. We do this after poisoning so that if the OS does
* not have to recycle the pages, we still get the benefit of poisoning.
*/
decommitAllArenas(rt);
/* Initialize the chunk info. */
info.freeArenasHead = &arenas[0].aheader;
info.lastDecommittedArenaOffset = 0;
info.numArenasFree = ArenasPerChunk;
info.numArenasFreeCommitted = ArenasPerChunk;
info.age = 0;
info.trailer.runtime = rt;
/* Initialize the arena header state. */
for (unsigned i = 0; i < ArenasPerChunk; i++) {
arenas[i].aheader.setAsNotAllocated();
arenas[i].aheader.next = (i + 1 < ArenasPerChunk)
? &arenas[i + 1].aheader
: nullptr;
}
/* The rest of info fields are initialized in PickChunk. */
}
@ -999,6 +989,8 @@ Chunk::releaseArena(ArenaHeader *aheader)
} else {
rt->gcChunkSet.remove(this);
removeFromAvailableList();
JS_ASSERT(info.numArenasFree == ArenasPerChunk);
decommitAllArenas(rt);
rt->gcChunkPool.put(this);
}
}
@ -2622,12 +2614,11 @@ GCHelperThread::threadLoop()
/* OOM stops the background allocation. */
if (!chunk) {
#if JS_TRACE_LOGGING
logger->log(TraceLogging::GC_ALLOCATING_STOP);
logger->log(TraceLogging::GC_ALLOCATING_STOP);
#endif
break;
}
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
JS_ASSERT(chunk->info.numArenasFreeCommitted == 0);
rt->gcChunkPool.put(chunk);
} while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt));
if (state == ALLOCATING)