<!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>[202003] 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/202003">202003</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-06-13 14:05:36 -0700 (Mon, 13 Jun 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add new builtin opcode tailCallForwardArguments
https://bugs.webkit.org/show_bug.cgi?id=158666

Reviewed by Filip Pizlo.

We should support the ability to have a builtin forward its
arguments to a helper without allocating an arguments object. This
patch adds a new bytecode intrinsic @tailCallForwardArguments that
takes two values. The first is the target of the call and the
second is the new this value. This opcode will tail call to the
passed function without triggering an allocation of an arguments
object for the caller function.

In the LLInt and Baseline this function acts the same way a normal
tail call does.  The bytecode will allocate a new stack frame
copying all the arguments of the caller function into the new
frame, along with the new this. Then when the actual call happens
the new frame is copied over the caller frame. While this is not
necessary, it allows the target function to have more arguments
than the caller function via arity fixup.

Once we get to the DFG we reuse existing DFG Nodes for forwarding
arguments, although there were some minor changes. This patch
swaps the meaning of the second and third children for each DFG
varargs node, exchanging the argmuments and this child,
respectively. It also makes the arguments child for each varargs
node, as well as the ForwardVarargs node optional. If the optional
child is missing, then forwarding node assumes that the arguments
for the node's inlineCallFrame should be used instead. Finally,
when inlining the target of an inlined
op_tail_call_forward_arguments we make sure the arguments of the
forwarding function are marked as non-unboxable since this would
normally be done by the caller's create arguments object node,
which does not exist in this case.

* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::callTypeFor):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::finishCreation):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitCallForwardArgumentsInTailPosition):
(JSC::BytecodeGenerator::emitCallVarargs):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_tryGetById):
* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::handleCall):
(JSC::DFG::ByteCodeParser::handleVarargsCall):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasArgumentsChild):
(JSC::DFG::Node::argumentsChild):
* dfg/DFGPreciseLocalClobberize.h:
(JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileForwardVarargs):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGVarargsForwardingPhase.cpp:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
(JSC::FTL::DFG::LowerDFGToB3::compileForwardVarargs):
* interpreter/Interpreter.cpp:
(JSC::sizeFrameForForwardArguments):
(JSC::setupForwardArgumentsFrame):
(JSC::setupForwardArgumentsFrameAndSetThis):
* interpreter/Interpreter.h:
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileSetupVarargsFrame):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
(JSC::JIT::emit_op_tail_call_forward_arguments):
(JSC::JIT::emitSlow_op_tail_call_forward_arguments):
* jit/JITCall32_64.cpp:
(JSC::JIT::emitSlow_op_tail_call_forward_arguments):
(JSC::JIT::emit_op_tail_call_forward_arguments):
(JSC::JIT::compileSetupVarargsFrame):
(JSC::JIT::compileOpCall):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::varargsSetup):
* llint/LLIntSlowPaths.h:
* llint/LowLevelInterpreter.asm:
* tests/stress/tailCallForwardArguments.js: Added.
(putFuncToPrivateName.createBuiltin):
(putFuncToPrivateName):
(createTailCallForwardingFuncWith):
(baz):
(baz2):
(baz3):
(let.bodyText):
(baz4):
(baz5):
(arrayEq):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeIntrinsicRegistryh">trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfoh">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathsh">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresstailCallForwardArgumentsjs">trunk/Source/JavaScriptCore/tests/stress/tailCallForwardArguments.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1,3 +1,123 @@
</span><ins>+2016-06-12  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        Add new builtin opcode tailCallForwardArguments
+        https://bugs.webkit.org/show_bug.cgi?id=158666
+
+        Reviewed by Filip Pizlo.
+
+        We should support the ability to have a builtin forward its
+        arguments to a helper without allocating an arguments object. This
+        patch adds a new bytecode intrinsic @tailCallForwardArguments that
+        takes two values. The first is the target of the call and the
+        second is the new this value. This opcode will tail call to the
+        passed function without triggering an allocation of an arguments
+        object for the caller function.
+
+        In the LLInt and Baseline this function acts the same way a normal
+        tail call does.  The bytecode will allocate a new stack frame
+        copying all the arguments of the caller function into the new
+        frame, along with the new this. Then when the actual call happens
+        the new frame is copied over the caller frame. While this is not
+        necessary, it allows the target function to have more arguments
+        than the caller function via arity fixup.
+
+        Once we get to the DFG we reuse existing DFG Nodes for forwarding
+        arguments, although there were some minor changes. This patch
+        swaps the meaning of the second and third children for each DFG
+        varargs node, exchanging the argmuments and this child,
+        respectively. It also makes the arguments child for each varargs
+        node, as well as the ForwardVarargs node optional. If the optional
+        child is missing, then forwarding node assumes that the arguments
+        for the node's inlineCallFrame should be used instead. Finally,
+        when inlining the target of an inlined
+        op_tail_call_forward_arguments we make sure the arguments of the
+        forwarding function are marked as non-unboxable since this would
+        normally be done by the caller's create arguments object node,
+        which does not exist in this case.
+
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::callTypeFor):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::finishCreation):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitCallForwardArgumentsInTailPosition):
+        (JSC::BytecodeGenerator::emitCallVarargs):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_tryGetById):
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::handleVarargsCall):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasArgumentsChild):
+        (JSC::DFG::Node::argumentsChild):
+        * dfg/DFGPreciseLocalClobberize.h:
+        (JSC::DFG::PreciseLocalClobberizeAdaptor::readTop):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileForwardVarargs):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGVarargsForwardingPhase.cpp:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallOrConstructVarargs):
+        (JSC::FTL::DFG::LowerDFGToB3::compileForwardVarargs):
+        * interpreter/Interpreter.cpp:
+        (JSC::sizeFrameForForwardArguments):
+        (JSC::setupForwardArgumentsFrame):
+        (JSC::setupForwardArgumentsFrameAndSetThis):
+        * interpreter/Interpreter.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileSetupVarargsFrame):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        (JSC::JIT::emit_op_tail_call_forward_arguments):
+        (JSC::JIT::emitSlow_op_tail_call_forward_arguments):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::emitSlow_op_tail_call_forward_arguments):
+        (JSC::JIT::emit_op_tail_call_forward_arguments):
+        (JSC::JIT::compileSetupVarargsFrame):
+        (JSC::JIT::compileOpCall):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::varargsSetup):
+        * llint/LLIntSlowPaths.h:
+        * llint/LowLevelInterpreter.asm:
+        * tests/stress/tailCallForwardArguments.js: Added.
+        (putFuncToPrivateName.createBuiltin):
+        (putFuncToPrivateName):
+        (createTailCallForwardingFuncWith):
+        (baz):
+        (baz2):
+        (baz3):
+        (let.bodyText):
+        (baz4):
+        (baz5):
+        (arrayEq):
+
</ins><span class="cx"> 2016-06-13  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, follow up patch for r201964
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeIntrinsicRegistryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx">     macro(argumentCount) \
</span><span class="cx">     macro(assert) \
</span><span class="cx">     macro(isObject) \
</span><ins>+    macro(tailCallForwardArguments) \
</ins><span class="cx">     macro(tryGetById) \
</span><span class="cx">     macro(putByValDirect) \
</span><span class="cx">     macro(toString)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -108,6 +108,7 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_call_eval&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_call_varargs&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_tail_call_varargs&quot;, &quot;length&quot; : 9 },
</span><ins>+            { &quot;name&quot; : &quot;op_tail_call_forward_arguments&quot;, &quot;length&quot; : 9 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_ret&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_construct&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_construct_varargs&quot;, &quot;length&quot; : 9 },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -223,7 +223,8 @@
</span><span class="cx">     case op_eq:
</span><span class="cx">     case op_push_with_scope:
</span><span class="cx">     case op_get_by_id_with_this:
</span><del>-    case op_del_by_val: {
</del><ins>+    case op_del_by_val:
+    case op_tail_call_forward_arguments: {
</ins><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 3);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
</span><span class="lines">@@ -390,6 +391,7 @@
</span><span class="cx">     case op_new_generator_func_exp:
</span><span class="cx">     case op_call_varargs:
</span><span class="cx">     case op_tail_call_varargs:
</span><ins>+    case op_tail_call_forward_arguments:
</ins><span class="cx">     case op_construct_varargs:
</span><span class="cx">     case op_get_from_scope:
</span><span class="cx">     case op_call:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">             return ConstructVarargs;
</span><span class="cx">         if (opcodeID == op_tail_call)
</span><span class="cx">             return TailCall;
</span><del>-        ASSERT(opcodeID == op_tail_call_varargs);
</del><ins>+        ASSERT(opcodeID == op_tail_call_varargs || op_tail_call_forward_arguments);
</ins><span class="cx">         return TailCallVarargs;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1466,7 +1466,8 @@
</span><span class="cx">             
</span><span class="cx">         case op_construct_varargs:
</span><span class="cx">         case op_call_varargs:
</span><del>-        case op_tail_call_varargs: {
</del><ins>+        case op_tail_call_varargs:
+        case op_tail_call_forward_arguments: {
</ins><span class="cx">             int result = (++it)-&gt;u.operand;
</span><span class="cx">             int callee = (++it)-&gt;u.operand;
</span><span class="cx">             int thisValue = (++it)-&gt;u.operand;
</span><span class="lines">@@ -1474,7 +1475,19 @@
</span><span class="cx">             int firstFreeRegister = (++it)-&gt;u.operand;
</span><span class="cx">             int varArgOffset = (++it)-&gt;u.operand;
</span><span class="cx">             ++it;
</span><del>-            printLocationAndOp(out, exec, location, it, opcode == op_call_varargs ? &quot;call_varargs&quot; : opcode == op_construct_varargs ? &quot;construct_varargs&quot; : &quot;tail_call_varargs&quot;);
</del><ins>+            const char* opName;
+            if (opcode == op_call_varargs)
+                opName = &quot;call_varargs&quot;;
+            else if (opcode == op_construct_varargs)
+                opName = &quot;construct_varargs&quot;;
+            else if (opcode == op_tail_call_varargs)
+                opName = &quot;tail_call_varargs&quot;;
+            else if (opcode == op_tail_call_forward_arguments)
+                opName = &quot;tail_call_forward_arguments&quot;;
+            else
+                RELEASE_ASSERT_NOT_REACHED();
+
+            printLocationAndOp(out, exec, location, it, opName);
</ins><span class="cx">             out.printf(&quot;%s, %s, %s, %s, %d, %d&quot;, registerName(result).data(), registerName(callee).data(), registerName(thisValue).data(), registerName(arguments).data(), firstFreeRegister, varArgOffset);
</span><span class="cx">             dumpValueProfiling(out, it, hasPrintedProfiling);
</span><span class="cx">             break;
</span><span class="lines">@@ -2055,6 +2068,7 @@
</span><span class="cx">         }
</span><span class="cx">         case op_call_varargs:
</span><span class="cx">         case op_tail_call_varargs:
</span><ins>+        case op_tail_call_forward_arguments:
</ins><span class="cx">         case op_construct_varargs:
</span><span class="cx">         case op_get_by_val: {
</span><span class="cx">             int arrayProfileIndex = pc[opLength - 2].u.operand;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -3115,6 +3115,12 @@
</span><span class="cx"> {
</span><span class="cx">     return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd);
</span><span class="cx"> }
</span><ins>+
+RegisterID* BytecodeGenerator::emitCallForwardArgumentsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
+{
+    ASSERT(m_inTailPosition);
+    return emitCallVarargs(op_tail_call_forward_arguments, dst, func, thisRegister, nullptr, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd);
+}
</ins><span class="cx">     
</span><span class="cx"> RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd)
</span><span class="cx"> {
</span><span class="lines">@@ -3130,7 +3136,7 @@
</span><span class="cx">     instructions().append(dst-&gt;index());
</span><span class="cx">     instructions().append(func-&gt;index());
</span><span class="cx">     instructions().append(thisRegister ? thisRegister-&gt;index() : 0);
</span><del>-    instructions().append(arguments-&gt;index());
</del><ins>+    instructions().append(arguments ? arguments-&gt;index() : 0);
</ins><span class="cx">     instructions().append(firstFreeRegister-&gt;index());
</span><span class="cx">     instructions().append(firstVarArgOffset);
</span><span class="cx">     instructions().append(arrayProfile);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -577,6 +577,7 @@
</span><span class="cx">         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&amp;, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx">         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx">         RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><ins>+        RegisterID* emitCallForwardArgumentsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</ins><span class="cx"> 
</span><span class="cx">         enum PropertyDescriptorOption {
</span><span class="cx">             PropertyConfigurable = 1,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -888,6 +888,18 @@
</span><span class="cx">     return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args-&gt;m_listNode;
+    RefPtr&lt;RegisterID&gt; function = generator.emitNode(node);
+    node = node-&gt;m_next;
+    RefPtr&lt;RegisterID&gt; thisRegister = generator.emitNode(node);
+    ASSERT(!node-&gt;m_next);
+
+    RefPtr&lt;RegisterID&gt; finalDst = generator.finalDestination(dst);
+    return generator.emitCallForwardArgumentsInTailPosition(finalDst.get(), function.get(), thisRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
+}
+
</ins><span class="cx"> RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx">     ArgumentListNode* node = m_args-&gt;m_listNode;
</span><span class="lines">@@ -899,8 +911,8 @@
</span><span class="cx">     const Identifier&amp; ident = static_cast&lt;StringNode*&gt;(node-&gt;m_expr)-&gt;value();
</span><span class="cx">     ASSERT(!node-&gt;m_next);
</span><span class="cx"> 
</span><del>-    RegisterID* finalDest = generator.finalDestination(dst);
-    return generator.emitTryGetById(finalDest, base.get(), ident);
</del><ins>+    RefPtr&lt;RegisterID&gt; finalDest = generator.finalDestination(dst);
+    return generator.emitTryGetById(finalDest.get(), base.get(), ident);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator&amp; generator, RegisterID* dst)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -191,7 +191,7 @@
</span><span class="cx">                 case TailCallVarargs:
</span><span class="cx">                 case TailCallVarargsInlinedCaller:
</span><span class="cx">                     escape(node-&gt;child1(), node);
</span><del>-                    escape(node-&gt;child3(), node);
</del><ins>+                    escape(node-&gt;child2(), node);
</ins><span class="cx">                     break;
</span><span class="cx"> 
</span><span class="cx">                 case Check:
</span><span class="lines">@@ -612,7 +612,7 @@
</span><span class="cx">                 case ConstructVarargs:
</span><span class="cx">                 case TailCallVarargs:
</span><span class="cx">                 case TailCallVarargsInlinedCaller: {
</span><del>-                    Node* candidate = node-&gt;child2().node();
</del><ins>+                    Node* candidate = node-&gt;child3().node();
</ins><span class="cx">                     if (!m_candidates.contains(candidate))
</span><span class="cx">                         break;
</span><span class="cx">                     
</span><span class="lines">@@ -633,7 +633,7 @@
</span><span class="cx">                         
</span><span class="cx">                         unsigned firstChild = m_graph.m_varArgChildren.size();
</span><span class="cx">                         m_graph.m_varArgChildren.append(node-&gt;child1());
</span><del>-                        m_graph.m_varArgChildren.append(node-&gt;child3());
</del><ins>+                        m_graph.m_varArgChildren.append(node-&gt;child2());
</ins><span class="cx">                         for (Node* argument : arguments)
</span><span class="cx">                             m_graph.m_varArgChildren.append(Edge(argument));
</span><span class="cx">                         switch (node-&gt;op()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -828,7 +828,8 @@
</span><span class="cx"> 
</span><span class="cx">                 switch (opcodeID) {
</span><span class="cx">                 case op_tail_call:
</span><del>-                case op_tail_call_varargs: {
</del><ins>+                case op_tail_call_varargs:
+                case op_tail_call_forward_arguments: {
</ins><span class="cx">                     if (!inlineCallFrame()) {
</span><span class="cx">                         prediction = SpecFullTop;
</span><span class="cx">                         break;
</span><span class="lines">@@ -1229,7 +1230,7 @@
</span><span class="cx">         Node* callNode = addCall(result, op, OpInfo(), callTarget, argumentCountIncludingThis, registerOffset, prediction);
</span><span class="cx">         if (callNode-&gt;op() == TailCall)
</span><span class="cx">             return Terminal;
</span><del>-        ASSERT(callNode-&gt;op() != TailCallVarargs);
</del><ins>+        ASSERT(callNode-&gt;op() != TailCallVarargs &amp;&amp; callNode-&gt;op() != TailCallForwardVarargs);
</ins><span class="cx">         return NonTerminal;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1246,7 +1247,7 @@
</span><span class="cx">     Node* callNode = addCall(result, op, callOpInfo, callTarget, argumentCountIncludingThis, registerOffset, prediction);
</span><span class="cx">     if (callNode-&gt;op() == TailCall)
</span><span class="cx">         return Terminal;
</span><del>-    ASSERT(callNode-&gt;op() != TailCallVarargs);
</del><ins>+    ASSERT(callNode-&gt;op() != TailCallVarargs &amp;&amp; callNode-&gt;op() != TailCallForwardVarargs);
</ins><span class="cx">     return NonTerminal;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1254,7 +1255,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_construct_varargs));
</span><span class="cx">     ASSERT(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_tail_call_varargs));
</span><del>-    
</del><ins>+
</ins><span class="cx">     int result = pc[1].u.operand;
</span><span class="cx">     int callee = pc[2].u.operand;
</span><span class="cx">     int thisReg = pc[3].u.operand;
</span><span class="lines">@@ -1285,16 +1286,19 @@
</span><span class="cx">     data-&gt;firstVarArgOffset = firstVarArgOffset;
</span><span class="cx">     
</span><span class="cx">     Node* thisChild = get(VirtualRegister(thisReg));
</span><ins>+    Node* argumentsChild = nullptr;
+    if (op != TailCallForwardVarargs)
+        argumentsChild = get(VirtualRegister(arguments));
</ins><span class="cx"> 
</span><del>-    if (op == TailCallVarargs) {
</del><ins>+    if (op == TailCallVarargs || op == TailCallForwardVarargs) {
</ins><span class="cx">         if (allInlineFramesAreTailCalls()) {
</span><del>-            addToGraph(op, OpInfo(data), OpInfo(), callTarget, get(VirtualRegister(arguments)), thisChild);
</del><ins>+            addToGraph(op, OpInfo(data), OpInfo(), callTarget, thisChild, argumentsChild);
</ins><span class="cx">             return Terminal;
</span><span class="cx">         }
</span><del>-        op = TailCallVarargsInlinedCaller;
</del><ins>+        op = op == TailCallVarargs ? TailCallVarargsInlinedCaller : TailCallForwardVarargsInlinedCaller;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, get(VirtualRegister(arguments)), thisChild);
</del><ins>+    Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, thisChild, argumentsChild);
</ins><span class="cx">     VirtualRegister resultReg(result);
</span><span class="cx">     if (resultReg.isValid())
</span><span class="cx">         set(resultReg, call);
</span><span class="lines">@@ -1767,9 +1771,12 @@
</span><span class="cx">                     data-&gt;offset = argumentsOffset;
</span><span class="cx">                     data-&gt;limit = maxNumArguments;
</span><span class="cx">                     data-&gt;mandatoryMinimum = mandatoryMinimum;
</span><del>-            
-                    addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
</del><span class="cx"> 
</span><ins>+                    if (callOp == TailCallForwardVarargs)
+                        addToGraph(ForwardVarargs, OpInfo(data));
+                    else
+                        addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
+
</ins><span class="cx">                     // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
</span><span class="cx">                     // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
</span><span class="cx">                     // callTargetNode because the other 2 are still in use and alive at this point.
</span><span class="lines">@@ -1962,7 +1969,7 @@
</span><span class="cx">         m_exitOK = true;
</span><span class="cx">         processSetLocalQueue(); // This only comes into play for intrinsics, since normal inlined code will leave an empty queue.
</span><span class="cx">         if (Node* terminal = m_currentBlock-&gt;terminal())
</span><del>-            ASSERT_UNUSED(terminal, terminal-&gt;op() == TailCall || terminal-&gt;op() == TailCallVarargs);
</del><ins>+            ASSERT_UNUSED(terminal, terminal-&gt;op() == TailCall || terminal-&gt;op() == TailCallVarargs || terminal-&gt;op() == TailCallForwardVarargs);
</ins><span class="cx">         else {
</span><span class="cx">             addToGraph(Jump);
</span><span class="cx">             landingBlocks.append(m_currentBlock);
</span><span class="lines">@@ -2003,7 +2010,7 @@
</span><span class="cx">     m_exitOK = true; // Origin changed, so it's fine to exit again.
</span><span class="cx">     processSetLocalQueue();
</span><span class="cx">     if (Node* terminal = m_currentBlock-&gt;terminal())
</span><del>-        ASSERT_UNUSED(terminal, terminal-&gt;op() == TailCall || terminal-&gt;op() == TailCallVarargs);
</del><ins>+        ASSERT_UNUSED(terminal, terminal-&gt;op() == TailCall || terminal-&gt;op() == TailCallVarargs || terminal-&gt;op() == TailCallForwardVarargs);
</ins><span class="cx">     else {
</span><span class="cx">         addToGraph(Jump);
</span><span class="cx">         landingBlocks.append(m_currentBlock);
</span><span class="lines">@@ -4437,17 +4444,15 @@
</span><span class="cx">             
</span><span class="cx">         case op_call:
</span><span class="cx">             handleCall(currentInstruction, Call, CallMode::Regular);
</span><del>-            // Verify that handleCall(), which could have inlined the callee, didn't trash m_currentInstruction.
-            ASSERT(m_currentInstruction == currentInstruction);
</del><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             NEXT_OPCODE(op_call);
</span><span class="cx"> 
</span><span class="cx">         case op_tail_call: {
</span><span class="cx">             flushForReturn();
</span><span class="cx">             Terminality terminality = handleCall(currentInstruction, TailCall, CallMode::Tail);
</span><del>-            // Verify that handleCall(), which could have inlined the callee, didn't trash m_currentInstruction.
-            ASSERT(m_currentInstruction == currentInstruction);
</del><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             // If the call is terminal then we should not parse any further bytecodes as the TailCall will exit the function.
</span><del>-            // If the call is not terminal, however, then we want the subsequent op_ret/op_jumpt to update metadata and clean
</del><ins>+            // If the call is not terminal, however, then we want the subsequent op_ret/op_jump to update metadata and clean
</ins><span class="cx">             // things up.
</span><span class="cx">             if (terminality == NonTerminal) {
</span><span class="cx">                 NEXT_OPCODE(op_tail_call);
</span><span class="lines">@@ -4458,18 +4463,21 @@
</span><span class="cx"> 
</span><span class="cx">         case op_construct:
</span><span class="cx">             handleCall(currentInstruction, Construct, CallMode::Construct);
</span><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             NEXT_OPCODE(op_construct);
</span><span class="cx">             
</span><span class="cx">         case op_call_varargs: {
</span><span class="cx">             handleVarargsCall(currentInstruction, CallVarargs, CallMode::Regular);
</span><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleVarargsCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             NEXT_OPCODE(op_call_varargs);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case op_tail_call_varargs: {
</span><span class="cx">             flushForReturn();
</span><span class="cx">             Terminality terminality = handleVarargsCall(currentInstruction, TailCallVarargs, CallMode::Tail);
</span><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleVarargsCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             // If the call is terminal then we should not parse any further bytecodes as the TailCall will exit the function.
</span><del>-            // If the call is not terminal, however, then we want the subsequent op_ret/op_jumpt to update metadata and clean
</del><ins>+            // If the call is not terminal, however, then we want the subsequent op_ret/op_jump to update metadata and clean
</ins><span class="cx">             // things up.
</span><span class="cx">             if (terminality == NonTerminal) {
</span><span class="cx">                 NEXT_OPCODE(op_tail_call_varargs);
</span><span class="lines">@@ -4477,9 +4485,27 @@
</span><span class="cx">                 LAST_OPCODE(op_tail_call_varargs);
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+
+        case op_tail_call_forward_arguments: {
+            // We need to make sure that we don't unbox our arguments here since that won't be
+            // done by the arguments object creation node as that node may not exist.
+            noticeArgumentsUse();
+            flushForReturn();
+            Terminality terminality = handleVarargsCall(currentInstruction, TailCallForwardVarargs, CallMode::Tail);
+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleVarargsCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
+            // If the call is terminal then we should not parse any further bytecodes as the TailCall will exit the function.
+            // If the call is not terminal, however, then we want the subsequent op_ret/op_jump to update metadata and clean
+            // things up.
+            if (terminality == NonTerminal) {
+                NEXT_OPCODE(op_tail_call);
+            } else {
+                LAST_OPCODE(op_tail_call);
+            }
+        }
</ins><span class="cx">             
</span><span class="cx">         case op_construct_varargs: {
</span><span class="cx">             handleVarargsCall(currentInstruction, ConstructVarargs, CallMode::Construct);
</span><ins>+            ASSERT_WITH_MESSAGE(m_currentInstruction == currentInstruction, &quot;handleVarargsCall, which may have inlined the callee, trashed m_currentInstruction&quot;);
</ins><span class="cx">             NEXT_OPCODE(op_construct_varargs);
</span><span class="cx">         }
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -200,6 +200,7 @@
</span><span class="cx">     case op_construct:
</span><span class="cx">     case op_call_varargs:
</span><span class="cx">     case op_tail_call_varargs:
</span><ins>+    case op_tail_call_forward_arguments:
</ins><span class="cx">     case op_construct_varargs:
</span><span class="cx">     case op_create_direct_arguments:
</span><span class="cx">     case op_create_scoped_arguments:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1321,7 +1321,6 @@
</span><span class="cx">         case PhantomCreateActivation:
</span><span class="cx">         case PhantomDirectArguments:
</span><span class="cx">         case PhantomClonedArguments:
</span><del>-        case ForwardVarargs:
</del><span class="cx">         case GetMyArgumentByVal:
</span><span class="cx">         case GetMyArgumentByValOutOfBounds:
</span><span class="cx">         case PutHint:
</span><span class="lines">@@ -1529,6 +1528,7 @@
</span><span class="cx">         case TailCallForwardVarargs:
</span><span class="cx">         case TailCallForwardVarargsInlinedCaller:
</span><span class="cx">         case LoadVarargs:
</span><ins>+        case ForwardVarargs:
</ins><span class="cx">         case ProfileControlFlow:
</span><span class="cx">         case NewObject:
</span><span class="cx">         case NewArrayBuffer:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -748,7 +748,51 @@
</span><span class="cx">         ASSERT(op() == CreateActivation);
</span><span class="cx">         return bitwise_cast&lt;FrozenValue*&gt;(m_opInfo2)-&gt;value();
</span><span class="cx">     }
</span><del>-     
</del><ins>+
+    bool hasArgumentsChild()
+    {
+        switch (op()) {
+        case GetMyArgumentByVal:
+        case GetMyArgumentByValOutOfBounds:
+        case LoadVarargs:
+        case ForwardVarargs:
+        case CallVarargs:
+        case CallForwardVarargs:
+        case ConstructVarargs:
+        case ConstructForwardVarargs:
+        case TailCallVarargs:
+        case TailCallForwardVarargs:
+        case TailCallVarargsInlinedCaller:
+        case TailCallForwardVarargsInlinedCaller:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    Edge&amp; argumentsChild()
+    {
+        switch (op()) {
+        case GetMyArgumentByVal:
+        case GetMyArgumentByValOutOfBounds:
+        case LoadVarargs:
+        case ForwardVarargs:
+            return child1();
+        case CallVarargs:
+        case CallForwardVarargs:
+        case ConstructVarargs:
+        case ConstructForwardVarargs:
+        case TailCallVarargs:
+        case TailCallForwardVarargs:
+        case TailCallVarargsInlinedCaller:
+        case TailCallForwardVarargsInlinedCaller:
+            return child3();
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return child1();
+        }
+    }
+
</ins><span class="cx">     bool containsMovHint()
</span><span class="cx">     {
</span><span class="cx">         switch (op()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPreciseLocalClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -115,7 +115,12 @@
</span><span class="cx">         case ConstructForwardVarargs:
</span><span class="cx">         case TailCallForwardVarargs:
</span><span class="cx">         case TailCallForwardVarargsInlinedCaller: {
</span><del>-            InlineCallFrame* inlineCallFrame = m_node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
</del><ins>+
+            InlineCallFrame* inlineCallFrame;
+            if (m_node-&gt;argumentsChild())
+                inlineCallFrame = m_node-&gt;argumentsChild()-&gt;origin.semantic.inlineCallFrame;
+            else
+                inlineCallFrame = m_node-&gt;origin.semantic.inlineCallFrame;
</ins><span class="cx">             if (!inlineCallFrame) {
</span><span class="cx">                 // Read the outermost arguments and argument count.
</span><span class="cx">                 for (unsigned i = m_graph.m_codeBlock-&gt;numParameters(); i-- &gt; 1;)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -972,7 +972,6 @@
</span><span class="cx">         case PhantomClonedArguments:
</span><span class="cx">         case GetMyArgumentByVal:
</span><span class="cx">         case GetMyArgumentByValOutOfBounds:
</span><del>-        case ForwardVarargs:
</del><span class="cx">         case PutHint:
</span><span class="cx">         case CheckStructureImmediate:
</span><span class="cx">         case MaterializeNewObject:
</span><span class="lines">@@ -1055,6 +1054,7 @@
</span><span class="cx">         case ZombieHint:
</span><span class="cx">         case ExitOK:
</span><span class="cx">         case LoadVarargs:
</span><ins>+        case ForwardVarargs:
</ins><span class="cx">         case CopyRest:
</span><span class="cx">         case PutDynamicVar:
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -5952,8 +5952,12 @@
</span><span class="cx"> void SpeculativeJIT::compileForwardVarargs(Node* node)
</span><span class="cx"> {
</span><span class="cx">     LoadVarargsData* data = node-&gt;loadVarargsData();
</span><del>-    InlineCallFrame* inlineCallFrame = node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
-        
</del><ins>+    InlineCallFrame* inlineCallFrame;
+    if (node-&gt;child1())
+        inlineCallFrame = node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
+    else
+        inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
+
</ins><span class="cx">     GPRTemporary length(this);
</span><span class="cx">     JSValueRegsTemporary temp(this);
</span><span class="cx">     GPRReg lengthGPR = length.gpr();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -729,7 +729,8 @@
</span><span class="cx">         
</span><span class="cx">         if (isForwardVarargs) {
</span><span class="cx">             flushRegisters();
</span><del>-            use(node-&gt;child2());
</del><ins>+            if (node-&gt;child3())
+                use(node-&gt;child3());
</ins><span class="cx">             
</span><span class="cx">             GPRReg scratchGPR1;
</span><span class="cx">             GPRReg scratchGPR2;
</span><span class="lines">@@ -741,7 +742,12 @@
</span><span class="cx">             
</span><span class="cx">             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
</span><span class="cx">             JITCompiler::JumpList slowCase;
</span><del>-            emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node-&gt;child2()-&gt;origin.semantic.inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</del><ins>+            InlineCallFrame* inlineCallFrame;
+            if (node-&gt;child3())
+                inlineCallFrame = node-&gt;child3()-&gt;origin.semantic.inlineCallFrame;
+            else
+                inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
+            emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</ins><span class="cx">             JITCompiler::Jump done = m_jit.jump();
</span><span class="cx">             slowCase.link(&amp;m_jit);
</span><span class="cx">             callOperation(operationThrowStackOverflowForVarargs);
</span><span class="lines">@@ -759,7 +765,7 @@
</span><span class="cx">             auto loadArgumentsGPR = [&amp;] (GPRReg reservedGPR) {
</span><span class="cx">                 if (reservedGPR != InvalidGPRReg)
</span><span class="cx">                     lock(reservedGPR);
</span><del>-                JSValueOperand arguments(this, node-&gt;child2());
</del><ins>+                JSValueOperand arguments(this, node-&gt;child3());
</ins><span class="cx">                 argumentsTagGPR = arguments.tagGPR();
</span><span class="cx">                 argumentsPayloadGPR = arguments.payloadGPR();
</span><span class="cx">                 if (reservedGPR != InvalidGPRReg)
</span><span class="lines">@@ -798,7 +804,7 @@
</span><span class="cx">         
</span><span class="cx">         // We don't need the arguments array anymore.
</span><span class="cx">         if (isVarargs)
</span><del>-            use(node-&gt;child2());
</del><ins>+            use(node-&gt;child3());
</ins><span class="cx"> 
</span><span class="cx">         // Now set up the &quot;this&quot; argument.
</span><span class="cx">         JSValueOperand thisArgument(this, node-&gt;child3());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -701,7 +701,8 @@
</span><span class="cx">         
</span><span class="cx">         if (isForwardVarargs) {
</span><span class="cx">             flushRegisters();
</span><del>-            use(node-&gt;child2());
</del><ins>+            if (node-&gt;child3())
+                use(node-&gt;child3());
</ins><span class="cx">             
</span><span class="cx">             GPRReg scratchGPR1;
</span><span class="cx">             GPRReg scratchGPR2;
</span><span class="lines">@@ -713,7 +714,12 @@
</span><span class="cx">             
</span><span class="cx">             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
</span><span class="cx">             JITCompiler::JumpList slowCase;
</span><del>-            emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node-&gt;child2()-&gt;origin.semantic.inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</del><ins>+            InlineCallFrame* inlineCallFrame;
+            if (node-&gt;child3())
+                inlineCallFrame = node-&gt;child3()-&gt;origin.semantic.inlineCallFrame;
+            else
+                inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
+            emitSetupVarargsFrameFastCase(m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</ins><span class="cx">             JITCompiler::Jump done = m_jit.jump();
</span><span class="cx">             slowCase.link(&amp;m_jit);
</span><span class="cx">             callOperation(operationThrowStackOverflowForVarargs);
</span><span class="lines">@@ -730,7 +736,7 @@
</span><span class="cx">             auto loadArgumentsGPR = [&amp;] (GPRReg reservedGPR) {
</span><span class="cx">                 if (reservedGPR != InvalidGPRReg)
</span><span class="cx">                     lock(reservedGPR);
</span><del>-                JSValueOperand arguments(this, node-&gt;child2());
</del><ins>+                JSValueOperand arguments(this, node-&gt;child3());
</ins><span class="cx">                 argumentsGPR = arguments.gpr();
</span><span class="cx">                 if (reservedGPR != InvalidGPRReg)
</span><span class="cx">                     unlock(reservedGPR);
</span><span class="lines">@@ -767,10 +773,10 @@
</span><span class="cx">         
</span><span class="cx">         // We don't need the arguments array anymore.
</span><span class="cx">         if (isVarargs)
</span><del>-            use(node-&gt;child2());
</del><ins>+            use(node-&gt;child3());
</ins><span class="cx"> 
</span><span class="cx">         // Now set up the &quot;this&quot; argument.
</span><del>-        JSValueOperand thisArgument(this, node-&gt;child3());
</del><ins>+        JSValueOperand thisArgument(this, node-&gt;child2());
</ins><span class="cx">         GPRReg thisArgumentGPR = thisArgument.gpr();
</span><span class="cx">         thisArgument.use();
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -137,7 +137,7 @@
</span><span class="cx">             case ConstructVarargs:
</span><span class="cx">             case TailCallVarargs:
</span><span class="cx">             case TailCallVarargsInlinedCaller:
</span><del>-                if (node-&gt;child1() == candidate || node-&gt;child3() == candidate) {
</del><ins>+                if (node-&gt;child1() == candidate || node-&gt;child2() == candidate) {
</ins><span class="cx">                     if (verbose)
</span><span class="cx">                         dataLog(&quot;    Escape at &quot;, node, &quot;\n&quot;);
</span><span class="cx">                     return;
</span><span class="lines">@@ -274,25 +274,25 @@
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="cx">             case CallVarargs:
</span><del>-                if (node-&gt;child2() != candidate)
</del><ins>+                if (node-&gt;child3() != candidate)
</ins><span class="cx">                     break;
</span><span class="cx">                 node-&gt;setOpAndDefaultFlags(CallForwardVarargs);
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="cx">             case ConstructVarargs:
</span><del>-                if (node-&gt;child2() != candidate)
</del><ins>+                if (node-&gt;child3() != candidate)
</ins><span class="cx">                     break;
</span><span class="cx">                 node-&gt;setOpAndDefaultFlags(ConstructForwardVarargs);
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case TailCallVarargs:
</span><del>-                if (node-&gt;child2() != candidate)
</del><ins>+                if (node-&gt;child3() != candidate)
</ins><span class="cx">                     break;
</span><span class="cx">                 node-&gt;setOpAndDefaultFlags(TailCallForwardVarargs);
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><span class="cx">             case TailCallVarargsInlinedCaller:
</span><del>-                if (node-&gt;child2() != candidate)
</del><ins>+                if (node-&gt;child3() != candidate)
</ins><span class="cx">                     break;
</span><span class="cx">                 node-&gt;setOpAndDefaultFlags(TailCallForwardVarargsInlinedCaller);
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -5197,7 +5197,7 @@
</span><span class="cx">     {
</span><span class="cx">         Node* node = m_node;
</span><span class="cx">         LValue jsCallee = lowJSValue(m_node-&gt;child1());
</span><del>-        LValue thisArg = lowJSValue(m_node-&gt;child3());
</del><ins>+        LValue thisArg = lowJSValue(m_node-&gt;child2());
</ins><span class="cx">         
</span><span class="cx">         LValue jsArguments = nullptr;
</span><span class="cx">         bool forwarding = false;
</span><span class="lines">@@ -5207,7 +5207,7 @@
</span><span class="cx">         case TailCallVarargs:
</span><span class="cx">         case TailCallVarargsInlinedCaller:
</span><span class="cx">         case ConstructVarargs:
</span><del>-            jsArguments = lowJSValue(node-&gt;child2());
</del><ins>+            jsArguments = lowJSValue(node-&gt;child3());
</ins><span class="cx">             break;
</span><span class="cx">         case CallForwardVarargs:
</span><span class="cx">         case TailCallForwardVarargs:
</span><span class="lines">@@ -5360,7 +5360,12 @@
</span><span class="cx">                     jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2);
</span><span class="cx">                     
</span><span class="cx">                     CCallHelpers::JumpList slowCase;
</span><del>-                    emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node-&gt;child2()-&gt;origin.semantic.inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</del><ins>+                    InlineCallFrame* inlineCallFrame;
+                    if (node-&gt;child3())
+                        inlineCallFrame = node-&gt;child3()-&gt;origin.semantic.inlineCallFrame;
+                    else
+                        inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
+                    emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data-&gt;firstVarArgOffset, slowCase);
</ins><span class="cx"> 
</span><span class="cx">                     CCallHelpers::Jump done = jit.jump();
</span><span class="cx">                     slowCase.link(&amp;jit);
</span><span class="lines">@@ -5504,7 +5509,11 @@
</span><span class="cx">     void compileForwardVarargs()
</span><span class="cx">     {
</span><span class="cx">         LoadVarargsData* data = m_node-&gt;loadVarargsData();
</span><del>-        InlineCallFrame* inlineCallFrame = m_node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
</del><ins>+        InlineCallFrame* inlineCallFrame;
+        if (m_node-&gt;child1())
+            inlineCallFrame = m_node-&gt;child1()-&gt;origin.semantic.inlineCallFrame;
+        else
+            inlineCallFrame = m_node-&gt;origin.semantic.inlineCallFrame;
</ins><span class="cx">         
</span><span class="cx">         LValue length = getArgumentsLength(inlineCallFrame).value;
</span><span class="cx">         LValue lengthIncludingThis = m_out.add(length, m_out.constInt32(1 - data-&gt;offset));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -235,6 +235,16 @@
</span><span class="cx">     return length;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+unsigned sizeFrameForForwardArguments(CallFrame* callFrame, JSStack* stack, unsigned numUsedStackSlots)
+{
+    unsigned length = callFrame-&gt;argumentCount();
+    CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
+    if (!stack-&gt;ensureCapacityFor(calleeFrame-&gt;registers()))
+        throwStackOverflowError(callFrame);
+
+    return length;
+}
+
</ins><span class="cx"> unsigned sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
</span><span class="cx"> {
</span><span class="cx">     unsigned length = sizeOfVarargs(callFrame, arguments, firstVarArgOffset);
</span><span class="lines">@@ -295,6 +305,22 @@
</span><span class="cx">     newCallFrame-&gt;setThisValue(thisValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length)
+{
+    ASSERT(length == execCaller-&gt;argumentCount());
+    unsigned offset = execCaller-&gt;argumentOffset(0) * sizeof(Register);
+    memcpy(reinterpret_cast&lt;char*&gt;(execCallee) + offset, reinterpret_cast&lt;char*&gt;(execCaller) + offset, length * sizeof(Register));
+    execCallee-&gt;setArgumentCountIncludingThis(length + 1);
+}
+
+void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length)
+{
+    setupForwardArgumentsFrame(execCaller, execCallee, length);
+    execCallee-&gt;setThisValue(thisValue);
+}
+
+    
+
</ins><span class="cx"> Interpreter::Interpreter(VM&amp; vm)
</span><span class="cx">     : m_vm(vm)
</span><span class="cx">     , m_stack(vm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -274,9 +274,12 @@
</span><span class="cx">     unsigned sizeOfVarargs(CallFrame* exec, JSValue arguments, uint32_t firstVarArgOffset);
</span><span class="cx">     static const unsigned maxArguments = 0x10000;
</span><span class="cx">     unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
</span><ins>+    unsigned sizeFrameForForwardArguments(CallFrame* exec, JSStack*, unsigned numUsedStackSlots);
</ins><span class="cx">     void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length);
</span><span class="cx">     void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
</span><span class="cx">     void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
</span><ins>+    void setupForwardArgumentsFrame(CallFrame* execCaller, CallFrame* execCallee, uint32_t length);
+    void setupForwardArgumentsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, uint32_t length);
</ins><span class="cx">     
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -215,6 +215,7 @@
</span><span class="cx">         DEFINE_OP(op_call_eval)
</span><span class="cx">         DEFINE_OP(op_call_varargs)
</span><span class="cx">         DEFINE_OP(op_tail_call_varargs)
</span><ins>+        DEFINE_OP(op_tail_call_forward_arguments)
</ins><span class="cx">         DEFINE_OP(op_construct_varargs)
</span><span class="cx">         DEFINE_OP(op_catch)
</span><span class="cx">         DEFINE_OP(op_construct)
</span><span class="lines">@@ -415,6 +416,7 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_call_eval)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_call_varargs)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_tail_call_varargs)
</span><ins>+        DEFINE_SLOWCASE_OP(op_tail_call_forward_arguments)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_construct_varargs)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_construct)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_to_this)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -317,7 +317,7 @@
</span><span class="cx"> 
</span><span class="cx">         void compileOpCall(OpcodeID, Instruction*, unsigned callLinkInfoIndex);
</span><span class="cx">         void compileOpCallSlowCase(OpcodeID, Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;, unsigned callLinkInfoIndex);
</span><del>-        void compileSetupVarargsFrame(Instruction*, CallLinkInfo*);
</del><ins>+        void compileSetupVarargsFrame(OpcodeID, Instruction*, CallLinkInfo*);
</ins><span class="cx">         void compileCallEval(Instruction*);
</span><span class="cx">         void compileCallEvalSlowCase(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitPutCallResult(Instruction*);
</span><span class="lines">@@ -483,6 +483,7 @@
</span><span class="cx">         void emit_op_call_eval(Instruction*);
</span><span class="cx">         void emit_op_call_varargs(Instruction*);
</span><span class="cx">         void emit_op_tail_call_varargs(Instruction*);
</span><ins>+        void emit_op_tail_call_forward_arguments(Instruction*);
</ins><span class="cx">         void emit_op_construct_varargs(Instruction*);
</span><span class="cx">         void emit_op_catch(Instruction*);
</span><span class="cx">         void emit_op_construct(Instruction*);
</span><span class="lines">@@ -614,6 +615,7 @@
</span><span class="cx">         void emitSlow_op_call_eval(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_call_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_tail_call_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_tail_call_forward_arguments(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx">         void emitSlow_op_construct_varargs(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_construct(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_to_this(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">     emitPutVirtualRegister(dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::compileSetupVarargsFrame(Instruction* instruction, CallLinkInfo* info)
</del><ins>+void JIT::compileSetupVarargsFrame(OpcodeID opcode, Instruction* instruction, CallLinkInfo* info)
</ins><span class="cx"> {
</span><span class="cx">     int thisValue = instruction[3].u.operand;
</span><span class="cx">     int arguments = instruction[4].u.operand;
</span><span class="lines">@@ -61,12 +61,22 @@
</span><span class="cx">     int firstVarArgOffset = instruction[6].u.operand;
</span><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(arguments, regT1);
</span><del>-    callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset);
</del><ins>+    Z_JITOperation_EJZZ sizeOperation;
+    if (opcode == op_tail_call_forward_arguments)
+        sizeOperation = operationSizeFrameForForwardArguments;
+    else
+        sizeOperation = operationSizeFrameForVarargs;
+    callOperation(sizeOperation, regT1, -firstFreeRegister, firstVarArgOffset);
</ins><span class="cx">     move(TrustedImm32(-firstFreeRegister), regT1);
</span><span class="cx">     emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
</span><span class="cx">     addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), regT1, stackPointerRegister);
</span><span class="cx">     emitGetVirtualRegister(arguments, regT2);
</span><del>-    callOperation(operationSetupVarargsFrame, regT1, regT2, firstVarArgOffset, regT0);
</del><ins>+    F_JITOperation_EFJZZ setupOperation;
+    if (opcode == op_tail_call_forward_arguments)
+        setupOperation = operationSetupForwardArgumentsFrame;
+    else
+        setupOperation = operationSetupVarargsFrame;
+    callOperation(setupOperation, regT1, regT2, firstVarArgOffset, regT0);
</ins><span class="cx">     move(returnValueGPR, regT1);
</span><span class="cx"> 
</span><span class="cx">     // Profile the argument count.
</span><span class="lines">@@ -147,11 +157,13 @@
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call), call_and_tail_call_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_varargs), call_and_tail_call_varargs_opcodes_must_be_same_length);
</span><ins>+    COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call_forward_arguments), call_and_tail_call_forward_arguments_opcodes_must_be_same_length);
+
</ins><span class="cx">     CallLinkInfo* info;
</span><span class="cx">     if (opcodeID != op_call_eval)
</span><span class="cx">         info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
-        compileSetupVarargsFrame(instruction, info);
</del><ins>+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
+        compileSetupVarargsFrame(opcodeID, instruction, info);
</ins><span class="cx">     else {
</span><span class="cx">         int argCount = instruction[3].u.operand;
</span><span class="cx">         int registerOffset = -instruction[4].u.operand;
</span><span class="lines">@@ -171,8 +183,8 @@
</span><span class="cx">     uint32_t bytecodeOffset = instruction - m_codeBlock-&gt;instructions().begin();
</span><span class="cx">     uint32_t locationBits = CallSiteIndex(bytecodeOffset).bits();
</span><span class="cx">     store32(TrustedImm32(locationBits), Address(callFrameRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + TagOffset));
</span><ins>+
</ins><span class="cx">     emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
</span><del>-
</del><span class="cx">     store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast&lt;int&gt;(sizeof(Register)) - sizeof(CallerFrameAndPC)));
</span><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_call_eval) {
</span><span class="lines">@@ -211,7 +223,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (opcodeID == op_tail_call_varargs) {
</del><ins>+    if (opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) {
</ins><span class="cx">         emitRestoreCalleeSaves();
</span><span class="cx">         prepareForTailCallSlow();
</span><span class="cx">         m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
</span><span class="lines">@@ -237,7 +249,7 @@
</span><span class="cx"> 
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><del>-    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs)
</del><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
</ins><span class="cx">         emitRestoreCalleeSaves();
</span><span class="cx"> 
</span><span class="cx">     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</span><span class="lines">@@ -282,6 +294,11 @@
</span><span class="cx">     compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_tail_call_forward_arguments(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call_forward_arguments, currentInstruction, m_callLinkInfoIndex++);
+}
+
</ins><span class="cx"> void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_construct_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="lines">@@ -316,6 +333,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emitSlow_op_tail_call_forward_arguments(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call_forward_arguments, currentInstruction, iter, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -87,6 +87,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCallSlowCase(op_tail_call_varargs, currentInstruction, iter, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emitSlow_op_tail_call_forward_arguments(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    compileOpCallSlowCase(op_tail_call_forward_arguments, currentInstruction, iter, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emitSlow_op_construct_varargs(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="lines">@@ -122,6 +127,11 @@
</span><span class="cx"> {
</span><span class="cx">     compileOpCall(op_tail_call_varargs, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><ins>+
+void JIT::emit_op_tail_call_forward_arguments(Instruction* currentInstruction)
+{
+    compileOpCall(op_tail_call_forward_arguments, currentInstruction, m_callLinkInfoIndex++);
+}
</ins><span class="cx">     
</span><span class="cx"> void JIT::emit_op_construct_varargs(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="lines">@@ -133,7 +143,7 @@
</span><span class="cx">     compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::compileSetupVarargsFrame(Instruction* instruction, CallLinkInfo* info)
</del><ins>+void JIT::compileSetupVarargsFrame(OpcodeID opcode, Instruction* instruction, CallLinkInfo* info)
</ins><span class="cx"> {
</span><span class="cx">     int thisValue = instruction[3].u.operand;
</span><span class="cx">     int arguments = instruction[4].u.operand;
</span><span class="lines">@@ -141,12 +151,22 @@
</span><span class="cx">     int firstVarArgOffset = instruction[6].u.operand;
</span><span class="cx"> 
</span><span class="cx">     emitLoad(arguments, regT1, regT0);
</span><del>-    callOperation(operationSizeFrameForVarargs, regT1, regT0, -firstFreeRegister, firstVarArgOffset);
</del><ins>+    Z_JITOperation_EJZZ sizeOperation;
+    if (opcode == op_tail_call_forward_arguments)
+        sizeOperation = operationSizeFrameForForwardArguments;
+    else
+        sizeOperation = operationSizeFrameForVarargs;
+    callOperation(sizeOperation, regT1, regT0, -firstFreeRegister, firstVarArgOffset);
</ins><span class="cx">     move(TrustedImm32(-firstFreeRegister), regT1);
</span><span class="cx">     emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
</span><span class="cx">     addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), regT1, stackPointerRegister);
</span><span class="cx">     emitLoad(arguments, regT2, regT4);
</span><del>-    callOperation(operationSetupVarargsFrame, regT1, regT2, regT4, firstVarArgOffset, regT0);
</del><ins>+    F_JITOperation_EFJZZ setupOperation;
+    if (opcode == op_tail_call_forward_arguments)
+        setupOperation = operationSetupForwardArgumentsFrame;
+    else
+        setupOperation = operationSetupVarargsFrame;
+    callOperation(setupOperation, regT1, regT2, regT4, firstVarArgOffset, regT0);
</ins><span class="cx">     move(returnValueGPR, regT1);
</span><span class="cx"> 
</span><span class="cx">     // Profile the argument count.
</span><span class="lines">@@ -229,8 +249,8 @@
</span><span class="cx">     CallLinkInfo* info = nullptr;
</span><span class="cx">     if (opcodeID != op_call_eval)
</span><span class="cx">         info = m_codeBlock-&gt;addCallLinkInfo();
</span><del>-    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs)
-        compileSetupVarargsFrame(instruction, info);
</del><ins>+    if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments)
+        compileSetupVarargsFrame(opcodeID, instruction, info);
</ins><span class="cx">     else {
</span><span class="cx">         int argCount = instruction[3].u.operand;
</span><span class="cx">         int registerOffset = -instruction[4].u.operand;
</span><span class="lines">@@ -277,7 +297,7 @@
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="cx"> 
</span><span class="cx">     checkStackPointerAlignment();
</span><del>-    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
</del><ins>+    if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs || opcodeID == op_tail_call_forward_arguments) {
</ins><span class="cx">         prepareForTailCallSlow();
</span><span class="cx">         m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1917,6 +1917,14 @@
</span><span class="cx">     return JSValue::encode(jsBoolean(result));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+int32_t JIT_OPERATION operationSizeFrameForForwardArguments(ExecState* exec, EncodedJSValue, int32_t numUsedStackSlots, int32_t)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSStack* stack = &amp;exec-&gt;interpreter()-&gt;stack();
+    return sizeFrameForForwardArguments(exec, stack, numUsedStackSlots);
+}
+
</ins><span class="cx"> int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="lines">@@ -1926,6 +1934,14 @@
</span><span class="cx">     return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CallFrame* JIT_OPERATION operationSetupForwardArgumentsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue, int32_t, int32_t length)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    setupForwardArgumentsFrame(exec, newCallFrame, length);
+    return newCallFrame;
+}
+
</ins><span class="cx"> CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -380,7 +380,9 @@
</span><span class="cx"> size_t JIT_OPERATION operationDeleteByVal(ExecState*, EncodedJSValue base, EncodedJSValue target) WTF_INTERNAL;
</span><span class="cx"> JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState*, EncodedJSValue, EncodedJSValue proto) WTF_INTERNAL;
</span><ins>+int32_t JIT_OPERATION operationSizeFrameForForwardArguments(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
</ins><span class="cx"> int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
</span><ins>+CallFrame* JIT_OPERATION operationSetupForwardArgumentsFrame(ExecState*, CallFrame*, EncodedJSValue, int32_t, int32_t length) WTF_INTERNAL;
</ins><span class="cx"> CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset, int32_t length) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToObject(ExecState*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1364,47 +1364,69 @@
</span><span class="cx">     LLINT_RETURN_CALLEE_FRAME(execCallee);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
</del><ins>+LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_forward_arguments)
</ins><span class="cx"> {
</span><del>-    LLINT_BEGIN_NO_SET_PC();
</del><ins>+    LLINT_BEGIN();
</ins><span class="cx">     // This needs to:
</span><del>-    // - Figure out what to call and compile it if necessary.
-    // - Return a tuple of machine code address to call and the new call frame.
-    
-    JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
-    
-    ExecState* execCallee = vm.newCallFrameReturnValue;
</del><ins>+    // - Set up a call frame with the same arguments as the current frame.
</ins><span class="cx"> 
</span><del>-    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
</del><ins>+    unsigned numUsedStackSlots = -pc[5].u.operand;
+
+    unsigned arguments = sizeFrameForForwardArguments(exec, &amp;vm.interpreter-&gt;stack(), numUsedStackSlots);
</ins><span class="cx">     LLINT_CALL_CHECK_EXCEPTION(exec, exec);
</span><del>-    
-    execCallee-&gt;uncheckedR(JSStack::Callee) = calleeAsValue;
-    execCallee-&gt;setCallerFrame(exec);
-    exec-&gt;setCurrentVPC(pc);
-    
-    return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
</del><ins>+
+    ExecState* execCallee = calleeFrameForVarargs(exec, numUsedStackSlots, arguments + 1);
+
+    vm.varargsLength = arguments;
+    vm.newCallFrameReturnValue = execCallee;
+
+    LLINT_RETURN_CALLEE_FRAME(execCallee);
</ins><span class="cx"> }
</span><del>-    
-LLINT_SLOW_PATH_DECL(slow_path_construct_varargs)
</del><ins>+
+enum class SetArgumentsWith {
+    Object,
+    CurrentArguments
+};
+
+inline SlowPathReturnType varargsSetup(ExecState* exec, Instruction* pc, CodeSpecializationKind kind, SetArgumentsWith set)
</ins><span class="cx"> {
</span><span class="cx">     LLINT_BEGIN_NO_SET_PC();
</span><span class="cx">     // This needs to:
</span><span class="cx">     // - Figure out what to call and compile it if necessary.
</span><span class="cx">     // - Return a tuple of machine code address to call and the new call frame.
</span><del>-    
</del><ins>+
</ins><span class="cx">     JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
</span><del>-    
</del><ins>+
</ins><span class="cx">     ExecState* execCallee = vm.newCallFrameReturnValue;
</span><del>-    
-    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
-    LLINT_CALL_CHECK_EXCEPTION(exec, exec);
-    
</del><ins>+
+    if (set == SetArgumentsWith::Object) {
+        setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
+        LLINT_CALL_CHECK_EXCEPTION(exec, exec);
+    } else
+        setupForwardArgumentsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), vm.varargsLength);
+
+    execCallee-&gt;setCallerFrame(exec);
</ins><span class="cx">     execCallee-&gt;uncheckedR(JSStack::Callee) = calleeAsValue;
</span><del>-    execCallee-&gt;setCallerFrame(exec);
</del><span class="cx">     exec-&gt;setCurrentVPC(pc);
</span><del>-    
-    return setUpCall(execCallee, pc, CodeForConstruct, calleeAsValue);
</del><ins>+
+    return setUpCall(execCallee, pc, kind, calleeAsValue);
</ins><span class="cx"> }
</span><ins>+
+LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
+{
+    return varargsSetup(exec, pc, CodeForCall, SetArgumentsWith::Object);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_tail_call_forward_arguments)
+{
+    return varargsSetup(exec, pc, CodeForCall, SetArgumentsWith::CurrentArguments);
+}
+
+LLINT_SLOW_PATH_DECL(slow_path_construct_varargs)
+{
+    return varargsSetup(exec, pc, CodeForConstruct, SetArgumentsWith::Object);
+}
+
</ins><span class="cx">     
</span><span class="cx"> LLINT_SLOW_PATH_DECL(slow_path_call_eval)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -107,7 +107,9 @@
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_size_frame_for_varargs);
</span><ins>+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_size_frame_for_forward_arguments);
</ins><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_varargs);
</span><ins>+LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tail_call_forward_arguments);
</ins><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_construct_varargs);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_call_eval);
</span><span class="cx"> LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_tear_off_arguments);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (202002 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-06-13 20:06:22 UTC (rev 202002)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -1529,8 +1529,8 @@
</span><span class="cx">     traceExecution()
</span><span class="cx">     doCall(_llint_slow_path_construct, prepareForRegularCall)
</span><span class="cx"> 
</span><del>-macro doCallVarargs(slowPath, prepareCall)
-    callSlowPath(_llint_slow_path_size_frame_for_varargs)
</del><ins>+macro doCallVarargs(frameSlowPath, slowPath, prepareCall)
+    callSlowPath(frameSlowPath)
</ins><span class="cx">     branchIfException(_llint_throw_from_slow_path_trampoline)
</span><span class="cx">     # calleeFrame in r1
</span><span class="cx">     if JSVALUE64
</span><span class="lines">@@ -1549,18 +1549,27 @@
</span><span class="cx"> 
</span><span class="cx"> _llint_op_call_varargs:
</span><span class="cx">     traceExecution()
</span><del>-    doCallVarargs(_llint_slow_path_call_varargs, prepareForRegularCall)
</del><ins>+    doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForRegularCall)
</ins><span class="cx"> 
</span><span class="cx"> _llint_op_tail_call_varargs:
</span><span class="cx">     traceExecution()
</span><span class="cx">     checkSwitchToJITForEpilogue()
</span><span class="cx">     # We lie and perform the tail call instead of preparing it since we can't
</span><span class="cx">     # prepare the frame for a call opcode
</span><del>-    doCallVarargs(_llint_slow_path_call_varargs, prepareForTailCall)
</del><ins>+    doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_call_varargs, prepareForTailCall)
</ins><span class="cx"> 
</span><ins>+
+_llint_op_tail_call_forward_arguments:
+    traceExecution()
+    checkSwitchToJITForEpilogue()
+    # We lie and perform the tail call instead of preparing it since we can't
+    # prepare the frame for a call opcode
+    doCallVarargs(_llint_slow_path_size_frame_for_forward_arguments, _llint_slow_path_tail_call_forward_arguments, prepareForTailCall)
+
+
</ins><span class="cx"> _llint_op_construct_varargs:
</span><span class="cx">     traceExecution()
</span><del>-    doCallVarargs(_llint_slow_path_construct_varargs, prepareForRegularCall)
</del><ins>+    doCallVarargs(_llint_slow_path_size_frame_for_varargs, _llint_slow_path_construct_varargs, prepareForRegularCall)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> _llint_op_call_eval:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstailCallForwardArgumentsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/tailCallForwardArguments.js (0 => 202003)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/tailCallForwardArguments.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/tailCallForwardArguments.js        2016-06-13 21:05:36 UTC (rev 202003)
</span><span class="lines">@@ -0,0 +1,161 @@
</span><ins>+// This is pretty bad but I need a private name.
+var putFuncToPrivateName = createBuiltin(`(function(func) { @arrayIteratorIsDone = func })`)
+putFuncToPrivateName(function (a,b) { return b; })
+
+function createTailCallForwardingFuncWith(body, thisValue) {
+    return createBuiltin(`(function (a) {
+        &quot;use strict&quot;;
+
+        ${body}
+
+        return @tailCallForwardArguments(@arrayIteratorIsDone, ${thisValue});
+    })`);
+}
+
+var foo = createTailCallForwardingFuncWith(&quot;&quot;, &quot;@undefined&quot;);
+
+function baz() {
+    return foo.call(true, 7);
+}
+noInline(baz);
+
+
+
+var fooNoInline = createTailCallForwardingFuncWith(&quot;&quot;, &quot;@undefined&quot;);
+noInline(foo);
+
+for (let i = 0; i &lt; 100000; i++) {
+    if (baz.call() !== undefined)
+        throw new Error(i);
+    if (fooNoInline.call(undefined, 3) !== undefined)
+        throw new Error(i);
+}
+
+putFuncToPrivateName(function () { &quot;use strict&quot;; return { thisValue: this, argumentsValue: arguments};  });
+var foo2 = createTailCallForwardingFuncWith(&quot;&quot;, &quot;this&quot;);
+var fooNI2 = createTailCallForwardingFuncWith(&quot;&quot;, &quot;this&quot;);
+noInline(fooNI2);
+
+function baz2() {
+    return foo2.call(true, 7);
+}
+noInline(baz2);
+
+for (let i = 0; i &lt; 100000; i++) {
+    let result = foo2.call(true, 7);
+    if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
+        throw new Error(i);
+    result = baz2.call();
+    if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
+        throw new Error(i);
+    result = fooNI2.call(true, 7);
+    if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7)
+        throw new Error(i);
+}
+
+putFuncToPrivateName(function () { &quot;use strict&quot;; return this;  });
+var foo3 = createTailCallForwardingFuncWith(&quot;&quot;, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+var fooNI3 = createTailCallForwardingFuncWith(&quot;&quot;, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+noInline(fooNI3);
+function baz3() {
+    return foo3.call(true, 7);
+}
+noInline(baz3);
+
+for (let i = 0; i &lt; 100000; i++) {
+    let result = foo3.call(true, 7);
+    if (result.thisValue !== true)
+        throw new Error(i);
+    result = baz3.call();
+    if (result.thisValue !== true)
+        throw new Error(i);
+    result = fooNI3.call(true, 7);
+    if (result.thisValue !== true)
+        throw new Error(i);
+}
+
+
+putFuncToPrivateName(function () { &quot;use strict&quot;; return this;  });
+let bodyText = `
+for (let i = 0; i &lt; 100; i++) {
+    if (a + i === 100)
+        return a;
+}
+`;
+var foo4 = createTailCallForwardingFuncWith(bodyText, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+var fooNI4 = createTailCallForwardingFuncWith(bodyText, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+noInline(fooNI4);
+function baz4() {
+    return foo4.call(true, 0);
+}
+noInline(baz4);
+
+for (let i = 0; i &lt; 100000; i++) {
+    let result = foo4.call(true, 0);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = baz4.call();
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = fooNI4.call(true, 0);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = fooNI4.call(true, 1);
+    if (result !== 1)
+        throw new Error(i);
+    result = fooNI4.call(true, &quot;&quot;);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+}
+
+var testFunc = function () { &quot;use strict&quot;; return this;  }
+noInline(testFunc);
+putFuncToPrivateName(testFunc);
+
+var foo5 = createTailCallForwardingFuncWith(bodyText, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+var fooNI5 = createTailCallForwardingFuncWith(bodyText, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+noInline(fooNI5);
+function baz5() {
+    return foo5.call(true, 0);
+}
+noInline(baz5);
+
+for (let i = 0; i &lt; 100000; i++) {
+    let result = foo5.call(true, 0);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = baz5.call();
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = fooNI5.call(true, 0);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+    result = fooNI5.call(true, 1);
+    if (result !== 1)
+        throw new Error(i);
+    result = fooNI5.call(true, &quot;&quot;);
+    if (result.thisValue !== true || result.otherValue !== &quot;hello&quot;)
+        throw new Error(i);
+}
+
+putFuncToPrivateName(function() { return arguments; });
+var foo6 = createTailCallForwardingFuncWith(bodyText, &quot;{ thisValue: this, otherValue: 'hello'} &quot;);
+function baz6() {
+    &quot;use strict&quot;
+    return foo6.apply(this, arguments);
+}
+noInline(baz6);
+
+function arrayEq(a, b) {
+    if (a.length !== b.length)
+        throw new Error();
+    for (let i = 0; i &lt; a.length; i++) {
+        if (a[i] !== b[i])
+            throw new Error();
+    }
+}
+let args = [&quot;a&quot;, {}, [], Symbol(), 1, 1.234, undefined, null];
+for (let i = 0; i &lt; 100000; i++) {
+    let result = baz6.apply(undefined, args);
+    arrayEq(result, args);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>