From fa9733f8d74f28aa5a4e14eb53c4875386993012 Mon Sep 17 00:00:00 2001 From: "oliver@apple.com" Date: Fri, 30 Sep 2011 22:23:33 +0000 Subject: [PATCH] 2011-09-30 Oliver Hunt Need a sensible GGC policy Reviewed by Geoff Garen. This replaces the existing random collection policy with a deterministic policy based on nursery size. * heap/AllocationSpace.cpp: (JSC::AllocationSpace::allocateSlowCase): * heap/Heap.cpp: (JSC::Heap::Heap): (JSC::Heap::markRoots): (JSC::Heap::collect): * heap/Heap.h: * heap/MarkedSpace.cpp: (JSC::MarkedSpace::MarkedSpace): (JSC::MarkedSpace::resetAllocator): * heap/MarkedSpace.h: (JSC::MarkedSpace::nurseryWaterMark): (JSC::MarkedSpace::allocate): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96432 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/JavaScriptCore/ChangeLog | 23 +++++++++++++++++++++++ Source/JavaScriptCore/heap/AllocationSpace.cpp | 8 +++++++- Source/JavaScriptCore/heap/Heap.cpp | 21 ++++++++++++++------- Source/JavaScriptCore/heap/Heap.h | 3 ++- Source/JavaScriptCore/heap/MarkedSpace.cpp | 2 ++ Source/JavaScriptCore/heap/MarkedSpace.h | 9 ++++++++- 6 files changed, 56 insertions(+), 10 deletions(-) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 50ea45c..1c4ea63 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,26 @@ +2011-09-30 Oliver Hunt + + Need a sensible GGC policy + + Reviewed by Geoff Garen. + + This replaces the existing random collection policy + with a deterministic policy based on nursery size. + + * heap/AllocationSpace.cpp: + (JSC::AllocationSpace::allocateSlowCase): + * heap/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::markRoots): + (JSC::Heap::collect): + * heap/Heap.h: + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::resetAllocator): + * heap/MarkedSpace.h: + (JSC::MarkedSpace::nurseryWaterMark): + (JSC::MarkedSpace::allocate): + 2011-09-30 Filip Pizlo DFG 32-bit support for op_call and op_construct causes diff --git a/Source/JavaScriptCore/heap/AllocationSpace.cpp b/Source/JavaScriptCore/heap/AllocationSpace.cpp index 5a1509c..1725de5 100644 --- a/Source/JavaScriptCore/heap/AllocationSpace.cpp +++ b/Source/JavaScriptCore/heap/AllocationSpace.cpp @@ -55,7 +55,13 @@ void* AllocationSpace::allocateSlowCase(MarkedSpace::SizeClass& sizeClass) AllocationEffort allocationEffort; - if (m_markedSpace.waterMark() < m_markedSpace.highWaterMark() || !m_heap->m_isSafeToCollect) + if (( +#if ENABLE(GGC) + m_markedSpace.nurseryWaterMark() < m_heap->m_minBytesPerCycle +#else + m_markedSpace.waterMark() < m_markedSpace.highWaterMark() +#endif + ) || !m_heap->m_isSafeToCollect) allocationEffort = AllocationMustSucceed; else allocationEffort = AllocationCanFail; diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index 37cf164..88f2585 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -214,6 +214,7 @@ inline PassOwnPtr RecordType::returnValue() Heap::Heap(JSGlobalData* globalData, HeapSize heapSize) : m_heapSize(heapSize) , m_minBytesPerCycle(heapSizeForHint(heapSize)) + , m_lastFullGCSize(0) , m_operationInProgress(NoOperation) , m_objectSpace(this) , m_extraCost(0) @@ -453,8 +454,9 @@ void Heap::getConservativeRegisterRoots(HashSet& roots) m_operationInProgress = NoOperation; } -void Heap::markRoots() +void Heap::markRoots(bool fullGC) { + UNUSED_PARAM(fullGC); ASSERT(isValidThreadState(m_globalData)); if (m_operationInProgress != NoOperation) CRASH(); @@ -473,9 +475,7 @@ void Heap::markRoots() m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks(); #if ENABLE(GGC) MarkedBlock::DirtyCellVector dirtyCells; - // Until we have a sensible policy we just random choose to perform - // young generation collections 90% of the time. - if (WTF::randomNumber() > 0.1) + if (!fullGC) m_objectSpace.gatherDirtyCells(dirtyCells); else #endif @@ -486,7 +486,8 @@ void Heap::markRoots() HeapRootVisitor heapRootVisitor(visitor); #if ENABLE(GGC) - for (size_t i = 0; i < dirtyObjectCount; i++) { + size_t dirtyCellCount = dirtyCells.size(); + for (size_t i = 0; i < dirtyCellCount; i++) { heapRootVisitor.visitChildren(dirtyCells[i]); visitor.drain(); } @@ -599,9 +600,12 @@ void Heap::collect(SweepToggle sweepToggle) ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); - + bool fullGC = sweepToggle == DoSweep; + if (!fullGC) + fullGC = (capacity() > 4 * m_lastFullGCSize); canonicalizeCellLivenessData(); - markRoots(); + + markRoots(fullGC); harvestWeakReferences(); m_handleHeap.finalizeWeakHandles(); @@ -621,6 +625,9 @@ void Heap::collect(SweepToggle sweepToggle) // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : // new bytes allocated) proportion, and seems to work well in benchmarks. size_t proportionalBytes = 2 * size(); + if (fullGC) + m_lastFullGCSize = proportionalBytes / 2; + m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); JAVASCRIPTCORE_GC_END(); diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index 2d93bcd..b5c6106 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -144,7 +144,7 @@ namespace JSC { void freeBlocks(MarkedBlock*); void clearMarks(); - void markRoots(); + void markRoots(bool fullGC); void markProtectedObjects(HeapRootVisitor&); void markTempSortVectors(HeapRootVisitor&); void harvestWeakReferences(); @@ -164,6 +164,7 @@ namespace JSC { const HeapSize m_heapSize; const size_t m_minBytesPerCycle; + size_t m_lastFullGCSize; OperationInProgress m_operationInProgress; AllocationSpace m_objectSpace; diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp index 04cb937..acbd8ac 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.cpp +++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp @@ -32,6 +32,7 @@ class Structure; MarkedSpace::MarkedSpace(Heap* heap) : m_waterMark(0) + , m_nurseryWaterMark(0) , m_highWaterMark(0) , m_heap(heap) { @@ -63,6 +64,7 @@ void MarkedSpace::removeBlock(MarkedBlock* block) void MarkedSpace::resetAllocator() { m_waterMark = 0; + m_nurseryWaterMark = 0; for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) sizeClassFor(cellSize).resetAllocator(); diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index 1a4d919..751fe2f 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -72,6 +72,7 @@ public: size_t waterMark(); size_t highWaterMark(); + size_t nurseryWaterMark(); void setHighWaterMark(size_t); template typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating. @@ -91,6 +92,7 @@ private: FixedArray m_preciseSizeClasses; FixedArray m_impreciseSizeClasses; size_t m_waterMark; + size_t m_nurseryWaterMark; size_t m_highWaterMark; Heap* m_heap; }; @@ -105,6 +107,11 @@ inline size_t MarkedSpace::highWaterMark() return m_highWaterMark; } +inline size_t MarkedSpace::nurseryWaterMark() +{ + return m_nurseryWaterMark; +} + inline void MarkedSpace::setHighWaterMark(size_t highWaterMark) { m_highWaterMark = highWaterMark; @@ -126,7 +133,7 @@ inline void* MarkedSpace::allocate(SizeClass& sizeClass) firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); if (firstFreeCell) break; - + m_nurseryWaterMark += block->capacity() - block->size(); m_waterMark += block->capacity(); block->didConsumeFreeList(); } -- 2.7.4