<!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>[202402] 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/202402">202402</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-06-23 16:28:50 -0700 (Thu, 23 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>DFGSpeculativeJIT's m_slowPathLambdas should restore the current node field and DFG OSR entry functions should use DeferGCForAWhile instead of DeferGC
https://bugs.webkit.org/show_bug.cgi?id=159064
&lt;rdar://problem/26599119&gt;

Reviewed by Filip Pizlo.

The DFG has a list of m_slowPathLambdas that are code generators it emits
amongst its slow paths. These lambdas, however, did not update the m_currentNode field.
This caused us to use whatever Node happened to be used as the currentNode at the time
we call the slowPathLambda. This means the wrong CallSiteIndex was stored into the call
frame when we made a call. This may lead to a crash if the CallSiteIndex corresponds to
the wrong CodeOrigin. For example, the wrong CodeOrigin could have an InlineCallFrame with
a calleeRecovery that will not be in sync with the current stack state. Trying
to recover that callee will often lead to a crash. The solution is to update
m_currentNode to the DFG::Node* it corresponds to when emitting these slowPathLambdas.

I found this bug because we were inside this bad state when calling an operation
that happened to have a DeferGC. When this DeferGC actually GCed, it would
take a StackTrace, which would lead to a crash because we were updating
ShadowChicken with vm.topCallFrame. It just so happened that the CallSiteIndex
in the call frame in this program corresponded to an InlineCallFrame with a calleeRecover.
However, this CallSiteIndex didn't correspond to the actual state of execution
of the program. I'm adding new options to make reproducing DeferGC related
bugs easier by making DeferGC force a GC according to some probability. To
always have DeferGC force a GC, you can set that probability to 1.

There is a second bug that I discovered after solving the above bug. We were
using DeferGC instead of DeferGCForAWhile in the OSR entry related functions
in the DFG. This would cause us to take a stack trace when the call frame was
in an inconsistent state. For example, the operation would call FTL::prepareOSREntry,
which would replace the DFG CodeBlock in the call frame with the FTL CodeBlock.
However, we wouldn't update the CallSiteIndex to correspond to an FTL CallSiteIndex.
This would lead to a crash when taking a stack trace. The solution is to prevent
stack traces from being taken when the program is in this state by using
DeferGCForAWhie instead of DeferGC.

* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::addSlowPathGenerator):
(JSC::DFG::SpeculativeJIT::runSlowPathGenerators):
* dfg/DFGSpeculativeJIT.h:
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::collectIfNecessaryOrDefer):
(JSC::Heap::collectAccordingToDeferGCProbability):
(JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
(JSC::Heap::markListSet):
* runtime/Options.cpp:
(JSC::recomputeDependentOptions):
(JSC::Options::initialize):
* runtime/Options.h:
* tests/stress/slow-path-generator-updating-current-node-dfg.js: Added.
(foo):
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressslowpathgeneratorupdatingcurrentnodedfgjs">trunk/Source/JavaScriptCore/tests/stress/slow-path-generator-updating-current-node-dfg.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-06-23  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        DFGSpeculativeJIT's m_slowPathLambdas should restore the current node field and DFG OSR entry functions should use DeferGCForAWhile instead of DeferGC
+        https://bugs.webkit.org/show_bug.cgi?id=159064
+        &lt;rdar://problem/26599119&gt;
+
+        Reviewed by Filip Pizlo.
+
+        The DFG has a list of m_slowPathLambdas that are code generators it emits
+        amongst its slow paths. These lambdas, however, did not update the m_currentNode field.
+        This caused us to use whatever Node happened to be used as the currentNode at the time
+        we call the slowPathLambda. This means the wrong CallSiteIndex was stored into the call
+        frame when we made a call. This may lead to a crash if the CallSiteIndex corresponds to
+        the wrong CodeOrigin. For example, the wrong CodeOrigin could have an InlineCallFrame with
+        a calleeRecovery that will not be in sync with the current stack state. Trying
+        to recover that callee will often lead to a crash. The solution is to update
+        m_currentNode to the DFG::Node* it corresponds to when emitting these slowPathLambdas.
+
+        I found this bug because we were inside this bad state when calling an operation
+        that happened to have a DeferGC. When this DeferGC actually GCed, it would
+        take a StackTrace, which would lead to a crash because we were updating
+        ShadowChicken with vm.topCallFrame. It just so happened that the CallSiteIndex
+        in the call frame in this program corresponded to an InlineCallFrame with a calleeRecover.
+        However, this CallSiteIndex didn't correspond to the actual state of execution
+        of the program. I'm adding new options to make reproducing DeferGC related
+        bugs easier by making DeferGC force a GC according to some probability. To
+        always have DeferGC force a GC, you can set that probability to 1.
+
+        There is a second bug that I discovered after solving the above bug. We were
+        using DeferGC instead of DeferGCForAWhile in the OSR entry related functions
+        in the DFG. This would cause us to take a stack trace when the call frame was
+        in an inconsistent state. For example, the operation would call FTL::prepareOSREntry,
+        which would replace the DFG CodeBlock in the call frame with the FTL CodeBlock.
+        However, we wouldn't update the CallSiteIndex to correspond to an FTL CallSiteIndex.
+        This would lead to a crash when taking a stack trace. The solution is to prevent
+        stack traces from being taken when the program is in this state by using
+        DeferGCForAWhie instead of DeferGC.
+
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::addSlowPathGenerator):
+        (JSC::DFG::SpeculativeJIT::runSlowPathGenerators):
+        * dfg/DFGSpeculativeJIT.h:
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::collectIfNecessaryOrDefer):
+        (JSC::Heap::collectAccordingToDeferGCProbability):
+        (JSC::Heap::decrementDeferralDepthAndGCIfNeeded):
+        (JSC::Heap::markListSet):
+        * runtime/Options.cpp:
+        (JSC::recomputeDependentOptions):
+        (JSC::Options::initialize):
+        * runtime/Options.h:
+        * tests/stress/slow-path-generator-updating-current-node-dfg.js: Added.
+        (foo):
+        (bar):
+
</ins><span class="cx"> 2016-06-23  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Failing baseline JIT compilation of a code block and then trying to compile it from OSR from DFG/FTL will corrupt the CodeBlock
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -1818,7 +1818,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><del>-    DeferGC deferGC(vm-&gt;heap);
</del><ins>+    DeferGCForAWhile deferGC(vm-&gt;heap);
</ins><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx">     
</span><span class="cx">     if (codeBlock-&gt;jitType() != JITCode::DFGJIT) {
</span><span class="lines">@@ -2000,7 +2000,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><del>-    DeferGC deferGC(vm-&gt;heap);
</del><ins>+    DeferGCForAWhile deferGC(vm-&gt;heap);
</ins><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx"> 
</span><span class="cx">     if (codeBlock-&gt;jitType() != JITCode::DFGJIT) {
</span><span class="lines">@@ -2034,7 +2034,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><del>-    DeferGC deferGC(vm-&gt;heap);
</del><ins>+    DeferGCForAWhile deferGC(vm-&gt;heap);
</ins><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx"> 
</span><span class="cx">     if (codeBlock-&gt;jitType() != JITCode::DFGJIT) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -362,7 +362,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::addSlowPathGenerator(std::function&lt;void()&gt; lambda)
</span><span class="cx"> {
</span><del>-    m_slowPathLambdas.append(std::make_pair(lambda, m_origin.semantic));
</del><ins>+    m_slowPathLambdas.append(std::make_pair(lambda, m_currentNode));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder&amp; pcToCodeOriginMapBuilder)
</span><span class="lines">@@ -372,7 +372,9 @@
</span><span class="cx">         slowPathGenerator-&gt;generate(this);
</span><span class="cx">     }
</span><span class="cx">     for (auto&amp; generatorPair : m_slowPathLambdas) {
</span><del>-        pcToCodeOriginMapBuilder.appendItem(m_jit.label(), generatorPair.second);
</del><ins>+        Node* currentNode = generatorPair.second;
+        m_currentNode = currentNode;
+        pcToCodeOriginMapBuilder.appendItem(m_jit.label(), currentNode-&gt;origin.semantic);
</ins><span class="cx">         generatorPair.first();
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -2829,7 +2829,7 @@
</span><span class="cx">     MinifiedGraph* m_minifiedGraph;
</span><span class="cx">     
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;SlowPathGenerator&gt;, 8&gt; m_slowPathGenerators;
</span><del>-    Vector&lt;std::pair&lt;std::function&lt;void()&gt;, CodeOrigin&gt;, 8&gt; m_slowPathLambdas;
</del><ins>+    Vector&lt;std::pair&lt;std::function&lt;void()&gt;, Node*&gt;, 8&gt; m_slowPathLambdas;
</ins><span class="cx">     Vector&lt;SilentRegisterSavePlan&gt; m_plans;
</span><span class="cx">     unsigned m_outOfLineStreamIndex { UINT_MAX };
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -170,6 +170,7 @@
</span><span class="cx">     bool shouldCollect();
</span><span class="cx">     JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
</span><span class="cx">     bool collectIfNecessaryOrDefer(); // Returns true if it did collect.
</span><ins>+    void collectAccordingToDeferGCProbability();
</ins><span class="cx"> 
</span><span class="cx">     void completeAllJITPlans();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;Structure.h&quot;
</span><span class="cx"> #include &lt;type_traits&gt;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><ins>+#include &lt;wtf/RandomNumber.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -302,10 +303,28 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void Heap::collectAccordingToDeferGCProbability()
+{
+    if (isDeferred() || !m_isSafeToCollect || m_operationInProgress != NoOperation)
+        return;
+
+    if (randomNumber() &lt; Options::deferGCProbability()) {
+        collect();
+        return;
+    }
+
+    // If our coin flip told us not to GC, we still might GC,
+    // but we GC according to our memory pressure markers.
+    collectIfNecessaryOrDefer();
+}
+
</ins><span class="cx"> inline void Heap::decrementDeferralDepthAndGCIfNeeded()
</span><span class="cx"> {
</span><span class="cx">     decrementDeferralDepth();
</span><del>-    collectIfNecessaryOrDefer();
</del><ins>+    if (UNLIKELY(Options::deferGCShouldCollectWithProbability()))
+        collectAccordingToDeferGCProbability();
+    else
+        collectIfNecessaryOrDefer();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline HashSet&lt;MarkedArgumentBuffer*&gt;&amp; Heap::markListSet()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.cpp (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/runtime/Options.cpp        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -388,6 +388,7 @@
</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><ins>+    ASSERT(Options::deferGCProbability() &gt;= 0.0 &amp;&amp; Options::deferGCProbability() &lt;= 1.0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Options::initialize()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (202401 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2016-06-23 23:22:21 UTC (rev 202401)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -300,6 +300,8 @@
</span><span class="cx">     v(double, minCopiedBlockUtilization, 0.9, 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><ins>+    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;) \
</ins><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="trunkSourceJavaScriptCoretestsstressslowpathgeneratorupdatingcurrentnodedfgjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/slow-path-generator-updating-current-node-dfg.js (0 => 202402)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/slow-path-generator-updating-current-node-dfg.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/slow-path-generator-updating-current-node-dfg.js        2016-06-23 23:28:50 UTC (rev 202402)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+//@ runMiscFTLNoCJITTest(&quot;--deferGCShouldCollectWithProbability=true&quot;, &quot;--deferGCProbability=1.0&quot;)
+
+function foo(a) {
+    return a.push(25);
+}
+
+function bar(a) {
+    for (let i = 0; i &lt; a.length; i++) {
+        a[i] = i;
+    }
+    return foo(a);
+}
+
+noInline(bar);
+
+for (let i = 0; i &lt; 100; i++) {
+    let smallArray = [1, 2, 3, 4, 5];
+    bar(smallArray);
+}
+
+let largeArray = [];
+for (let i = 0; i &lt; 10000000; i++)
+    largeArray.push(i);
+bar(largeArray);
</ins></span></pre>
</div>
</div>

</body>
</html>