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 ddce428119
commit dc6410d514
2 changed files with 22 additions and 17 deletions

View File

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

View File

@ -667,8 +667,7 @@ ChunkPool::get(JSRuntime *rt)
chunk = Chunk::allocate(rt); chunk = Chunk::allocate(rt);
if (!chunk) if (!chunk)
return nullptr; return nullptr;
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk); JS_ASSERT(chunk->info.numArenasFreeCommitted == 0);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
} }
JS_ASSERT(chunk->unused()); JS_ASSERT(chunk->unused());
JS_ASSERT(!rt->gcChunkSet.has(chunk)); JS_ASSERT(!rt->gcChunkSet.has(chunk));
@ -805,25 +804,20 @@ Chunk::init(JSRuntime *rt)
*/ */
bitmap.clear(); 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. */ /* Initialize the chunk info. */
info.freeArenasHead = &arenas[0].aheader; info.freeArenasHead = nullptr;
info.lastDecommittedArenaOffset = 0; info.lastDecommittedArenaOffset = 0;
info.numArenasFree = ArenasPerChunk; info.numArenasFree = ArenasPerChunk;
info.numArenasFreeCommitted = ArenasPerChunk; info.numArenasFreeCommitted = 0;
info.age = 0; info.age = 0;
info.trailer.runtime = rt; 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. */ /* The rest of info fields are initialized in PickChunk. */
} }
@ -999,6 +993,7 @@ Chunk::releaseArena(ArenaHeader *aheader)
} else { } else {
rt->gcChunkSet.remove(this); rt->gcChunkSet.remove(this);
removeFromAvailableList(); removeFromAvailableList();
decommitAllArenas(rt);
rt->gcChunkPool.put(this); rt->gcChunkPool.put(this);
} }
} }
@ -2622,12 +2617,11 @@ GCHelperThread::threadLoop()
/* OOM stops the background allocation. */ /* OOM stops the background allocation. */
if (!chunk) { if (!chunk) {
#if JS_TRACE_LOGGING #if JS_TRACE_LOGGING
logger->log(TraceLogging::GC_ALLOCATING_STOP); logger->log(TraceLogging::GC_ALLOCATING_STOP);
#endif #endif
break; break;
} }
JS_ASSERT(chunk->info.numArenasFreeCommitted == ArenasPerChunk); JS_ASSERT(chunk->info.numArenasFreeCommitted == 0);
rt->gcNumArenasFreeCommitted += ArenasPerChunk;
rt->gcChunkPool.put(chunk); rt->gcChunkPool.put(chunk);
} while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt)); } while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt));
if (state == ALLOCATING) if (state == ALLOCATING)