From 8ef475634eaa08dbfdeef814d5f78126f1a7506c Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 26 Mar 2014 13:12:45 -0400 Subject: [PATCH] Bug 988326 - Start GC arenas in the decommitted state; r=jonco --- js/src/gc/Heap.h | 11 +++++++++++ js/src/jsgc.cpp | 29 ++++++++++------------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/js/src/gc/Heap.h b/js/src/gc/Heap.h index 286246d024f..47ed8f874c8 100644 --- a/js/src/gc/Heap.h +++ b/js/src/gc/Heap.h @@ -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); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index a2fb50f5c46..58064de65a1 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -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)