Reduced (but did not eliminate) use of "berzerker GC"
https://bugs.webkit.org/show_bug.cgi?id=89237

Reviewed by Gavin Barraclough.

(PART 1)

This patch turned out to be crashy, so I'm landing the non-crashy bits
first.

This part is pre-requisite refactoring. I didn't actually turn off
"berzerker GC" or turn on incremental shrinking.

* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::removeBlock): Make sure to clear the free list when
we throw away the block we're currently allocating out of. Otherwise, we'll
allocate out of a stale free list.

* heap/MarkedSpace.cpp:
(JSC::Free::Free):
(JSC::Free::operator()):
(JSC::Free::returnValue): Refactored this functor to use a shared helper
function, so we can share our implementation with the incremental sweeper.

Also changed to freeing individual blocks immediately instead of linking
them into a list for later freeing. This makes the programming interface
simpler, and it's slightly more efficient to boot.

(JSC::MarkedSpace::~MarkedSpace): Updated for rename.

(JSC::MarkedSpace::freeBlock):
(JSC::MarkedSpace::freeOrShrinkBlock): New helper functions to share behavior
with the incremental sweeper.

(JSC::MarkedSpace::shrink): Updated for new functor behavior.

* heap/MarkedSpace.h: Statically typed languages are awesome.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@120898 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
index 9552a54..9cac906 100644
--- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp
+++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
@@ -107,8 +107,10 @@
 
 void MarkedAllocator::removeBlock(MarkedBlock* block)
 {
-    if (m_currentBlock == block)
-        m_currentBlock = 0;
+    if (m_currentBlock == block) {
+        m_currentBlock = static_cast<MarkedBlock*>(m_currentBlock->next());
+        m_freeList = MarkedBlock::FreeList();
+    }
     m_blockList.remove(block);
 }
 
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp
index 42247a3..a742d8d 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.cpp
+++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp
@@ -30,38 +30,37 @@
 
 class Structure;
 
-class Take {
+class Free {
 public:
     typedef MarkedBlock* ReturnType;
 
-    enum TakeMode { TakeIfEmpty, TakeAll };
+    enum FreeMode { FreeOrShrink, FreeAll };
 
-    Take(TakeMode, MarkedSpace*);
+    Free(FreeMode, MarkedSpace*);
     void operator()(MarkedBlock*);
     ReturnType returnValue();
     
 private:
-    TakeMode m_takeMode;
+    FreeMode m_freeMode;
     MarkedSpace* m_markedSpace;
     DoublyLinkedList<MarkedBlock> m_blocks;
 };
 
-inline Take::Take(TakeMode takeMode, MarkedSpace* newSpace)
-    : m_takeMode(takeMode)
+inline Free::Free(FreeMode freeMode, MarkedSpace* newSpace)
+    : m_freeMode(freeMode)
     , m_markedSpace(newSpace)
 {
 }
 
-inline void Take::operator()(MarkedBlock* block)
+inline void Free::operator()(MarkedBlock* block)
 {
-    if (m_takeMode == TakeIfEmpty && !block->isEmpty())
-        return;
-    
-    m_markedSpace->allocatorFor(block).removeBlock(block);
-    m_blocks.append(block);
+    if (m_freeMode == FreeOrShrink)
+        m_markedSpace->freeOrShrinkBlock(block);
+    else
+        m_markedSpace->freeBlock(block);
 }
 
-inline Take::ReturnType Take::returnValue()
+inline Free::ReturnType Free::returnValue()
 {
     return m_blocks.head();
 }
@@ -93,9 +92,8 @@
 
 MarkedSpace::~MarkedSpace()
 {
-    // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
-    Take take(Take::TakeAll, this);
-    freeBlocks(forEachBlock(take));
+    Free free(Free::FreeAll, this);
+    forEachBlock(free);
 }
 
 struct LastChanceToFinalize : MarkedBlock::VoidFunctor {
@@ -160,17 +158,21 @@
     return false;
 }
 
-void MarkedSpace::freeBlocks(MarkedBlock* head)
+void MarkedSpace::freeBlock(MarkedBlock* block)
 {
-    MarkedBlock* next;
-    for (MarkedBlock* block = head; block; block = next) {
-        next = static_cast<MarkedBlock*>(block->next());
-        
-        m_blocks.remove(block);
-        block->sweep();
+    allocatorFor(block).removeBlock(block);
+    m_blocks.remove(block);
+    m_heap->blockAllocator().deallocate(MarkedBlock::destroy(block));
+}
 
-        m_heap->blockAllocator().deallocate(MarkedBlock::destroy(block));
+void MarkedSpace::freeOrShrinkBlock(MarkedBlock* block)
+{
+    if (!block->isEmpty()) {
+        block->shrink();
+        return;
     }
+
+    freeBlock(block);
 }
 
 struct Shrink : MarkedBlock::VoidFunctor {
@@ -179,11 +181,8 @@
 
 void MarkedSpace::shrink()
 {
-    // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
-    Take takeIfEmpty(Take::TakeIfEmpty, this);
-    freeBlocks(forEachBlock(takeIfEmpty));
-
-    forEachBlock<Shrink>();
+    Free freeOrShrink(Free::FreeOrShrink, this);
+    forEachBlock(freeOrShrink);
 }
 
 #if ENABLE(GGC)
diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h
index 3f82bac..62d4e5d 100644
--- a/Source/JavaScriptCore/heap/MarkedSpace.h
+++ b/Source/JavaScriptCore/heap/MarkedSpace.h
@@ -98,7 +98,8 @@
     template<typename Functor> typename Functor::ReturnType forEachBlock();
     
     void shrink();
-    void freeBlocks(MarkedBlock* head);
+    void freeBlock(MarkedBlock*);
+    void freeOrShrinkBlock(MarkedBlock*);
 
     void didAddBlock(MarkedBlock*);
     void didConsumeFreeList(MarkedBlock*);