<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[189516] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/189516">189516</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2015-09-08 17:07:51 -0700 (Tue, 08 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>GC should be able to discover new strong CodeBlock references during marking
https://bugs.webkit.org/show_bug.cgi?id=148981

Reviewed by Mark Lam.

Previously, we required a strong reference to register itself before the
first visit to a CodeBlock. Now, we can discover a strong reference at
any time during the marking phase.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock): Remove the two strong reference state
variables from CodeBlock. Now, a strong reference immediately marks
the CodeBlock and its references at the moment of its discovery, and no
separate state is required.

(JSC::CodeBlock::visitStrongly): New helper function for establishing
a strong reference to a CodeBlock.

(JSC::CodeBlock::visitAggregate): Adopt helper function above.

(JSC::CodeBlock::shouldImmediatelyAssumeLivenessDuringScan): Updated
for state removal.

(JSC::CodeBlock::isKnownToBeLiveDuringGC): Ditto.

(JSC::CodeBlock::stronglyVisitWeakReferences): Be sure to record that
we have proven liveness (by virtue of marking all the references the
proof would check). This is required so that the CodeBlock knows itself
to be live, and it is also an optimization to avoid testing weak references
after we have already visited them.

* bytecode/CodeBlock.h:
(JSC::CodeBlock::clearMarks):
(JSC::CodeBlockSet::mark):
(JSC::CodeBlockSet::clearMarks): Deleted. Updated for state removal.

* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::clearCodeBlockMarks):
(JSC::DFG::Plan::checkLivenessAndVisitChildren):
* dfg/DFGPlan.h: No need to use a CodeBlockSet in order to mark anymore.

* dfg/DFGWorklist.cpp:
(JSC::DFG::Worklist::completeAllPlansForVM):
(JSC::DFG::Worklist::clearCodeBlockMarks):
(JSC::DFG::Worklist::resumeAllThreads):
(JSC::DFG::Worklist::visitWeakReferences):
(JSC::DFG::completeAllPlansForVM):
(JSC::DFG::clearCodeBlockMarks):
* dfg/DFGWorklist.h:
(JSC::DFG::worklistForIndexOrNull): No need to use a CodeBlockSet in order
to mark anymore.

* heap/CodeBlockSet.cpp:
(JSC::CodeBlockSet::clearMarksForFullCollection):
(JSC::CodeBlockSet::clearMarksForEdenCollection):
(JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
(JSC::CodeBlockSet::traceMarked):
(JSC::CodeBlockSet::rememberCurrentlyExecutingCodeBlocks):
(JSC::CodeBlockSet::dump):
* heap/CodeBlockSet.h: Keep the currently executing CodeBlocks in RefPtrs
since we can no longer rely on the m_currentlyExecuting bit to keep them
alive. (A currently executing CodeBlock may not be referenced by its
Executable because it may since have been replaced by another CodeBlock.
This is common in the cases of OSR entry and exit.)

* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::visitCompilerWorklistWeakReferences):
(JSC::Heap::visitWeakHandles): No need to trace the list of CodeBlocks
on the stack in the weak reference fixpoint because we no longer overload
&quot;on the stack&quot; to include CodeBlocks referenced by the compiler.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlanh">trunk/Source/JavaScriptCore/dfg/DFGPlan.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklistcpp">trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklisth">trunk/Source/JavaScriptCore/dfg/DFGWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSetcpp">trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCodeBlockSeth">trunk/Source/JavaScriptCore/heap/CodeBlockSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -1,3 +1,77 @@
</span><ins>+2015-09-08  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        GC should be able to discover new strong CodeBlock references during marking
+        https://bugs.webkit.org/show_bug.cgi?id=148981
+
+        Reviewed by Mark Lam.
+
+        Previously, we required a strong reference to register itself before the
+        first visit to a CodeBlock. Now, we can discover a strong reference at
+        any time during the marking phase.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock): Remove the two strong reference state
+        variables from CodeBlock. Now, a strong reference immediately marks
+        the CodeBlock and its references at the moment of its discovery, and no
+        separate state is required.
+
+        (JSC::CodeBlock::visitStrongly): New helper function for establishing
+        a strong reference to a CodeBlock.
+
+        (JSC::CodeBlock::visitAggregate): Adopt helper function above.
+
+        (JSC::CodeBlock::shouldImmediatelyAssumeLivenessDuringScan): Updated
+        for state removal.
+
+        (JSC::CodeBlock::isKnownToBeLiveDuringGC): Ditto.
+
+        (JSC::CodeBlock::stronglyVisitWeakReferences): Be sure to record that
+        we have proven liveness (by virtue of marking all the references the
+        proof would check). This is required so that the CodeBlock knows itself
+        to be live, and it is also an optimization to avoid testing weak references
+        after we have already visited them.
+
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::clearMarks):
+        (JSC::CodeBlockSet::mark):
+        (JSC::CodeBlockSet::clearMarks): Deleted. Updated for state removal.
+
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::clearCodeBlockMarks):
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren):
+        * dfg/DFGPlan.h: No need to use a CodeBlockSet in order to mark anymore.
+
+        * dfg/DFGWorklist.cpp:
+        (JSC::DFG::Worklist::completeAllPlansForVM):
+        (JSC::DFG::Worklist::clearCodeBlockMarks):
+        (JSC::DFG::Worklist::resumeAllThreads):
+        (JSC::DFG::Worklist::visitWeakReferences):
+        (JSC::DFG::completeAllPlansForVM):
+        (JSC::DFG::clearCodeBlockMarks):
+        * dfg/DFGWorklist.h:
+        (JSC::DFG::worklistForIndexOrNull): No need to use a CodeBlockSet in order
+        to mark anymore.
+
+        * heap/CodeBlockSet.cpp:
+        (JSC::CodeBlockSet::clearMarksForFullCollection):
+        (JSC::CodeBlockSet::clearMarksForEdenCollection):
+        (JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced):
+        (JSC::CodeBlockSet::traceMarked):
+        (JSC::CodeBlockSet::rememberCurrentlyExecutingCodeBlocks):
+        (JSC::CodeBlockSet::dump):
+        * heap/CodeBlockSet.h: Keep the currently executing CodeBlocks in RefPtrs
+        since we can no longer rely on the m_currentlyExecuting bit to keep them
+        alive. (A currently executing CodeBlock may not be referenced by its
+        Executable because it may since have been replaced by another CodeBlock.
+        This is common in the cases of OSR entry and exit.)
+
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::visitCompilerWorklistWeakReferences):
+        (JSC::Heap::visitWeakHandles): No need to trace the list of CodeBlocks
+        on the stack in the weak reference fixpoint because we no longer overload
+        &quot;on the stack&quot; to include CodeBlocks referenced by the compiler.
+
</ins><span class="cx"> 2015-09-08  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Remove unused Heap::getConservativeRegisterRoots().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -1692,8 +1692,6 @@
</span><span class="cx">     , m_lexicalEnvironmentRegister(other.m_lexicalEnvironmentRegister)
</span><span class="cx">     , m_isStrictMode(other.m_isStrictMode)
</span><span class="cx">     , m_needsActivation(other.m_needsActivation)
</span><del>-    , m_mayBeExecuting(false)
-    , m_isStronglyReferenced(false)
</del><span class="cx">     , m_source(other.m_source)
</span><span class="cx">     , m_sourceOffset(other.m_sourceOffset)
</span><span class="cx">     , m_firstLineColumnOffset(other.m_firstLineColumnOffset)
</span><span class="lines">@@ -1752,8 +1750,6 @@
</span><span class="cx">     , m_lexicalEnvironmentRegister(unlinkedCodeBlock-&gt;activationRegister())
</span><span class="cx">     , m_isStrictMode(unlinkedCodeBlock-&gt;isStrictMode())
</span><span class="cx">     , m_needsActivation(unlinkedCodeBlock-&gt;hasActivationRegister() &amp;&amp; unlinkedCodeBlock-&gt;codeType() == FunctionCode)
</span><del>-    , m_mayBeExecuting(false)
-    , m_isStronglyReferenced(false)
</del><span class="cx">     , m_source(sourceProvider)
</span><span class="cx">     , m_sourceOffset(sourceOffset)
</span><span class="cx">     , m_firstLineColumnOffset(firstLineColumnOffset)
</span><span class="lines">@@ -2229,8 +2225,6 @@
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx">     , m_isStrictMode(false)
</span><span class="cx">     , m_needsActivation(false)
</span><del>-    , m_mayBeExecuting(false)
-    , m_isStronglyReferenced(false)
</del><span class="cx">     , m_codeType(FunctionCode)
</span><span class="cx">     , m_osrExitCounter(0)
</span><span class="cx">     , m_optimizationDelayCounter(0)
</span><span class="lines">@@ -2303,6 +2297,15 @@
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CodeBlock::visitStrongly(SlotVisitor&amp; visitor)
+{
+    visitAggregate(visitor);
+
+    stronglyVisitStrongReferences(visitor);
+    stronglyVisitWeakReferences(visitor);
+    propagateTransitions(visitor);
+}
+
</ins><span class="cx"> void CodeBlock::visitAggregate(SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><span class="lines">@@ -2342,10 +2345,7 @@
</span><span class="cx">     m_allTransitionsHaveBeenMarked = false;
</span><span class="cx">     
</span><span class="cx">     if (shouldImmediatelyAssumeLivenessDuringScan()) {
</span><del>-        // This code block is live, so scan all references strongly and return.
-        stronglyVisitStrongReferences(visitor);
-        stronglyVisitWeakReferences(visitor);
-        propagateTransitions(visitor);
</del><ins>+        visitStrongly(visitor);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -2382,9 +2382,6 @@
</span><span class="cx">     if (!JITCode::isOptimizingJIT(jitType()))
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    if (m_isStronglyReferenced)
-        return true;
-
</del><span class="cx">     if (Options::forceDFGCodeBlockLiveness())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="lines">@@ -2402,8 +2399,7 @@
</span><span class="cx">     //   are live.
</span><span class="cx">     // - Code blocks that were running on the stack.
</span><span class="cx">     // - Code blocks that survived the last GC if the current GC is an Eden GC. This is
</span><del>-    //   because either livenessHasBeenProved would have survived as true or
-    //   m_isStronglyReferenced would survive as true.
</del><ins>+    //   because livenessHasBeenProved would have survived as true.
</ins><span class="cx">     // - Code blocks that don't have any dead weak references.
</span><span class="cx">     
</span><span class="cx">     return shouldImmediatelyAssumeLivenessDuringScan()
</span><span class="lines">@@ -2877,6 +2873,8 @@
</span><span class="cx"> 
</span><span class="cx">     for (unsigned i = 0; i &lt; dfgCommon-&gt;weakStructureReferences.size(); ++i)
</span><span class="cx">         visitor.append(&amp;dfgCommon-&gt;weakStructureReferences[i]);
</span><ins>+
+    dfgCommon-&gt;livenessHasBeenProved = true;
</ins><span class="cx"> #endif    
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -156,7 +156,9 @@
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=123677
</span><span class="cx">     CodeBlock* baselineVersion();
</span><span class="cx"> 
</span><ins>+    void clearMarks();
</ins><span class="cx">     void visitAggregate(SlotVisitor&amp;);
</span><ins>+    void visitStrongly(SlotVisitor&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void dumpSource();
</span><span class="cx">     void dumpSource(PrintStream&amp;);
</span><span class="lines">@@ -1000,8 +1002,6 @@
</span><span class="cx">     bool m_isStrictMode;
</span><span class="cx">     bool m_needsActivation;
</span><span class="cx"> 
</span><del>-    bool m_mayBeExecuting;
-    bool m_isStronglyReferenced;
</del><span class="cx">     Atomic&lt;bool&gt; m_visitAggregateHasBeenCalled;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;SourceProvider&gt; m_source;
</span><span class="lines">@@ -1206,14 +1206,9 @@
</span><span class="cx">     return uncheckedR(reg.offset());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void CodeBlockSet::clearMarks(CodeBlock* codeBlock)
</del><ins>+inline void CodeBlock::clearMarks()
</ins><span class="cx"> {
</span><del>-    if (!codeBlock)
-        return;
-
-    codeBlock-&gt;m_mayBeExecuting = false;
-    codeBlock-&gt;m_isStronglyReferenced = false;
-    codeBlock-&gt;m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
</del><ins>+    m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void CodeBlockSet::mark(void* candidateCodeBlock)
</span><span class="lines">@@ -1239,21 +1234,14 @@
</span><span class="cx">     if (!codeBlock)
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (codeBlock-&gt;m_mayBeExecuting)
-        return;
-    
-    codeBlock-&gt;m_mayBeExecuting = true;
-
-    // We might not have cleared the marks for this CodeBlock, but we need to visit it.
</del><ins>+    // Force GC to visit all CodeBlocks on the stack, including old CodeBlocks
+    // that have not executed a barrier. This is overkill, but we have always
+    // done this, and it might help us recover gracefully if we forget to execute
+    // a barrier when a CodeBlock needs it.
</ins><span class="cx">     codeBlock-&gt;m_visitAggregateHasBeenCalled.store(false, std::memory_order_relaxed);
</span><span class="cx"> 
</span><del>-    // For simplicity, we don't attempt to jettison code blocks during GC if
-    // they are executing. Instead we strongly mark their weak references to
-    // allow them to continue to execute soundly.
-    codeBlock-&gt;m_isStronglyReferenced = true;
-
</del><span class="cx"> #if ENABLE(GGC)
</span><del>-    m_currentlyExecuting.append(codeBlock);
</del><ins>+    m_currentlyExecuting.add(codeBlock);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -595,25 +595,31 @@
</span><span class="cx">     return CompilationKey(codeBlock-&gt;alternative(), mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::clearCodeBlockMarks(CodeBlockSet&amp; codeBlocks)
</del><ins>+void Plan::clearCodeBlockMarks()
</ins><span class="cx"> {
</span><del>-    codeBlocks.clearMarks(codeBlock.get());
-    codeBlocks.clearMarks(codeBlock-&gt;alternative());
-    codeBlocks.clearMarks(profiledDFGCodeBlock.get());
</del><ins>+    // Compilation writes lots of values to a CodeBlock without performing
+    // an explicit barrier. So, we need to be pessimistic and assume that
+    // all our CodeBlocks must be visited during GC.
+
+    codeBlock-&gt;clearMarks();
+    codeBlock-&gt;alternative()-&gt;clearMarks();
+    if (profiledDFGCodeBlock)
+        profiledDFGCodeBlock-&gt;clearMarks();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::checkLivenessAndVisitChildren(SlotVisitor&amp; visitor, CodeBlockSet&amp; codeBlocks)
</del><ins>+void Plan::checkLivenessAndVisitChildren(SlotVisitor&amp; visitor)
</ins><span class="cx"> {
</span><span class="cx">     if (!isKnownToBeLiveDuringGC())
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     for (unsigned i = mustHandleValues.size(); i--;)
</span><span class="cx">         visitor.appendUnbarrieredValue(&amp;mustHandleValues[i]);
</span><del>-    
-    codeBlocks.mark(codeBlock.get());
-    codeBlocks.mark(codeBlock-&gt;alternative());
-    codeBlocks.mark(profiledDFGCodeBlock.get());
-    
</del><ins>+
+    codeBlock-&gt;visitStrongly(visitor);
+    codeBlock-&gt;alternative()-&gt;visitStrongly(visitor);
+    if (profiledDFGCodeBlock)
+        profiledDFGCodeBlock-&gt;visitStrongly(visitor);
+
</ins><span class="cx">     weakReferences.visitChildren(visitor);
</span><span class="cx">     transitions.visitChildren(visitor);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.h (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.h        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.h        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -44,7 +44,6 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CodeBlock;
</span><del>-class CodeBlockSet;
</del><span class="cx"> class SlotVisitor;
</span><span class="cx"> 
</span><span class="cx"> namespace DFG {
</span><span class="lines">@@ -72,8 +71,8 @@
</span><span class="cx">     
</span><span class="cx">     CompilationKey key();
</span><span class="cx">     
</span><del>-    void clearCodeBlockMarks(CodeBlockSet&amp;);
-    void checkLivenessAndVisitChildren(SlotVisitor&amp;, CodeBlockSet&amp;);
</del><ins>+    void clearCodeBlockMarks();
+    void checkLivenessAndVisitChildren(SlotVisitor&amp;);
</ins><span class="cx">     bool isKnownToBeLiveDuringGC();
</span><span class="cx">     void cancel();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklistcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -207,14 +207,14 @@
</span><span class="cx">     completeAllReadyPlansForVM(vm);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Worklist::clearCodeBlockMarks(VM&amp; vm, CodeBlockSet&amp; codeBlocks)
</del><ins>+void Worklist::clearCodeBlockMarks(VM&amp; vm)
</ins><span class="cx"> {
</span><span class="cx">     LockHolder locker(m_lock);
</span><span class="cx">     for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
</span><span class="cx">         Plan* plan = iter-&gt;value.get();
</span><span class="cx">         if (&amp;plan-&gt;vm != &amp;vm)
</span><span class="cx">             continue;
</span><del>-        plan-&gt;clearCodeBlockMarks(codeBlocks);
</del><ins>+        plan-&gt;clearCodeBlockMarks();
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -232,7 +232,7 @@
</span><span class="cx">     m_suspensionLock.unlock();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Worklist::visitWeakReferences(SlotVisitor&amp; visitor, CodeBlockSet&amp; codeBlocks)
</del><ins>+void Worklist::visitWeakReferences(SlotVisitor&amp; visitor)
</ins><span class="cx"> {
</span><span class="cx">     VM* vm = visitor.heap()-&gt;vm();
</span><span class="cx">     {
</span><span class="lines">@@ -241,7 +241,7 @@
</span><span class="cx">             Plan* plan = iter-&gt;value.get();
</span><span class="cx">             if (&amp;plan-&gt;vm != vm)
</span><span class="cx">                 continue;
</span><del>-            plan-&gt;checkLivenessAndVisitChildren(visitor, codeBlocks);
</del><ins>+            plan-&gt;checkLivenessAndVisitChildren(visitor);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     // This loop doesn't need locking because:
</span><span class="lines">@@ -467,11 +467,11 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void clearCodeBlockMarks(VM&amp; vm, CodeBlockSet&amp; codeBlockSet)
</del><ins>+void clearCodeBlockMarks(VM&amp; vm)
</ins><span class="cx"> {
</span><span class="cx">     for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><span class="cx">         if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</span><del>-            worklist-&gt;clearCodeBlockMarks(vm, codeBlockSet);
</del><ins>+            worklist-&gt;clearCodeBlockMarks(vm);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.h (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -38,7 +38,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-class CodeBlockSet;
</del><span class="cx"> class SlotVisitor;
</span><span class="cx"> 
</span><span class="cx"> namespace DFG {
</span><span class="lines">@@ -58,7 +57,7 @@
</span><span class="cx">     // worklist-&gt;completeAllReadyPlansForVM(vm);
</span><span class="cx">     void completeAllPlansForVM(VM&amp;);
</span><span class="cx"> 
</span><del>-    void clearCodeBlockMarks(VM&amp;, CodeBlockSet&amp;);
</del><ins>+    void clearCodeBlockMarks(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void waitUntilAllPlansForVMAreReady(VM&amp;);
</span><span class="cx">     State completeAllReadyPlansForVM(VM&amp;, CompilationKey = CompilationKey());
</span><span class="lines">@@ -74,7 +73,7 @@
</span><span class="cx">     bool isActiveForVM(VM&amp;) const;
</span><span class="cx">     
</span><span class="cx">     // Only called on the main thread after suspending all threads.
</span><del>-    void visitWeakReferences(SlotVisitor&amp;, CodeBlockSet&amp;);
</del><ins>+    void visitWeakReferences(SlotVisitor&amp;);
</ins><span class="cx">     void removeDeadPlans(VM&amp;);
</span><span class="cx">     
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="lines">@@ -142,7 +141,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void completeAllPlansForVM(VM&amp;);
</span><del>-void clearCodeBlockMarks(VM&amp;, CodeBlockSet&amp;);
</del><ins>+void clearCodeBlockMarks(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx"> void CodeBlockSet::clearMarksForFullCollection()
</span><span class="cx"> {
</span><span class="cx">     for (CodeBlock* codeBlock : m_oldCodeBlocks)
</span><del>-        clearMarks(codeBlock);
</del><ins>+        codeBlock-&gt;clearMarks();
</ins><span class="cx"> 
</span><span class="cx">     // We promote after we clear marks on the old generation CodeBlocks because
</span><span class="cx">     // none of the young generations CodeBlocks need to be cleared.
</span><span class="lines">@@ -79,7 +79,7 @@
</span><span class="cx">         if (!executable)
</span><span class="cx">             continue;
</span><span class="cx">         executable-&gt;forEachCodeBlock([this](CodeBlock* codeBlock) {
</span><del>-            clearMarks(codeBlock);
</del><ins>+            codeBlock-&gt;clearMarks();
</ins><span class="cx">         });
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -99,8 +99,6 @@
</span><span class="cx">         for (CodeBlock* codeBlock : set) {
</span><span class="cx">             if (!codeBlock-&gt;hasOneRef())
</span><span class="cx">                 continue;
</span><del>-            if (codeBlock-&gt;m_isStronglyReferenced)
-                continue;
</del><span class="cx">             codeBlock-&gt;deref();
</span><span class="cx">             toRemove.append(codeBlock);
</span><span class="cx">         }
</span><span class="lines">@@ -133,11 +131,8 @@
</span><span class="cx"> {
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Tracing &quot;, m_currentlyExecuting.size(), &quot; code blocks.\n&quot;);
</span><del>-    for (CodeBlock* codeBlock : m_currentlyExecuting) {
-        ASSERT(codeBlock-&gt;m_mayBeExecuting);
-        ASSERT(codeBlock-&gt;m_isStronglyReferenced);
-        codeBlock-&gt;visitAggregate(visitor);
-    }
</del><ins>+    for (const RefPtr&lt;CodeBlock&gt;&amp; codeBlock : m_currentlyExecuting)
+        codeBlock-&gt;visitStrongly(visitor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlockSet::rememberCurrentlyExecutingCodeBlocks(Heap* heap)
</span><span class="lines">@@ -145,11 +140,12 @@
</span><span class="cx"> #if ENABLE(GGC)
</span><span class="cx">     if (verbose)
</span><span class="cx">         dataLog(&quot;Remembering &quot;, m_currentlyExecuting.size(), &quot; code blocks.\n&quot;);
</span><del>-    for (CodeBlock* codeBlock : m_currentlyExecuting) {
-        ASSERT(codeBlock-&gt;m_mayBeExecuting);
-        ASSERT(codeBlock-&gt;m_isStronglyReferenced);
</del><ins>+    for (const RefPtr&lt;CodeBlock&gt;&amp; codeBlock : m_currentlyExecuting)
</ins><span class="cx">         heap-&gt;addToRememberedSet(codeBlock-&gt;ownerExecutable());
</span><del>-    }
</del><ins>+
+    // It's safe to clear this RefPtr set because we won't delete the CodeBlocks
+    // in it until the next GC, and we'll recompute m_currentlyExecuting at that
+    // time.
</ins><span class="cx">     m_currentlyExecuting.clear();
</span><span class="cx"> #else
</span><span class="cx">     UNUSED_PARAM(heap);
</span><span class="lines">@@ -168,8 +164,8 @@
</span><span class="cx">         out.print(comma, pointerDump(codeBlock));
</span><span class="cx">     out.print(&quot;], currentlyExecuting = [&quot;);
</span><span class="cx">     comma = CommaPrinter();
</span><del>-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        out.print(comma, pointerDump(codeBlock));
</del><ins>+    for (const RefPtr&lt;CodeBlock&gt;&amp; codeBlock : m_currentlyExecuting)
+        out.print(comma, pointerDump(codeBlock.get()));
</ins><span class="cx">     out.print(&quot;]}&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCodeBlockSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CodeBlockSet.h (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CodeBlockSet.h        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/heap/CodeBlockSet.h        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -61,8 +61,6 @@
</span><span class="cx">     // Clear all mark bits for all CodeBlocks.
</span><span class="cx">     void clearMarksForFullCollection();
</span><span class="cx"> 
</span><del>-    void clearMarks(CodeBlock*);
-
</del><span class="cx">     // Mark a pointer that may be a CodeBlock that belongs to the set of DFG
</span><span class="cx">     // blocks. This is defined in CodeBlock.h.
</span><span class="cx">     void mark(CodeBlock* candidateCodeBlock);
</span><span class="lines">@@ -111,7 +109,7 @@
</span><span class="cx">     // and all, but that seemed like overkill.
</span><span class="cx">     HashSet&lt;CodeBlock*&gt; m_oldCodeBlocks;
</span><span class="cx">     HashSet&lt;CodeBlock*&gt; m_newCodeBlocks;
</span><del>-    Vector&lt;CodeBlock*&gt; m_currentlyExecuting;
</del><ins>+    HashSet&lt;RefPtr&lt;CodeBlock&gt;&gt; m_currentlyExecuting;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (189515 => 189516)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-08 23:10:57 UTC (rev 189515)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-09 00:07:51 UTC (rev 189516)
</span><span class="lines">@@ -525,7 +525,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    DFG::clearCodeBlockMarks(*m_vm, m_codeBlocks);
</del><ins>+    DFG::clearCodeBlockMarks(*m_vm);
</ins><span class="cx"> #endif
</span><span class="cx">     if (m_operationInProgress == EdenCollection)
</span><span class="cx">         m_codeBlocks.clearMarksForEdenCollection(rememberedSet);
</span><span class="lines">@@ -661,7 +661,7 @@
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     for (auto worklist : m_suspendedCompilerWorklists)
</span><del>-        worklist-&gt;visitWeakReferences(m_slotVisitor, m_codeBlocks);
</del><ins>+        worklist-&gt;visitWeakReferences(m_slotVisitor);
</ins><span class="cx"> 
</span><span class="cx">     if (Options::logGC() == GCLogging::Verbose)
</span><span class="cx">         dataLog(&quot;DFG Worklists:\n&quot;, m_slotVisitor);
</span><span class="lines">@@ -768,7 +768,6 @@
</span><span class="cx">         m_objectSpace.visitWeakSets(visitor);
</span><span class="cx">         harvestWeakReferences();
</span><span class="cx">         visitCompilerWorklistWeakReferences();
</span><del>-        m_codeBlocks.traceMarked(m_slotVisitor); // New &quot;executing&quot; code blocks may be discovered.
</del><span class="cx">         if (m_slotVisitor.isEmpty())
</span><span class="cx">             break;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>