Unreviewed, rolling out r190522.
https://bugs.webkit.org/show_bug.cgi?id=149787

Caused a lot of leaks (Requested by ap on #webkit).

Reverted changeset:

"Unreviewed, rolling back in r190450"
https://bugs.webkit.org/show_bug.cgi?id=149727
http://trac.webkit.org/changeset/190522

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@190546 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/heap/CodeBlockSet.cpp b/Source/JavaScriptCore/heap/CodeBlockSet.cpp
index cfeb81f..3eda521 100644
--- a/Source/JavaScriptCore/heap/CodeBlockSet.cpp
+++ b/Source/JavaScriptCore/heap/CodeBlockSet.cpp
@@ -41,11 +41,17 @@
 
 CodeBlockSet::~CodeBlockSet()
 {
+    for (CodeBlock* codeBlock : m_oldCodeBlocks)
+        codeBlock->deref();
+
+    for (CodeBlock* codeBlock : m_newCodeBlocks)
+        codeBlock->deref();
 }
 
-void CodeBlockSet::add(CodeBlock* codeBlock)
+void CodeBlockSet::add(PassRefPtr<CodeBlock> codeBlock)
 {
-    bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry;
+    CodeBlock* block = codeBlock.leakRef();
+    bool isNewEntry = m_newCodeBlocks.add(block).isNewEntry;
     ASSERT_UNUSED(isNewEntry, isNewEntry);
 }
 
@@ -58,26 +64,52 @@
 void CodeBlockSet::clearMarksForFullCollection()
 {
     for (CodeBlock* codeBlock : m_oldCodeBlocks)
-        codeBlock->clearVisitWeaklyHasBeenCalled();
+        codeBlock->clearMarks();
 
     // We promote after we clear marks on the old generation CodeBlocks because
     // none of the young generations CodeBlocks need to be cleared.
     promoteYoungCodeBlocks();
 }
 
+void CodeBlockSet::clearMarksForEdenCollection(const Vector<const JSCell*>& rememberedSet)
+{
+    // This ensures that we will revisit CodeBlocks in remembered Executables even if they were previously marked.
+    for (const JSCell* cell : rememberedSet) {
+        ScriptExecutable* executable = const_cast<ScriptExecutable*>(jsDynamicCast<const ScriptExecutable*>(cell));
+        if (!executable)
+            continue;
+        executable->forEachCodeBlock([this](CodeBlock* codeBlock) {
+            codeBlock->clearMarks();
+            m_remembered.add(codeBlock);
+        });
+    }
+}
+
 void CodeBlockSet::deleteUnmarkedAndUnreferenced(HeapOperation collectionType)
 {
     HashSet<CodeBlock*>& set = collectionType == EdenCollection ? m_newCodeBlocks : m_oldCodeBlocks;
-    Vector<CodeBlock*> unmarked;
-    for (CodeBlock* codeBlock : set) {
-        if (Heap::isMarked(codeBlock))
-            continue;
-        unmarked.append(codeBlock);
-    }
 
-    for (CodeBlock* codeBlock : unmarked) {
-        codeBlock->classInfo()->methodTable.destroy(codeBlock);
-        set.remove(codeBlock);
+    // This needs to be a fixpoint because code blocks that are unmarked may
+    // refer to each other. For example, a DFG code block that is owned by
+    // the GC may refer to an FTL for-entry code block that is also owned by
+    // the GC.
+    Vector<CodeBlock*, 16> toRemove;
+    if (verbose)
+        dataLog("Fixpointing over unmarked, set size = ", set.size(), "...\n");
+    for (;;) {
+        for (CodeBlock* codeBlock : set) {
+            if (!codeBlock->hasOneRef())
+                continue;
+            codeBlock->deref();
+            toRemove.append(codeBlock);
+        }
+        if (verbose)
+            dataLog("    Removing ", toRemove.size(), " blocks.\n");
+        if (toRemove.isEmpty())
+            break;
+        for (CodeBlock* codeBlock : toRemove)
+            set.remove(codeBlock);
+        toRemove.resize(0);
     }
 
     // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.
@@ -87,6 +119,7 @@
 
 void CodeBlockSet::remove(CodeBlock* codeBlock)
 {
+    codeBlock->deref();
     if (m_oldCodeBlocks.contains(codeBlock)) {
         m_oldCodeBlocks.remove(codeBlock);
         return;
@@ -95,13 +128,35 @@
     m_newCodeBlocks.remove(codeBlock);
 }
 
+void CodeBlockSet::traceMarked(SlotVisitor& visitor)
+{
+    if (verbose)
+        dataLog("Tracing ", m_currentlyExecuting.size(), " code blocks.\n");
+
+    // We strongly visit the currently executing set because jettisoning code
+    // is not valuable once it's on the stack. We're past the point where
+    // jettisoning would avoid the cost of OSR exit.
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        codeBlock->visitStrongly(visitor);
+
+    // We strongly visit the remembered set because jettisoning old code during
+    // Eden GC is unsound. There might be an old object with a strong reference
+    // to the code.
+    for (const RefPtr<CodeBlock>& codeBlock : m_remembered)
+        codeBlock->visitStrongly(visitor);
+}
+
 void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap)
 {
     if (verbose)
         dataLog("Remembering ", m_currentlyExecuting.size(), " code blocks.\n");
-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        heap->addToRememberedSet(codeBlock);
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        heap->addToRememberedSet(codeBlock->ownerExecutable());
+
+    // It's safe to clear these RefPtr sets because we won't delete the CodeBlocks
+    // in them until the next GC, and we'll recompute them at that time.
     m_currentlyExecuting.clear();
+    m_remembered.clear();
 }
 
 void CodeBlockSet::dump(PrintStream& out) const
@@ -116,8 +171,8 @@
         out.print(comma, pointerDump(codeBlock));
     out.print("], currentlyExecuting = [");
     comma = CommaPrinter();
-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        out.print(comma, pointerDump(codeBlock));
+    for (const RefPtr<CodeBlock>& codeBlock : m_currentlyExecuting)
+        out.print(comma, pointerDump(codeBlock.get()));
     out.print("]}");
 }