<!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>[210451] trunk</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/210451">210451</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2017-01-06 12:23:25 -0800 (Fri, 06 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>DeferGC::~DeferGC should be super cheap
https://bugs.webkit.org/show_bug.cgi?id=166626

Reviewed by Saam Barati.
JSTests:


* stress/slow-path-generator-updating-current-node-dfg.js:
* stress/unshift-array-storage.js:

Source/JavaScriptCore:

        
Right now, ~DeferGC requires running the collector's full collectIfNecessaryOrDefer()
hook, which is super big. Normally, that hook would only be called from GC slow paths,
so it ought to be possible to add complex logic to it. It benefits the GC algorithm to
make that code smart, not necessarily fast.

The right thing for it to do is to have ~DeferGC check a boolean to see if
collectIfNecessaryOrDefer() had previously deferred anything, and only call it if that
is true. That's what this patch does.
        
Unfortunately, this means that we lose the collectAccordingToDeferGCProbability mode,
which we used for two tests. Since I could only see two tests that used this mode, I
felt that it was better to enhance the GC than to keep the tests. I filed bug 166627 to
bring back something like that mode.
        
Although this patch does make some paths faster, its real goal is to ensure that bug
165963 can add more logic to collectIfNecessaryOrDefer() without introducing a big
regression. Until then, I wouldn't be surprised if this patch was a progression, but I'm
not betting on it.

* heap/Heap.cpp:
(JSC::Heap::collectIfNecessaryOrDefer):
(JSC::Heap::decrementDeferralDepthAndGCIfNeededSlow):
(JSC::Heap::canCollect): Deleted.
(JSC::Heap::shouldCollectHeuristic): Deleted.
(JSC::Heap::shouldCollect): Deleted.
(JSC::Heap::collectAccordingToDeferGCProbability): Deleted.
(JSC::Heap::decrementDeferralDepthAndGCIfNeeded): Deleted.
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::incrementDeferralDepth):
(JSC::Heap::decrementDeferralDepth):
(JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
(JSC::Heap::mayNeedToStop):
(JSC::Heap::stopIfNecessary):
* runtime/Options.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressslowpathgeneratorupdatingcurrentnodedfgjs">trunk/JSTests/stress/slow-path-generator-updating-current-node-dfg.js</a></li>
<li><a href="#trunkJSTestsstressunshiftarraystoragejs">trunk/JSTests/stress/unshift-array-storage.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionscpp">trunk/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeScriptExecutablecpp">trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/JSTests/ChangeLog        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-12-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DeferGC::~DeferGC should be super cheap
+        https://bugs.webkit.org/show_bug.cgi?id=166626
+
+        Reviewed by Saam Barati.
+
+        * stress/slow-path-generator-updating-current-node-dfg.js:
+        * stress/unshift-array-storage.js:
+
</ins><span class="cx"> 2017-01-04  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: sections with the same name are allowed
</span></span></pre></div>
<a id="trunkJSTestsstressslowpathgeneratorupdatingcurrentnodedfgjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/slow-path-generator-updating-current-node-dfg.js (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/slow-path-generator-updating-current-node-dfg.js        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/JSTests/stress/slow-path-generator-updating-current-node-dfg.js        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,4 +1,7 @@
</span><del>-//@ runFTLNoCJIT(&quot;--deferGCShouldCollectWithProbability=true&quot;, &quot;--deferGCProbability=1.0&quot;)
</del><ins>+// FIXME: Bring back something like the deferGC probability mode.
+// https://bugs.webkit.org/show_bug.cgi?id=166627
+//@ skip
+// //@ runFTLNoCJIT(&quot;--deferGCShouldCollectWithProbability=true&quot;, &quot;--deferGCProbability=1.0&quot;)
</ins><span class="cx"> 
</span><span class="cx"> function foo(a) {
</span><span class="cx">     return a.push(25);
</span></span></pre></div>
<a id="trunkJSTestsstressunshiftarraystoragejs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/unshift-array-storage.js (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/unshift-array-storage.js        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/JSTests/stress/unshift-array-storage.js        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,4 +1,7 @@
</span><del>-//@ runFTLNoCJIT(&quot;--scribbleFreeCells=true&quot;, &quot;--deferGCShouldCollectWithProbability=true&quot;, &quot;--deferGCProbability=1&quot;)
</del><ins>+// FIXME: Bring back something like the deferGC probability mode.
+// https://bugs.webkit.org/show_bug.cgi?id=166627
+//@ skip
+// //@ runFTLNoCJIT(&quot;--scribbleFreeCells=true&quot;, &quot;--deferGCShouldCollectWithProbability=true&quot;, &quot;--deferGCProbability=1&quot;)
</ins><span class="cx"> 
</span><span class="cx"> // Create some array storage.
</span><span class="cx"> var array = [];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2016-12-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DeferGC::~DeferGC should be super cheap
+        https://bugs.webkit.org/show_bug.cgi?id=166626
+
+        Reviewed by Saam Barati.
+        
+        Right now, ~DeferGC requires running the collector's full collectIfNecessaryOrDefer()
+        hook, which is super big. Normally, that hook would only be called from GC slow paths,
+        so it ought to be possible to add complex logic to it. It benefits the GC algorithm to
+        make that code smart, not necessarily fast.
+
+        The right thing for it to do is to have ~DeferGC check a boolean to see if
+        collectIfNecessaryOrDefer() had previously deferred anything, and only call it if that
+        is true. That's what this patch does.
+        
+        Unfortunately, this means that we lose the collectAccordingToDeferGCProbability mode,
+        which we used for two tests. Since I could only see two tests that used this mode, I
+        felt that it was better to enhance the GC than to keep the tests. I filed bug 166627 to
+        bring back something like that mode.
+        
+        Although this patch does make some paths faster, its real goal is to ensure that bug
+        165963 can add more logic to collectIfNecessaryOrDefer() without introducing a big
+        regression. Until then, I wouldn't be surprised if this patch was a progression, but I'm
+        not betting on it.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::collectIfNecessaryOrDefer):
+        (JSC::Heap::decrementDeferralDepthAndGCIfNeededSlow):
+        (JSC::Heap::canCollect): Deleted.
+        (JSC::Heap::shouldCollectHeuristic): Deleted.
+        (JSC::Heap::shouldCollect): Deleted.
+        (JSC::Heap::collectAccordingToDeferGCProbability): Deleted.
+        (JSC::Heap::decrementDeferralDepthAndGCIfNeeded): Deleted.
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::incrementDeferralDepth):
+        (JSC::Heap::decrementDeferralDepth):
+        (JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
+        (JSC::Heap::mayNeedToStop):
+        (JSC::Heap::stopIfNecessary):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2017-01-05  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AutomaticThread timeout shutdown leaves a small window where notify() would think that the thread is still running
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2003-2009, 2011, 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -2023,29 +2023,6 @@
</span><span class="cx">     addToRememberedSet(from);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Heap::canCollect()
-{
-    if (isDeferred())
-        return false;
-    if (!m_isSafeToCollect)
-        return false;
-    if (mutatorState() == MutatorState::HelpingGC)
-        return false;
-    return true;
-}
-
-bool Heap::shouldCollectHeuristic()
-{
-    if (Options::gcMaxHeapSize())
-        return m_bytesAllocatedThisCycle &gt; Options::gcMaxHeapSize();
-    return m_bytesAllocatedThisCycle &gt; m_maxEdenSize;
-}
-
-bool Heap::shouldCollect()
-{
-    return canCollect() &amp;&amp; shouldCollectHeuristic();
-}
-
</del><span class="cx"> bool Heap::isCurrentThreadBusy()
</span><span class="cx"> {
</span><span class="cx">     return mayBeGCThread() || mutatorState() != MutatorState::Running;
</span><span class="lines">@@ -2077,49 +2054,55 @@
</span><span class="cx"> 
</span><span class="cx"> bool Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
</span><span class="cx"> {
</span><del>-    if (!canCollect())
</del><ins>+    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
+
+    if (!m_isSafeToCollect)
</ins><span class="cx">         return false;
</span><ins>+    if (mutatorState() == MutatorState::HelpingGC)
+        return false;
+    if (!Options::useGC())
+        return false;
</ins><span class="cx">     
</span><del>-    if (deferralContext) {
-        deferralContext-&gt;m_shouldGC |=
-            !!(m_worldState.load() &amp; (shouldStopBit | needFinalizeBit | gcDidJITBit));
-    } else
-        stopIfNecessary();
</del><ins>+    if (mayNeedToStop()) {
+        if (deferralContext)
+            deferralContext-&gt;m_shouldGC = true;
+        else if (isDeferred())
+            m_didDeferGCWork = true;
+        else
+            stopIfNecessary();
+    }
</ins><span class="cx">     
</span><del>-    if (!shouldCollectHeuristic())
-        return false;
</del><ins>+    if (UNLIKELY(Options::gcMaxHeapSize())) {
+        if (m_bytesAllocatedThisCycle &lt;= Options::gcMaxHeapSize())
+            return false;
+    } else {
+        if (m_bytesAllocatedThisCycle &lt;= m_maxEdenSize)
+            return false;
+    }
</ins><span class="cx"> 
</span><span class="cx">     if (deferralContext)
</span><span class="cx">         deferralContext-&gt;m_shouldGC = true;
</span><ins>+    else if (isDeferred())
+        m_didDeferGCWork = true;
</ins><span class="cx">     else
</span><span class="cx">         collectAsync();
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::collectAccordingToDeferGCProbability()
</del><ins>+void Heap::decrementDeferralDepthAndGCIfNeededSlow()
</ins><span class="cx"> {
</span><del>-    if (isDeferred() || !m_isSafeToCollect || collectionScope() || mutatorState() == MutatorState::HelpingGC)
</del><ins>+    // Can't do anything if we're still deferred.
+    if (m_deferralDepth)
</ins><span class="cx">         return;
</span><del>-
-    if (randomNumber() &lt; Options::deferGCProbability()) {
-        collectAsync();
-        return;
-    }
-
-    // If our coin flip told us not to GC, we still might GC,
-    // but we GC according to our memory pressure markers.
</del><ins>+    
+    ASSERT(!isDeferred());
+    
+    m_didDeferGCWork = false;
+    // FIXME: Bring back something like the DeferGCProbability mode.
+    // https://bugs.webkit.org/show_bug.cgi?id=166627
</ins><span class="cx">     collectIfNecessaryOrDefer();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::decrementDeferralDepthAndGCIfNeeded()
-{
-    decrementDeferralDepth();
-    if (UNLIKELY(Options::deferGCShouldCollectWithProbability()))
-        collectAccordingToDeferGCProbability();
-    else
-        collectIfNecessaryOrDefer();
-}
-
</del><span class="cx"> void Heap::registerWeakGCMap(void* weakGCMap, std::function&lt;void()&gt; pruningCallback)
</span><span class="cx"> {
</span><span class="cx">     m_weakGCMaps.add(weakGCMap, WTFMove(pruningCallback));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003-2009, 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -185,9 +185,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
</span><span class="cx">     JS_EXPORT_PRIVATE void collectAllGarbage();
</span><span class="cx"> 
</span><del>-    bool canCollect();
</del><span class="cx">     bool shouldCollectHeuristic();
</span><del>-    bool shouldCollect();
</del><span class="cx">     
</span><span class="cx">     // Queue up a collection. Returns immediately. This will not queue a collection if a collection
</span><span class="cx">     // of equal or greater strength exists. Full collections are stronger than std::nullopt collections
</span><span class="lines">@@ -204,7 +202,6 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void collectSync(std::optional&lt;CollectionScope&gt; = std::nullopt);
</span><span class="cx">     
</span><span class="cx">     bool collectIfNecessaryOrDefer(GCDeferralContext* = nullptr); // Returns true if it did collect.
</span><del>-    void collectAccordingToDeferGCProbability();
</del><span class="cx"> 
</span><span class="cx">     void completeAllJITPlans();
</span><span class="cx">     
</span><span class="lines">@@ -268,7 +265,7 @@
</span><span class="cx">     
</span><span class="cx">     void addReference(JSCell*, ArrayBuffer*);
</span><span class="cx">     
</span><del>-    bool isDeferred() const { return !!m_deferralDepth || !Options::useGC(); }
</del><ins>+    bool isDeferred() const { return !!m_deferralDepth; }
</ins><span class="cx"> 
</span><span class="cx">     StructureIDTable&amp; structureIDTable() { return m_structureIDTable; }
</span><span class="cx"> 
</span><span class="lines">@@ -341,6 +338,8 @@
</span><span class="cx">     // already be called for you at the right times.
</span><span class="cx">     void stopIfNecessary();
</span><span class="cx">     
</span><ins>+    bool mayNeedToStop();
+    
</ins><span class="cx">     // This is a much stronger kind of stopping of the collector, and it may require waiting for a
</span><span class="cx">     // while. This is meant to be a legacy API for clients of collectAllGarbage that expect that there
</span><span class="cx">     // is no GC before or after that function call. After calling this, you are free to start GCs
</span><span class="lines">@@ -488,7 +487,8 @@
</span><span class="cx"> 
</span><span class="cx">     void incrementDeferralDepth();
</span><span class="cx">     void decrementDeferralDepth();
</span><del>-    JS_EXPORT_PRIVATE void decrementDeferralDepthAndGCIfNeeded();
</del><ins>+    void decrementDeferralDepthAndGCIfNeeded();
+    JS_EXPORT_PRIVATE void decrementDeferralDepthAndGCIfNeededSlow();
</ins><span class="cx"> 
</span><span class="cx">     size_t threadVisitCount();
</span><span class="cx">     size_t threadBytesVisited();
</span><span class="lines">@@ -579,6 +579,7 @@
</span><span class="cx">     Vector&lt;HeapObserver*&gt; m_observers;
</span><span class="cx"> 
</span><span class="cx">     unsigned m_deferralDepth;
</span><ins>+    bool m_didDeferGCWork { false };
</ins><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;HeapVerifier&gt; m_verifier;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -315,16 +315,47 @@
</span><span class="cx"> 
</span><span class="cx"> inline void Heap::incrementDeferralDepth()
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_deferralDepth &lt; 100); // Sanity check to make sure this doesn't get ridiculous.
</del><ins>+    ASSERT(!mayBeGCThread() || m_collectorBelievesThatTheWorldIsStopped);
</ins><span class="cx">     m_deferralDepth++;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void Heap::decrementDeferralDepth()
</span><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_deferralDepth &gt;= 1);
</del><ins>+    ASSERT(!mayBeGCThread() || m_collectorBelievesThatTheWorldIsStopped);
</ins><span class="cx">     m_deferralDepth--;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void Heap::decrementDeferralDepthAndGCIfNeeded()
+{
+    ASSERT(!mayBeGCThread() || m_collectorBelievesThatTheWorldIsStopped);
+    m_deferralDepth--;
+    
+    if (UNLIKELY(m_didDeferGCWork)) {
+        decrementDeferralDepthAndGCIfNeededSlow();
+        
+        // Here are the possible relationships between m_deferralDepth and m_didDeferGCWork.
+        // Note that prior to the call to decrementDeferralDepthAndGCIfNeededSlow,
+        // m_didDeferGCWork had to have been true. Now it can be either false or true. There is
+        // nothing we can reliably assert.
+        //
+        // Possible arrangements of m_didDeferGCWork and !!m_deferralDepth:
+        //
+        // Both false: We popped out of all DeferGCs and we did whatever work was deferred.
+        //
+        // Only m_didDeferGCWork is true: We stopped for GC and the GC did DeferGC. This is
+        // possible because of how we handle the baseline JIT's worklist. It's also perfectly
+        // safe because it only protects reportExtraMemory. We can just ignore this.
+        //
+        // Only !!m_deferralDepth is true: m_didDeferGCWork had been set spuriously. It is only
+        // cleared by decrementDeferralDepthAndGCIfNeededSlow(). So, if we had deferred work but
+        // then decrementDeferralDepth()'d, then we might have the bit set even if we GC'd since
+        // then.
+        //
+        // Both true: We're in a recursive ~DeferGC. We wanted to do something about the
+        // deferred work, but were unable to.
+    }
+}
+
</ins><span class="cx"> inline HashSet&lt;MarkedArgumentBuffer*&gt;&amp; Heap::markListSet()
</span><span class="cx"> {
</span><span class="cx">     if (!m_markListSet)
</span><span class="lines">@@ -363,11 +394,15 @@
</span><span class="cx">     releaseAccessSlow();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool Heap::mayNeedToStop()
+{
+    return m_worldState.loadRelaxed() != hasAccessBit;
+}
+
</ins><span class="cx"> inline void Heap::stopIfNecessary()
</span><span class="cx"> {
</span><del>-    if (m_worldState.loadRelaxed() == hasAccessBit)
-        return;
-    stopIfNecessarySlow();
</del><ins>+    if (mayNeedToStop())
+        stopIfNecessarySlow();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void Heap::writeBarrierOpaqueRoot(void* root)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2012, 2014-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -418,7 +418,6 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT((static_cast&lt;int64_t&gt;(Options::thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; Options::reoptimizationRetryCounterMax()) &gt; 0);
</span><span class="cx">     ASSERT((static_cast&lt;int64_t&gt;(Options::thresholdForOptimizeAfterLongWarmUp()) &lt;&lt; Options::reoptimizationRetryCounterMax()) &lt;= static_cast&lt;int64_t&gt;(std::numeric_limits&lt;int32_t&gt;::max()));
</span><del>-    ASSERT(Options::deferGCProbability() &gt;= 0.0 &amp;&amp; Options::deferGCProbability() &lt;= 1.0);
</del><span class="cx"> 
</span><span class="cx"> #if ENABLE(LLINT_STATS)
</span><span class="cx">     LLInt::Data::loadStats();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -330,8 +330,6 @@
</span><span class="cx">     v(double, minHeapUtilization, 0.8, Normal, nullptr) \
</span><span class="cx">     v(double, minMarkedBlockUtilization, 0.9, Normal, nullptr) \
</span><span class="cx">     v(unsigned, slowPathAllocsBetweenGCs, 0, Normal, &quot;force a GC on every Nth slow path alloc, where N is specified by this option&quot;) \
</span><del>-    v(bool, deferGCShouldCollectWithProbability, false, Normal, &quot;If true, we perform a collection based on flipping a coin according the probability in the 'deferGCProbability' option when DeferGC is destructed.&quot;) \
-    v(double, deferGCProbability, 1.0, Normal, &quot;Should be a number between 0 and 1. 1 means DeferGC always GCs when it's destructed and GCing is safe. 0.7 means we force GC 70% the time on DeferGC destruction.&quot;) \
</del><span class="cx">     \
</span><span class="cx">     v(double, percentCPUPerMBForFullTimer, 0.0003125, Normal, nullptr) \
</span><span class="cx">     v(double, percentCPUPerMBForEdenTimer, 0.0025, Normal, nullptr) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeScriptExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp (210450 => 210451)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2017-01-06 20:17:48 UTC (rev 210450)
+++ trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2017-01-06 20:23:25 UTC (rev 210451)
</span><span class="lines">@@ -77,8 +77,6 @@
</span><span class="cx"> 
</span><span class="cx"> void ScriptExecutable::installCode(VM&amp; vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)
</span><span class="cx"> {
</span><del>-    ASSERT(vm.heap.isDeferred());
-    
</del><span class="cx">     if (genericCodeBlock)
</span><span class="cx">         CODEBLOCK_LOG_EVENT(genericCodeBlock, &quot;installCode&quot;, ());
</span><span class="cx">     
</span></span></pre>
</div>
</div>

</body>
</html>