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/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();