<!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>[182148] 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/182148">182148</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-03-30 11:36:08 -0700 (Mon, 30 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION: js/regress/inline-arguments-local-escape.html is flaky
https://bugs.webkit.org/show_bug.cgi?id=143104

Reviewed by Geoffrey Garen.

Created a test that is a 100% repro of the flaky failure. This test is called
get-my-argument-by-val-for-inlined-escaped-arguments.js. It fails all of the time because it
always causes the compiler to emit a GetMyArgumentByVal of the arguments object returned by
the inlined function. Other than that, it's the same as inline-arguments-local-escape.

Also created three more tests for three similar, but not identical, failures.

Then fixed the bug: PreciseLocalClobberize was assuming that if we read(Stack) then we are
only reading those parts of the stack that are relevant to the current semantic code origin.
That's false after ArgumentsEliminationPhase - we might have operations on phantom arguments,
like GetMyArgumentByVal, ForwardVarargs, CallForwardVarargs, and ConstructForwardVarargs, that
read parts of the stack associated with the inline call frame for the phantom arguments. This
may not be subsumed by the current semantic origin's stack area in cases that the arguments
were allowed to &quot;locally&quot; escape.

The higher-order lesson here is that in DFG SSA IR, the current semantic origin's stack area
is not really a meaningful concept anymore. It is only meaningful for nodes that will read
the stack due to function.arguments, but there are a bunch of other ways that we could also
read the stack and those operations may read any stack slot. I believe that this change makes
PreciseLocalClobberize right: it will refine a read(Stack) from Clobberize correctly by casing
on node type. In future, if we add a read(Stack) to Clobberize, we'll have to make sure that
readTop() in PreciseLocalClobberize does the right thing.

* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
* dfg/DFGPutStackSinkingPhase.cpp:
* tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js: Added.
* tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js: Added.
* tests/stress/forward-varargs-for-inlined-escaped-arguments.js: Added.
* tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js: Added.
* tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPutStackSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresscallforwardvarargsforinlinedescapedargumentsjs">trunk/Source/JavaScriptCore/tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressconstructforwardvarargsforinlinedescapedargumentsjs">trunk/Source/JavaScriptCore/tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressforwardvarargsforinlinedescapedargumentsjs">trunk/Source/JavaScriptCore/tests/stress/forward-varargs-for-inlined-escaped-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressgetmyargumentbyvalforinlinedescapedargumentsjs">trunk/Source/JavaScriptCore/tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressrealforwardvarargsforinlinedescapedargumentsjs">trunk/Source/JavaScriptCore/tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (182147 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-30 18:33:39 UTC (rev 182147)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -1,3 +1,44 @@
</span><ins>+2015-03-30  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        REGRESSION: js/regress/inline-arguments-local-escape.html is flaky
+        https://bugs.webkit.org/show_bug.cgi?id=143104
+
+        Reviewed by Geoffrey Garen.
+        
+        Created a test that is a 100% repro of the flaky failure. This test is called
+        get-my-argument-by-val-for-inlined-escaped-arguments.js. It fails all of the time because it
+        always causes the compiler to emit a GetMyArgumentByVal of the arguments object returned by
+        the inlined function. Other than that, it's the same as inline-arguments-local-escape.
+        
+        Also created three more tests for three similar, but not identical, failures.
+        
+        Then fixed the bug: PreciseLocalClobberize was assuming that if we read(Stack) then we are
+        only reading those parts of the stack that are relevant to the current semantic code origin.
+        That's false after ArgumentsEliminationPhase - we might have operations on phantom arguments,
+        like GetMyArgumentByVal, ForwardVarargs, CallForwardVarargs, and ConstructForwardVarargs, that
+        read parts of the stack associated with the inline call frame for the phantom arguments. This
+        may not be subsumed by the current semantic origin's stack area in cases that the arguments
+        were allowed to &quot;locally&quot; escape.
+        
+        The higher-order lesson here is that in DFG SSA IR, the current semantic origin's stack area
+        is not really a meaningful concept anymore. It is only meaningful for nodes that will read
+        the stack due to function.arguments, but there are a bunch of other ways that we could also
+        read the stack and those operations may read any stack slot. I believe that this change makes
+        PreciseLocalClobberize right: it will refine a read(Stack) from Clobberize correctly by casing
+        on node type. In future, if we add a read(Stack) to Clobberize, we'll have to make sure that
+        readTop() in PreciseLocalClobberize does the right thing.
+
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGPreciseLocalClobberize.h:
+        (JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
+        * dfg/DFGPutStackSinkingPhase.cpp:
+        * tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js: Added.
+        * tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js: Added.
+        * tests/stress/forward-varargs-for-inlined-escaped-arguments.js: Added.
+        * tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js: Added.
+        * tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js: Added.
+
</ins><span class="cx"> 2015-03-30  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Start the features.json files
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (182147 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-03-30 18:33:39 UTC (rev 182147)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -76,6 +76,9 @@
</span><span class="cx">     //   can use it for IR dumps. No promises on whether the answers are sound
</span><span class="cx">     //   prior to type inference - though they probably could be if we did some
</span><span class="cx">     //   small hacking.
</span><ins>+    //
+    // - If you do read(Stack) or read(World), then make sure that readTop() in
+    //   PreciseLocalClobberize is correct.
</ins><span class="cx">     
</span><span class="cx">     // While read() and write() are fairly self-explanatory - they track what sorts of things the
</span><span class="cx">     // node may read or write - the def() functor is more tricky. It tells you the heap locations
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h (182147 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2015-03-30 18:33:39 UTC (rev 182147)
+++ trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -107,26 +107,47 @@
</span><span class="cx">     
</span><span class="cx">     void readTop()
</span><span class="cx">     {
</span><del>-        // All of the outermost arguments, except this, are definitely read.
-        for (unsigned i = m_graph.m_codeBlock-&gt;numParameters(); i-- &gt; 1;)
-            m_read(virtualRegisterForArgument(i));
-        
-        // The stack header is read.
-        for (unsigned i = 0; i &lt; JSStack::ThisArgument; ++i)
-            m_read(VirtualRegister(i));
-        
-        // Read all of the inline arguments and call frame headers that we didn't already capture.
-        for (InlineCallFrame* inlineCallFrame = m_node-&gt;origin.semantic.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame-&gt;caller.inlineCallFrame) {
</del><ins>+        switch (m_node-&gt;op()) {
+        case GetMyArgumentByVal:
+        case ForwardVarargs:
+        case CallForwardVarargs:
+        case ConstructForwardVarargs: {
+            InlineCallFrame* inlineCallFrame = m_node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
+            if (!inlineCallFrame) {
+                // Read the outermost arguments and argument count.
+                for (unsigned i = m_graph.m_codeBlock-&gt;numParameters(); i-- &gt; 1;)
+                    m_read(virtualRegisterForArgument(i));
+                m_read(VirtualRegister(JSStack::ArgumentCount));
+                break;
+            }
+            
</ins><span class="cx">             for (unsigned i = inlineCallFrame-&gt;arguments.size(); i-- &gt; 1;)
</span><span class="cx">                 m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + virtualRegisterForArgument(i).offset()));
</span><del>-            if (inlineCallFrame-&gt;isClosureCall)
-                m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + JSStack::Callee));
</del><span class="cx">             if (inlineCallFrame-&gt;isVarargs())
</span><span class="cx">                 m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount));
</span><ins>+            break;
</ins><span class="cx">         }
</span><del>-
-        // Note that we don't need to do anything special for CallForwardVarargs, since it reads
-        // our arguments the same way that any effectful thing might.
</del><ins>+            
+        default: {
+            // All of the outermost arguments, except this, are definitely read.
+            for (unsigned i = m_graph.m_codeBlock-&gt;numParameters(); i-- &gt; 1;)
+                m_read(virtualRegisterForArgument(i));
+        
+            // The stack header is read.
+            for (unsigned i = 0; i &lt; JSStack::ThisArgument; ++i)
+                m_read(VirtualRegister(i));
+        
+            // Read all of the inline arguments and call frame headers that we didn't already capture.
+            for (InlineCallFrame* inlineCallFrame = m_node-&gt;origin.semantic.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame-&gt;caller.inlineCallFrame) {
+                for (unsigned i = inlineCallFrame-&gt;arguments.size(); i-- &gt; 1;)
+                    m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + virtualRegisterForArgument(i).offset()));
+                if (inlineCallFrame-&gt;isClosureCall)
+                    m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + JSStack::Callee));
+                if (inlineCallFrame-&gt;isVarargs())
+                    m_read(VirtualRegister(inlineCallFrame-&gt;stackOffset + JSStack::ArgumentCount));
+            }
+            break;
+        } }
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Graph&amp; m_graph;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPutStackSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp (182147 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2015-03-30 18:33:39 UTC (rev 182147)
+++ trunk/Source/JavaScriptCore/dfg/DFGPutStackSinkingPhase.cpp        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -216,11 +216,6 @@
</span><span class="cx">                     if (verbose)
</span><span class="cx">                         dataLog(&quot;Deferred at &quot;, node, &quot;:&quot;, deferred, &quot;\n&quot;);
</span><span class="cx">                     
</span><del>-                    if (node-&gt;op() == KillStack) {
-                        deferred.operand(node-&gt;unlinkedLocal()) = ConflictingFlush;
-                        continue;
-                    }
-                    
</del><span class="cx">                     if (node-&gt;op() == GetStack) {
</span><span class="cx">                         // A GetStack doesn't affect anything, since we know which local we are reading
</span><span class="cx">                         // from.
</span><span class="lines">@@ -392,11 +387,6 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                     
</span><del>-                case KillStack: {
-                    deferred.operand(node-&gt;unlinkedLocal()) = ConflictingFlush;
-                    break;
-                }
-                    
</del><span class="cx">                 case GetStack: {
</span><span class="cx">                     StackAccessData* data = node-&gt;stackAccessData();
</span><span class="cx">                     FlushFormat format = deferred.operand(data-&gt;local);
</span><span class="lines">@@ -493,7 +483,7 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         // Finally eliminate the sunken PutStacks by turning them into Phantoms. This keeps whatever
</span><del>-        // type check they were doing. Also prepend KillLocals to them to ensure that we know that
</del><ins>+        // type check they were doing. Also prepend KillStacks to them to ensure that we know that
</ins><span class="cx">         // the relevant value was *not* stored to the stack.
</span><span class="cx">         for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
</span><span class="cx">             for (unsigned nodeIndex = 0; nodeIndex &lt; block-&gt;size(); ++nodeIndex) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresscallforwardvarargsforinlinedescapedargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js (0 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/call-forward-varargs-for-inlined-escaped-arguments.js        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+function foo() {
+    return arguments;
+}
+
+function baz(a, b, c) {
+    return a + b + c;
+}
+
+noInline(baz);
+
+function bar(a, b, c) {
+    var args = foo(b, c, 42);
+    return baz.apply(void 0, args);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = bar(1, 2, 3);
+    if (result != 47)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressconstructforwardvarargsforinlinedescapedargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js (0 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/construct-forward-varargs-for-inlined-escaped-arguments.js        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+function foo() {
+    return arguments;
+}
+
+function Baz(a, b, c) {
+    this.f = a + b + c;
+}
+
+noInline(Baz);
+
+function bar(a, b, c) {
+    var args = foo(b, c, 42);
+    return new Baz(...args);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = bar(1, 2, 3);
+    if (result.f != 47)
+        throw &quot;Error: bad result: &quot; + result.f;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressforwardvarargsforinlinedescapedargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/forward-varargs-for-inlined-escaped-arguments.js (0 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/forward-varargs-for-inlined-escaped-arguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/forward-varargs-for-inlined-escaped-arguments.js        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+function foo() {
+    return arguments;
+}
+
+function baz(a, b, c) {
+    return a + b + c;
+}
+
+function bar(a, b, c) {
+    var args = foo(b, c, 42);
+    return baz.apply(void 0, args);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = bar(1, 2, 3);
+    if (result != 47)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressgetmyargumentbyvalforinlinedescapedargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js (0 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/get-my-argument-by-val-for-inlined-escaped-arguments.js        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+function foo() {
+    return arguments;
+}
+
+function bar(a, b, c, i) {
+    var args = foo(b, c, 42);
+    return args[i];
+}
+
+noInline(bar);
+
+var expected = [2, 3, 42];
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = bar(1, 2, 3, i % 3);
+    if (result != expected[i % 3])
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressrealforwardvarargsforinlinedescapedargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js (0 => 182148)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/real-forward-varargs-for-inlined-escaped-arguments.js        2015-03-30 18:36:08 UTC (rev 182148)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo() {
+    return arguments;
+}
+
+function fuzz(args) {
+    return foo.apply(void 0, args);
+}
+
+function baz(a, b, c) {
+    return a + b + c;
+}
+
+function bar(args1) {
+    var args2 = fuzz(args1);
+    return baz.apply(void 0, args2);
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 20000; ++i) {
+    var result = bar([1, 2, 3]);
+    if (result != 6)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>