2011-09-30 Oliver Hunt <oliver@apple.com>
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
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 <oliver@apple.com>
+
+ 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 <fpizlo@apple.com>
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
void freeBlocks(MarkedBlock*);
void clearMarks();
- void markRoots();
+ void markRoots(bool fullGC);
void markProtectedObjects(HeapRootVisitor&);
void markTempSortVectors(HeapRootVisitor&);
void harvestWeakReferences();
@@ -164,6 +164,7 @@
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 @@
MarkedSpace::MarkedSpace(Heap* heap)
: m_waterMark(0)
+ , m_nurseryWaterMark(0)
, m_highWaterMark(0)
, m_heap(heap)
{
@@ -63,6 +64,7 @@
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 @@
size_t waterMark();
size_t highWaterMark();
+ size_t nurseryWaterMark();
void setHighWaterMark(size_t);
template<typename Functor> typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating.
@@ -91,6 +92,7 @@
FixedArray<SizeClass, preciseCount> m_preciseSizeClasses;
FixedArray<SizeClass, impreciseCount> m_impreciseSizeClasses;
size_t m_waterMark;
+ size_t m_nurseryWaterMark;
size_t m_highWaterMark;
Heap* m_heap;
};
@@ -105,6 +107,11 @@
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 @@
firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList);
if (firstFreeCell)
break;
-
+ m_nurseryWaterMark += block->capacity() - block->size();
m_waterMark += block->capacity();
block->didConsumeFreeList();
}