<!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>[183307] 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/183307">183307</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-04-24 22:19:07 -0700 (Fri, 24 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>CRASH in operationCreateDirectArgumentsDuringExit()
https://bugs.webkit.org/show_bug.cgi?id=143962

Reviewed by Geoffrey Garen.
        
We shouldn't assume that constant-like OSR exit values are always recoverable. They are only
recoverable so long as they are live. Therefore, OSR exit should track liveness of
constants instead of assuming that they are always live.

* dfg/DFGGenerationInfo.h:
(JSC::DFG::GenerationInfo::noticeOSRBirth):
(JSC::DFG::GenerationInfo::appendBirth):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
* dfg/DFGVariableEvent.cpp:
(JSC::DFG::VariableEvent::dump):
* dfg/DFGVariableEvent.h:
(JSC::DFG::VariableEvent::birth):
(JSC::DFG::VariableEvent::id):
(JSC::DFG::VariableEvent::dataFormat):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* tests/stress/phantom-direct-arguments-clobber-argument-count.js: Added.
(foo):
(bar):
* tests/stress/phantom-direct-arguments-clobber-callee.js: Added.
(foo):
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGenerationInfoh">trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventcpp">trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventh">trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp">trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressphantomdirectargumentsclobberargumentcountjs">trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-argument-count.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressphantomdirectargumentsclobbercalleejs">trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-callee.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2015-04-24  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        CRASH in operationCreateDirectArgumentsDuringExit()
+        https://bugs.webkit.org/show_bug.cgi?id=143962
+
+        Reviewed by Geoffrey Garen.
+        
+        We shouldn't assume that constant-like OSR exit values are always recoverable. They are only
+        recoverable so long as they are live. Therefore, OSR exit should track liveness of
+        constants instead of assuming that they are always live.
+
+        * dfg/DFGGenerationInfo.h:
+        (JSC::DFG::GenerationInfo::noticeOSRBirth):
+        (JSC::DFG::GenerationInfo::appendBirth):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        * dfg/DFGVariableEvent.cpp:
+        (JSC::DFG::VariableEvent::dump):
+        * dfg/DFGVariableEvent.h:
+        (JSC::DFG::VariableEvent::birth):
+        (JSC::DFG::VariableEvent::id):
+        (JSC::DFG::VariableEvent::dataFormat):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::reconstruct):
+        * tests/stress/phantom-direct-arguments-clobber-argument-count.js: Added.
+        (foo):
+        (bar):
+        * tests/stress/phantom-direct-arguments-clobber-callee.js: Added.
+        (foo):
+        (bar):
+
</ins><span class="cx"> 2015-04-24  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] When inserting a NaN into a Int32 array, we convert it to DoubleArray then to ContiguousArray
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGenerationInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -153,8 +153,6 @@
</span><span class="cx">     
</span><span class="cx">     void noticeOSRBirth(VariableEventStream&amp; stream, Node* node, VirtualRegister virtualRegister)
</span><span class="cx">     {
</span><del>-        if (m_isConstant)
-            return;
</del><span class="cx">         if (m_node != node)
</span><span class="cx">             return;
</span><span class="cx">         if (!alive())
</span><span class="lines">@@ -164,7 +162,9 @@
</span><span class="cx">         
</span><span class="cx">         m_bornForOSR = true;
</span><span class="cx">         
</span><del>-        if (m_registerFormat != DataFormatNone)
</del><ins>+        if (m_isConstant)
+            appendBirth(stream);
+        else if (m_registerFormat != DataFormatNone)
</ins><span class="cx">             appendFill(BirthToFill, stream);
</span><span class="cx">         else if (m_spillFormat != DataFormatNone)
</span><span class="cx">             appendSpill(BirthToSpill, stream, virtualRegister);
</span><span class="lines">@@ -379,6 +379,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    void appendBirth(VariableEventStream&amp; stream)
+    {
+        stream.appendAndLog(VariableEvent::birth(MinifiedID(m_node)));
+    }
+    
</ins><span class="cx">     void appendFill(VariableEventKind kind, VariableEventStream&amp; stream)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_bornForOSR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -1428,33 +1428,29 @@
</span><span class="cx">         m_codeOriginForExitTarget = m_currentNode-&gt;origin.forExit;
</span><span class="cx">         m_codeOriginForExitProfile = m_currentNode-&gt;origin.semantic;
</span><span class="cx">         m_lastGeneratedNode = m_currentNode-&gt;op();
</span><del>-        if (!m_currentNode-&gt;shouldGenerate()) {
-            if (belongsInMinifiedGraph(m_currentNode-&gt;op()))
-                m_minifiedGraph-&gt;append(MinifiedNode::fromNode(m_currentNode));
-        } else {
-            if (verboseCompilationEnabled()) {
-                dataLogF(
-                    &quot;SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x&quot;,
-                    (int)m_currentNode-&gt;index(),
-                    m_currentNode-&gt;origin.semantic.bytecodeIndex, m_jit.debugOffset());
-                dataLog(&quot;\n&quot;);
-            }
-            
-            compile(m_currentNode);
-
</del><ins>+        
+        ASSERT(m_currentNode-&gt;shouldGenerate());
+        
+        if (verboseCompilationEnabled()) {
+            dataLogF(
+                &quot;SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x&quot;,
+                (int)m_currentNode-&gt;index(),
+                m_currentNode-&gt;origin.semantic.bytecodeIndex, m_jit.debugOffset());
+            dataLog(&quot;\n&quot;);
+        }
+        
+        compile(m_currentNode);
+        
+        if (belongsInMinifiedGraph(m_currentNode-&gt;op()))
+            m_minifiedGraph-&gt;append(MinifiedNode::fromNode(m_currentNode));
+        
</ins><span class="cx"> #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
</span><del>-            m_jit.clearRegisterAllocationOffsets();
</del><ins>+        m_jit.clearRegisterAllocationOffsets();
</ins><span class="cx"> #endif
</span><del>-
-            if (!m_compileOkay) {
-                bail(DFGBailedAtEndOfNode);
-                return;
-            }
-            
-            if (belongsInMinifiedGraph(m_currentNode-&gt;op())) {
-                m_minifiedGraph-&gt;append(MinifiedNode::fromNode(m_currentNode));
-                noticeOSRBirth(m_currentNode);
-            }
</del><ins>+        
+        if (!m_compileOkay) {
+            bail(DFGBailedAtEndOfNode);
+            return;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         // Make sure that the abstract state is rematerialized for the next node.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.cpp (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.cpp        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.cpp        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -46,6 +46,9 @@
</span><span class="cx">     case BirthToSpill:
</span><span class="cx">         dumpSpillInfo(&quot;BirthToSpill&quot;, out);
</span><span class="cx">         break;
</span><ins>+    case Birth:
+        out.print(&quot;Birth(&quot;, id(), &quot;)&quot;);
+        break;
</ins><span class="cx">     case Fill:
</span><span class="cx">         dumpFillInfo(&quot;Fill&quot;, out);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.h (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.h        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEvent.h        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx">     // that we start to care about this node.
</span><span class="cx">     BirthToFill,
</span><span class="cx">     BirthToSpill,
</span><ins>+    Birth,
</ins><span class="cx">     
</span><span class="cx">     // Events related to how a node is represented.
</span><span class="cx">     Fill,
</span><span class="lines">@@ -133,6 +134,14 @@
</span><span class="cx">         return event;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static VariableEvent birth(MinifiedID id)
+    {
+        VariableEvent event;
+        event.m_which.id = id.bits();
+        event.m_kind = Birth;
+        return event;
+    }
+    
</ins><span class="cx">     static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(kind == BirthToSpill || kind == Spill);
</span><span class="lines">@@ -179,17 +188,17 @@
</span><span class="cx">     
</span><span class="cx">     MinifiedID id() const
</span><span class="cx">     {
</span><del>-        ASSERT(m_kind == BirthToFill || m_kind == Fill
-               || m_kind == BirthToSpill || m_kind == Spill
-               || m_kind == Death || m_kind == MovHintEvent);
</del><ins>+        ASSERT(
+            m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+            || m_kind == Death || m_kind == MovHintEvent || m_kind == Birth);
</ins><span class="cx">         return MinifiedID::fromBits(m_which.id);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     DataFormat dataFormat() const
</span><span class="cx">     {
</span><del>-        ASSERT(m_kind == BirthToFill || m_kind == Fill
-               || m_kind == BirthToSpill || m_kind == Spill
-               || m_kind == SetLocalEvent);
</del><ins>+        ASSERT(
+            m_kind == BirthToFill || m_kind == Fill || m_kind == BirthToSpill || m_kind == Spill
+            || m_kind == SetLocalEvent);
</ins><span class="cx">         return static_cast&lt;DataFormat&gt;(m_dataFormat);
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (183306 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2015-04-25 03:40:02 UTC (rev 183306)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -48,11 +48,14 @@
</span><span class="cx"> 
</span><span class="cx"> struct MinifiedGenerationInfo {
</span><span class="cx">     bool filled; // true -&gt; in gpr/fpr/pair, false -&gt; spilled
</span><ins>+    bool alive;
</ins><span class="cx">     VariableRepresentation u;
</span><span class="cx">     DataFormat format;
</span><span class="cx">     
</span><span class="cx">     MinifiedGenerationInfo()
</span><del>-        : format(DataFormatNone)
</del><ins>+        : filled(false)
+        , alive(false)
+        , format(DataFormatNone)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -62,13 +65,19 @@
</span><span class="cx">         case BirthToFill:
</span><span class="cx">         case Fill:
</span><span class="cx">             filled = true;
</span><ins>+            alive = true;
</ins><span class="cx">             break;
</span><span class="cx">         case BirthToSpill:
</span><span class="cx">         case Spill:
</span><span class="cx">             filled = false;
</span><ins>+            alive = true;
</ins><span class="cx">             break;
</span><ins>+        case Birth:
+            alive = true;
+            return;
</ins><span class="cx">         case Death:
</span><span class="cx">             format = DataFormatNone;
</span><ins>+            alive = false;
</ins><span class="cx">             return;
</span><span class="cx">         default:
</span><span class="cx">             return;
</span><span class="lines">@@ -146,7 +155,8 @@
</span><span class="cx">             // nothing to do.
</span><span class="cx">             break;
</span><span class="cx">         case BirthToFill:
</span><del>-        case BirthToSpill: {
</del><ins>+        case BirthToSpill:
+        case Birth: {
</ins><span class="cx">             MinifiedGenerationInfo info;
</span><span class="cx">             info.update(event);
</span><span class="cx">             generationInfos.add(event.id(), info);
</span><span class="lines">@@ -185,14 +195,14 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(source.kind() == HaveNode);
</span><span class="cx">         MinifiedNode* node = graph.at(source.id());
</span><del>-        if (tryToSetConstantRecovery(valueRecoveries[i], node))
-            continue;
-        
</del><span class="cx">         MinifiedGenerationInfo info = generationInfos.get(source.id());
</span><del>-        if (info.format == DataFormatNone) {
</del><ins>+        if (!info.alive) {
</ins><span class="cx">             valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><ins>+
+        if (tryToSetConstantRecovery(valueRecoveries[i], node))
+            continue;
</ins><span class="cx">         
</span><span class="cx">         ASSERT(info.format != DataFormatNone);
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressphantomdirectargumentsclobberargumentcountjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-argument-count.js (0 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-argument-count.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-argument-count.js        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+function foo() {
+    return effectful42.apply(this, arguments);
+}
+
+function bar(a, b) {
+    var result = foo.apply(this, b);
+    return [a, a, a, a, a, a, a, a, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = &quot;&quot; + bar(1, []);
+    if (result != &quot;1,1,1,1,1,1,1,1,43&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = &quot;&quot; + bar(2147483647, []);
+if (result != &quot;2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483647,2147483689&quot;)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressphantomdirectargumentsclobbercalleejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-callee.js (0 => 183307)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-callee.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/phantom-direct-arguments-clobber-callee.js        2015-04-25 05:19:07 UTC (rev 183307)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+function foo() {
+    return function() { return effectful42.apply(this, arguments) };
+}
+noInline(foo);
+
+function bar(a) {
+    var result = foo()();
+    return [result, result, result, result, result, result, result, result, result + a];
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = &quot;&quot; + bar(1);
+    if (result != &quot;42,42,42,42,42,42,42,42,43&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+var result = &quot;&quot; + bar(2147483647);
+if (result != &quot;42,42,42,42,42,42,42,42,2147483689&quot;)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre>
</div>
</div>

</body>
</html>