<!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>[203356] 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/203356">203356</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-07-18 11:55:31 -0700 (Mon, 18 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>OSR entry into DFG has problems with lexical scoping
https://bugs.webkit.org/show_bug.cgi?id=159687

Reviewed by Saam Barati.
Source/JavaScriptCore:

        
What a fun bug! It turns out that uses of lexical scoping, like &quot;let&quot;, may sometimes cause us
to not be able to OSR enter into a loop from baseline to DFG. The bug is in a mitigation for
a different bug, which in turn had a mitigation for yet another bug, so the story here is a
long one.
        
DFG OSR entry has long had a mitigation for the following bug: the DFG bytecode parser may
choose to make us always OSR exit at some instruction if it thinks that it doesn't have
enough profiling for that instruction. We will do this if some kinds of put_by_id only
execute once, for example. This causes problems for loopy benchmarks like this:
        
    put_by_id(something crazy);
    for (var i = 0; i &lt; bigNumber; ++i) simpleMath;
        
In this case, the put_by_id will have only executed once, and since it did something crazy
that one time, the bytecode parser will replace it with ForceOSRExit.
        
This creates an OSR entry bug: DFG CFA will then prove that the loop is unreachable, and will
tell OSR entry that it's impossible to enter into that loop.
        
We mitigated this bug a long time ago by recording mustHandleValues for loops at which we
want to enter. We inject these values into DFG CFA and we force CFA to recognize that the
loop is reachable even if CFA wanted to prove that it wasn't.
        
But this leads to another bug: we need to scrape the values from the stack inside
operationOptimize() and then we need to reason about them in the compiler. Some of those
values may be garbage, which would cause pandemonium inside the compiler. We also mitigated
this bug, by only recording the &quot;vars&quot;, since those are guaranteed to be reset by op_enter.
        
And that's where the lexical scoping bug happens: &quot;let&quot; bound variables aren't part of the
&quot;vars&quot;. DFG will see that they are live, but mustHandleValues will not have anything for
those variables, so CFA will prove that the values are Bottom. Then OSR entry will always
fail because no value is ever a subset of Bottom.
        
The first part of the fix is to ensure that mustHandleValues record all of the values on the
stack (i.e. within m_numCalleeLocals, rather than just m_numVars). But this creates a second
problem: we may record garbage. This patch includes a better fix for the garbage: before
touching mustHandleValues we run the bytecode liveness analysis and clear any values that are
not live. This ensures that we clear the garbage.
        
This is an enormous speed-up on microbenchmarks that use lexical scoping and have some crazy
put_by_id in the lead-up to the hot loop.

* dfg/DFGCFAPhase.cpp:
(JSC::DFG::CFAPhase::run):
* dfg/DFGOSREntry.cpp:
(JSC::DFG::prepareOSREntry):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
(JSC::DFG::Plan::checkLivenessAndVisitChildren):
(JSC::DFG::Plan::cancel):
(JSC::DFG::Plan::cleanMustHandleValuesIfNecessary):
* dfg/DFGPlan.h:
(JSC::DFG::Plan::canTierUpAndOSREnter):
* jit/JITOperations.cpp:

LayoutTests:


* js/regress/script-tests/strict-osr-entry.js: Added.
(let.o.apply_):
* js/regress/strict-osr-entry-expected.txt: Added.
* js/regress/strict-osr-entry.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCFAPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSREntrycpp">trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp</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="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressscripttestsstrictosrentryjs">trunk/LayoutTests/js/regress/script-tests/strict-osr-entry.js</a></li>
<li><a href="#trunkLayoutTestsjsregressstrictosrentryexpectedtxt">trunk/LayoutTests/js/regress/strict-osr-entry-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressstrictosrentryhtml">trunk/LayoutTests/js/regress/strict-osr-entry.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/LayoutTests/ChangeLog        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-07-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        OSR entry into DFG has problems with lexical scoping
+        https://bugs.webkit.org/show_bug.cgi?id=159687
+
+        Reviewed by Saam Barati.
+
+        * js/regress/script-tests/strict-osr-entry.js: Added.
+        (let.o.apply_):
+        * js/regress/strict-osr-entry-expected.txt: Added.
+        * js/regress/strict-osr-entry.html: Added.
+
</ins><span class="cx"> 2016-07-18  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Streams API] ReadableStream should throw a RangeError in case of NaN highWaterMark
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsstrictosrentryjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/strict-osr-entry.js (0 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/strict-osr-entry.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/strict-osr-entry.js        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+&quot;use strict&quot;;
+
+(function() {
+    let o = {
+        apply_(a, b) {
+            return a + b;
+        }
+    };
+    
+    let result = 0;
+    for (let i = 0; i &lt; 10000000; ++i)
+        result = o.apply_(result, 1);
+    
+    if (result != 10000000)
+        throw new &quot;Bad result: &quot; + result;
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressstrictosrentryexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/strict-osr-entry-expected.txt (0 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/strict-osr-entry-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/strict-osr-entry-expected.txt        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/strict-osr-entry
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressstrictosrentryhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/strict-osr-entry.html (0 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/strict-osr-entry.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/strict-osr-entry.html        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/strict-osr-entry.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -1,3 +1,65 @@
</span><ins>+2016-07-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        OSR entry into DFG has problems with lexical scoping
+        https://bugs.webkit.org/show_bug.cgi?id=159687
+
+        Reviewed by Saam Barati.
+        
+        What a fun bug! It turns out that uses of lexical scoping, like &quot;let&quot;, may sometimes cause us
+        to not be able to OSR enter into a loop from baseline to DFG. The bug is in a mitigation for
+        a different bug, which in turn had a mitigation for yet another bug, so the story here is a
+        long one.
+        
+        DFG OSR entry has long had a mitigation for the following bug: the DFG bytecode parser may
+        choose to make us always OSR exit at some instruction if it thinks that it doesn't have
+        enough profiling for that instruction. We will do this if some kinds of put_by_id only
+        execute once, for example. This causes problems for loopy benchmarks like this:
+        
+            put_by_id(something crazy);
+            for (var i = 0; i &lt; bigNumber; ++i) simpleMath;
+        
+        In this case, the put_by_id will have only executed once, and since it did something crazy
+        that one time, the bytecode parser will replace it with ForceOSRExit.
+        
+        This creates an OSR entry bug: DFG CFA will then prove that the loop is unreachable, and will
+        tell OSR entry that it's impossible to enter into that loop.
+        
+        We mitigated this bug a long time ago by recording mustHandleValues for loops at which we
+        want to enter. We inject these values into DFG CFA and we force CFA to recognize that the
+        loop is reachable even if CFA wanted to prove that it wasn't.
+        
+        But this leads to another bug: we need to scrape the values from the stack inside
+        operationOptimize() and then we need to reason about them in the compiler. Some of those
+        values may be garbage, which would cause pandemonium inside the compiler. We also mitigated
+        this bug, by only recording the &quot;vars&quot;, since those are guaranteed to be reset by op_enter.
+        
+        And that's where the lexical scoping bug happens: &quot;let&quot; bound variables aren't part of the
+        &quot;vars&quot;. DFG will see that they are live, but mustHandleValues will not have anything for
+        those variables, so CFA will prove that the values are Bottom. Then OSR entry will always
+        fail because no value is ever a subset of Bottom.
+        
+        The first part of the fix is to ensure that mustHandleValues record all of the values on the
+        stack (i.e. within m_numCalleeLocals, rather than just m_numVars). But this creates a second
+        problem: we may record garbage. This patch includes a better fix for the garbage: before
+        touching mustHandleValues we run the bytecode liveness analysis and clear any values that are
+        not live. This ensures that we clear the garbage.
+        
+        This is an enormous speed-up on microbenchmarks that use lexical scoping and have some crazy
+        put_by_id in the lead-up to the hot loop.
+
+        * dfg/DFGCFAPhase.cpp:
+        (JSC::DFG::CFAPhase::run):
+        * dfg/DFGOSREntry.cpp:
+        (JSC::DFG::prepareOSREntry):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren):
+        (JSC::DFG::Plan::cancel):
+        (JSC::DFG::Plan::cleanMustHandleValuesIfNecessary):
+        * dfg/DFGPlan.h:
+        (JSC::DFG::Plan::canTierUpAndOSREnter):
+        * jit/JITOperations.cpp:
+
</ins><span class="cx"> 2016-07-18  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r202975): --minimal build is broken
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCFAPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -80,6 +80,9 @@
</span><span class="cx">         } while (m_changed);
</span><span class="cx">         
</span><span class="cx">         if (m_graph.m_form != SSA) {
</span><ins>+            if (m_verbose)
+                dataLog(&quot;   Widening state at OSR entry block.\n&quot;);
+            
</ins><span class="cx">             ASSERT(!m_changed);
</span><span class="cx">             
</span><span class="cx">             // Widen the abstract values at the block that serves as the must-handle OSR entry.
</span><span class="lines">@@ -93,14 +96,23 @@
</span><span class="cx">                 if (block-&gt;bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex)
</span><span class="cx">                     continue;
</span><span class="cx">                 
</span><ins>+                if (m_verbose)
+                    dataLog(&quot;   Found must-handle block: &quot;, *block, &quot;\n&quot;);
+                
</ins><span class="cx">                 bool changed = false;
</span><span class="cx">                 for (size_t i = m_graph.m_plan.mustHandleValues.size(); i--;) {
</span><span class="cx">                     int operand = m_graph.m_plan.mustHandleValues.operandForIndex(i);
</span><span class="cx">                     JSValue value = m_graph.m_plan.mustHandleValues[i];
</span><span class="cx">                     Node* node = block-&gt;variablesAtHead.operand(operand);
</span><del>-                    if (!node)
</del><ins>+                    if (!node) {
+                        if (m_verbose)
+                            dataLog(&quot;   Not live: &quot;, VirtualRegister(operand), &quot;\n&quot;);
</ins><span class="cx">                         continue;
</span><ins>+                    }
</ins><span class="cx">                     
</span><ins>+                    if (m_verbose)
+                        dataLog(&quot;   Widening &quot;, VirtualRegister(operand), &quot; with &quot;, value, &quot;\n&quot;);
+
</ins><span class="cx">                     AbstractValue&amp; target = block-&gt;valuesAtHead.operand(operand);
</span><span class="cx">                     changed |= target.mergeOSREntryValue(m_graph, value);
</span><span class="cx">                     target.fixTypeForRepresentation(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSREntrycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -228,7 +228,7 @@
</span><span class="cx">         if (!entry-&gt;m_expectedValues.local(local).validate(exec-&gt;registers()[localOffset].asanUnsafeJSValue())) {
</span><span class="cx">             if (Options::verboseOSR()) {
</span><span class="cx">                 dataLog(
</span><del>-                    &quot;    OSR failed because variable &quot;, localOffset, &quot; is &quot;,
</del><ins>+                    &quot;    OSR failed because variable &quot;, VirtualRegister(localOffset), &quot; is &quot;,
</ins><span class="cx">                     exec-&gt;registers()[localOffset].asanUnsafeJSValue(), &quot;, expected &quot;,
</span><span class="cx">                     entry-&gt;m_expectedValues.local(local), &quot;.\n&quot;);
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -238,6 +238,8 @@
</span><span class="cx"> 
</span><span class="cx"> Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState&amp; longLivedState)
</span><span class="cx"> {
</span><ins>+    cleanMustHandleValuesIfNecessary();
+    
</ins><span class="cx">     if (verboseCompilationEnabled(mode) &amp;&amp; osrEntryBytecodeIndex != UINT_MAX) {
</span><span class="cx">         dataLog(&quot;\n&quot;);
</span><span class="cx">         dataLog(&quot;Compiler must handle OSR entry from bc#&quot;, osrEntryBytecodeIndex, &quot; with values: &quot;, mustHandleValues, &quot;\n&quot;);
</span><span class="lines">@@ -626,7 +628,8 @@
</span><span class="cx"> {
</span><span class="cx">     if (!isKnownToBeLiveDuringGC())
</span><span class="cx">         return;
</span><del>-    
</del><ins>+
+    cleanMustHandleValuesIfNecessary();
</ins><span class="cx">     for (unsigned i = mustHandleValues.size(); i--;)
</span><span class="cx">         visitor.appendUnbarrieredValue(&amp;mustHandleValues[i]);
</span><span class="cx"> 
</span><span class="lines">@@ -675,6 +678,29 @@
</span><span class="cx">     stage = Cancelled;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Plan::cleanMustHandleValuesIfNecessary()
+{
+    LockHolder locker(mustHandleValueCleaningLock);
+    
+    if (!mustHandleValuesMayIncludeGarbage)
+        return;
+    
+    mustHandleValuesMayIncludeGarbage = false;
+    
+    if (!codeBlock)
+        return;
+    
+    if (!mustHandleValues.numberOfLocals())
+        return;
+    
+    FastBitVector liveness = codeBlock-&gt;alternative()-&gt;livenessAnalysis().getLivenessInfoAtBytecodeOffset(osrEntryBytecodeIndex);
+    
+    for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
+        if (!liveness.get(local))
+            mustHandleValues.local(local) = jsUndefined();
+    }
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlanh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.h (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.h        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.h        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -78,6 +78,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool canTierUpAndOSREnter() const { return !tierUpAndOSREnterBytecodes.isEmpty(); }
</span><span class="cx">     
</span><ins>+    void cleanMustHandleValuesIfNecessary();
+    
</ins><span class="cx">     // Warning: pretty much all of the pointer fields in this object get nulled by cancel(). So, if
</span><span class="cx">     // you're writing code that is callable on the cancel path, be sure to null check everything!
</span><span class="cx">     
</span><span class="lines">@@ -90,6 +92,8 @@
</span><span class="cx">     CompilationMode mode;
</span><span class="cx">     const unsigned osrEntryBytecodeIndex;
</span><span class="cx">     Operands&lt;JSValue&gt; mustHandleValues;
</span><ins>+    bool mustHandleValuesMayIncludeGarbage { true };
+    Lock mustHandleValueCleaningLock;
</ins><span class="cx">     
</span><span class="cx">     ThreadData* threadData;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (203355 => 203356)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-18 18:51:13 UTC (rev 203355)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-18 18:55:31 UTC (rev 203356)
</span><span class="lines">@@ -1353,7 +1353,7 @@
</span><span class="cx"> 
</span><span class="cx">         unsigned numVarsWithValues;
</span><span class="cx">         if (bytecodeIndex)
</span><del>-            numVarsWithValues = codeBlock-&gt;m_numVars;
</del><ins>+            numVarsWithValues = codeBlock-&gt;m_numCalleeLocals;
</ins><span class="cx">         else
</span><span class="cx">             numVarsWithValues = 0;
</span><span class="cx">         Operands&lt;JSValue&gt; mustHandleValues(codeBlock-&gt;numParameters(), numVarsWithValues);
</span></span></pre>
</div>
</div>

</body>
</html>