<!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>[198154] 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/198154">198154</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-03-14 13:55:15 -0700 (Mon, 14 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>We should be able to eliminate cloned arguments objects that use the length property
https://bugs.webkit.org/show_bug.cgi?id=155391

Reviewed by Geoffrey Garen.

Previously if a programmer tried to use arguments.length in a strict function we would not eliminate the
arguments object. We were unable to eliminate the arguments object because the user would get a cloned arguments
object, which does not special case the length property. Thus, in order to get arguments elimination for cloned
we need to add a special case. There are two things that need to happen for the elimination to succeed.

First, we need to eliminate the CheckStructure blocking the GetByOffset for the length property. In order to
eliminate the check structure we need to prove to the Abstract Interpreter that this structure check is
unnesssary. This didn't occur before for two reasons: 1) CreateClonedArguments did not set the structure it
produced. 2) Even if CreateClonedArguments provided the global object's cloned arguments structure we would
transition the new argements object when we added the length property during construction. To fix the second
problem we now pre-assign a slot on clonedArgumentsStructure for the length property. Additionally, in order to
prevent future transitions of the structure we need to choose an indexing type for the structure. Since, not
eliminating the arguments object is so expensive we choose to have all cloned arguments start with continuous
indexing type, this avoids transitioning when otherwise we would not have to. In the future we should be smarter
about choosing the indexing type but since its relatively rare to have a arguments object escape we don't worry
about this for now.

Additionally, this patch renames all former references of outOfBandArguments to clonedArguments and adds
extra instrumentation to DFGArgumentsEliminationPhase.

* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::clonedArgumentsThatWereNotCreated):
(JSC::ValueRecovery::outOfBandArgumentsThatWereNotCreated): Deleted.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
* dfg/DFGStructureRegistrationPhase.cpp:
(JSC::DFG::StructureRegistrationPhase::run):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCreateClonedArguments):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_create_cloned_arguments):
(JSC::JIT::emit_op_create_out_of_band_arguments): Deleted.
* llint/LowLevelInterpreter.asm:
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::ClonedArguments):
(JSC::ClonedArguments::createEmpty):
(JSC::ClonedArguments::createWithInlineFrame):
(JSC::ClonedArguments::createByCopyingFrom):
(JSC::ClonedArguments::createStructure):
* runtime/ClonedArguments.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::clonedArgumentsStructure):
(JSC::JSGlobalObject::outOfBandArgumentsStructure): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</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="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueRecoveryh">trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</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="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStructureRegistrationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp">trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOperationscpp">trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp</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="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeClonedArgumentscpp">trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeClonedArgumentsh">trunk/Source/JavaScriptCore/runtime/ClonedArguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjecth">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressclonedargumentseliminationjs">trunk/Source/JavaScriptCore/tests/stress/cloned-arguments-elimination.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -1,3 +1,80 @@
</span><ins>+2016-03-14  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        We should be able to eliminate cloned arguments objects that use the length property
+        https://bugs.webkit.org/show_bug.cgi?id=155391
+
+        Reviewed by Geoffrey Garen.
+
+        Previously if a programmer tried to use arguments.length in a strict function we would not eliminate the
+        arguments object. We were unable to eliminate the arguments object because the user would get a cloned arguments
+        object, which does not special case the length property. Thus, in order to get arguments elimination for cloned
+        we need to add a special case. There are two things that need to happen for the elimination to succeed.
+
+        First, we need to eliminate the CheckStructure blocking the GetByOffset for the length property. In order to
+        eliminate the check structure we need to prove to the Abstract Interpreter that this structure check is
+        unnesssary. This didn't occur before for two reasons: 1) CreateClonedArguments did not set the structure it
+        produced. 2) Even if CreateClonedArguments provided the global object's cloned arguments structure we would
+        transition the new argements object when we added the length property during construction. To fix the second
+        problem we now pre-assign a slot on clonedArgumentsStructure for the length property. Additionally, in order to
+        prevent future transitions of the structure we need to choose an indexing type for the structure. Since, not
+        eliminating the arguments object is so expensive we choose to have all cloned arguments start with continuous
+        indexing type, this avoids transitioning when otherwise we would not have to. In the future we should be smarter
+        about choosing the indexing type but since its relatively rare to have a arguments object escape we don't worry
+        about this for now.
+
+        Additionally, this patch renames all former references of outOfBandArguments to clonedArguments and adds
+        extra instrumentation to DFGArgumentsEliminationPhase.
+
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/ValueRecovery.h:
+        (JSC::ValueRecovery::clonedArgumentsThatWereNotCreated):
+        (JSC::ValueRecovery::outOfBandArgumentsThatWereNotCreated): Deleted.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
+        * dfg/DFGStructureRegistrationPhase.cpp:
+        (JSC::DFG::StructureRegistrationPhase::run):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateClonedArguments):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_create_cloned_arguments):
+        (JSC::JIT::emit_op_create_out_of_band_arguments): Deleted.
+        * llint/LowLevelInterpreter.asm:
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::ClonedArguments):
+        (JSC::ClonedArguments::createEmpty):
+        (JSC::ClonedArguments::createWithInlineFrame):
+        (JSC::ClonedArguments::createByCopyingFrom):
+        (JSC::ClonedArguments::createStructure):
+        * runtime/ClonedArguments.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::clonedArgumentsStructure):
+        (JSC::JSGlobalObject::outOfBandArgumentsStructure): Deleted.
+
</ins><span class="cx"> 2016-03-14  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Make JSON.stringify ES6 compatible
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -7,7 +7,7 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_get_scope&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_direct_arguments&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_scoped_arguments&quot;, &quot;length&quot; : 3 },
</span><del>-            { &quot;name&quot; : &quot;op_create_out_of_band_arguments&quot;, &quot;length&quot; : 2 },
</del><ins>+            { &quot;name&quot; : &quot;op_create_cloned_arguments&quot;, &quot;length&quot; : 2 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_create_this&quot;, &quot;length&quot; : 5 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_to_this&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_check_tdz&quot;, &quot;length&quot; : 2 },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">     case op_catch:
</span><span class="cx">     case op_profile_control_flow:
</span><span class="cx">     case op_create_direct_arguments:
</span><del>-    case op_create_out_of_band_arguments:
</del><ins>+    case op_create_cloned_arguments:
</ins><span class="cx">     case op_get_rest_length:
</span><span class="cx">     case op_watchdog:
</span><span class="cx">         return;
</span><span class="lines">@@ -410,7 +410,7 @@
</span><span class="cx">     case op_get_scope:
</span><span class="cx">     case op_create_direct_arguments:
</span><span class="cx">     case op_create_scoped_arguments:
</span><del>-    case op_create_out_of_band_arguments:
</del><ins>+    case op_create_cloned_arguments:
</ins><span class="cx">     case op_del_by_id:
</span><span class="cx">     case op_del_by_val:
</span><span class="cx">     case op_unsigned:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -799,9 +799,9 @@
</span><span class="cx">             out.printf(&quot;%s, %s&quot;, registerName(r0).data(), registerName(r1).data());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        case op_create_out_of_band_arguments: {
</del><ins>+        case op_create_cloned_arguments: {
</ins><span class="cx">             int r0 = (++it)-&gt;u.operand;
</span><del>-            printLocationAndOp(out, exec, location, it, &quot;create_out_of_band_arguments&quot;);
</del><ins>+            printLocationAndOp(out, exec, location, it, &quot;create_cloned_arguments&quot;);
</ins><span class="cx">             out.printf(&quot;%s&quot;, registerName(r0).data());
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueRecoveryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -197,7 +197,7 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static ValueRecovery outOfBandArgumentsThatWereNotCreated(DFG::MinifiedID id)
</del><ins>+    static ValueRecovery clonedArgumentsThatWereNotCreated(DFG::MinifiedID id)
</ins><span class="cx">     {
</span><span class="cx">         ValueRecovery result;
</span><span class="cx">         result.m_technique = ClonedArgumentsThatWereNotCreated;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -447,8 +447,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (needsArguments &amp;&amp; (codeBlock-&gt;isStrictMode() || !isSimpleParameterList)) {
</span><del>-        // Allocate an out-of-bands arguments object.
-        emitOpcode(op_create_out_of_band_arguments);
</del><ins>+        // Allocate a cloned arguments object.
+        emitOpcode(op_create_cloned_arguments);
</ins><span class="cx">         instructions().append(m_argumentsRegister-&gt;index());
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -1822,7 +1822,7 @@
</span><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     case CreateClonedArguments:
</span><del>-        forNode(node).setType(m_graph, SpecObjectOther);
</del><ins>+        forNode(node).set(m_graph, m_codeBlock-&gt;globalObjectFor(node-&gt;origin.semantic)-&gt;clonedArgumentsStructure());
</ins><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case NewArrowFunction:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;BytecodeLivenessAnalysisInlines.h&quot;
</span><ins>+#include &quot;ClonedArguments.h&quot;
</ins><span class="cx"> #include &quot;DFGArgumentsUtilities.h&quot;
</span><span class="cx"> #include &quot;DFGBasicBlockInlines.h&quot;
</span><span class="cx"> #include &quot;DFGBlockMapInlines.h&quot;
</span><span class="lines">@@ -118,28 +119,30 @@
</span><span class="cx">     // Look for escaping sites, and remove from the candidates set if we see an escape.
</span><span class="cx">     void eliminateCandidatesThatEscape()
</span><span class="cx">     {
</span><del>-        auto escape = [&amp;] (Edge edge) {
</del><ins>+        auto escape = [&amp;] (Edge edge, Node* source) {
</ins><span class="cx">             if (!edge)
</span><span class="cx">                 return;
</span><del>-            m_candidates.remove(edge.node());
</del><ins>+            bool removed = m_candidates.remove(edge.node());
+            if (removed &amp;&amp; verbose)
+                dataLog(&quot;eliminating candidate: &quot;, edge.node(), &quot; because it escapes from: &quot;, source, &quot;\n&quot;);
</ins><span class="cx">         };
</span><span class="cx">         
</span><del>-        auto escapeBasedOnArrayMode = [&amp;] (ArrayMode mode, Edge edge) {
</del><ins>+        auto escapeBasedOnArrayMode = [&amp;] (ArrayMode mode, Edge edge, Node* source) {
</ins><span class="cx">             switch (mode.type()) {
</span><span class="cx">             case Array::DirectArguments:
</span><span class="cx">                 if (edge-&gt;op() != CreateDirectArguments)
</span><del>-                    escape(edge);
</del><ins>+                    escape(edge, source);
</ins><span class="cx">                 break;
</span><span class="cx">             
</span><span class="cx">             case Array::Int32:
</span><span class="cx">             case Array::Double:
</span><span class="cx">             case Array::Contiguous:
</span><span class="cx">                 if (edge-&gt;op() != CreateClonedArguments)
</span><del>-                    escape(edge);
</del><ins>+                    escape(edge, source);
</ins><span class="cx">                 break;
</span><span class="cx">             
</span><span class="cx">             default:
</span><del>-                escape(edge);
</del><ins>+                escape(edge, source);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         };
</span><span class="lines">@@ -152,14 +155,14 @@
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="cx">                 case GetByVal:
</span><del>-                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1());
-                    escape(node-&gt;child2());
-                    escape(node-&gt;child3());
</del><ins>+                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1(), node);
+                    escape(node-&gt;child2(), node);
+                    escape(node-&gt;child3(), node);
</ins><span class="cx">                     break;
</span><del>-                    
</del><ins>+
</ins><span class="cx">                 case GetArrayLength:
</span><del>-                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1());
-                    escape(node-&gt;child2());
</del><ins>+                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1(), node);
+                    escape(node-&gt;child2(), node);
</ins><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="cx">                 case LoadVarargs:
</span><span class="lines">@@ -169,8 +172,8 @@
</span><span class="cx">                 case ConstructVarargs:
</span><span class="cx">                 case TailCallVarargs:
</span><span class="cx">                 case TailCallVarargsInlinedCaller:
</span><del>-                    escape(node-&gt;child1());
-                    escape(node-&gt;child3());
</del><ins>+                    escape(node-&gt;child1(), node);
+                    escape(node-&gt;child3(), node);
</ins><span class="cx">                     break;
</span><span class="cx"> 
</span><span class="cx">                 case Check:
</span><span class="lines">@@ -183,7 +186,7 @@
</span><span class="cx">                             if (alreadyChecked(edge.useKind(), SpecObject))
</span><span class="cx">                                 return;
</span><span class="cx">                             
</span><del>-                            escape(edge);
</del><ins>+                            escape(edge, node);
</ins><span class="cx">                         });
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="lines">@@ -201,18 +204,19 @@
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="cx">                 case CheckArray:
</span><del>-                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1());
</del><ins>+                    escapeBasedOnArrayMode(node-&gt;arrayMode(), node-&gt;child1(), node);
</ins><span class="cx">                     break;
</span><ins>+
</ins><span class="cx">                     
</span><del>-                // FIXME: For cloned arguments, we'd like to allow GetByOffset on length to not be
-                // an escape.
-                // https://bugs.webkit.org/show_bug.cgi?id=143074
-                    
</del><span class="cx">                 // FIXME: We should be able to handle GetById/GetByOffset on callee.
</span><span class="cx">                 // https://bugs.webkit.org/show_bug.cgi?id=143075
</span><del>-                    
</del><ins>+
+                case GetByOffset:
+                    if (node-&gt;child2()-&gt;op() == CreateClonedArguments &amp;&amp; node-&gt;storageAccessData().offset == clonedArgumentsLengthPropertyOffset)
+                        break;
+                    FALLTHROUGH;
</ins><span class="cx">                 default:
</span><del>-                    m_graph.doToChildren(node, escape);
</del><ins>+                    m_graph.doToChildren(node, [&amp;] (Edge edge) { return escape(edge, node); });
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="lines">@@ -319,6 +323,8 @@
</span><span class="cx">                     // for this arguments allocation, and we'd have to examine every node in the block,
</span><span class="cx">                     // then we can just eliminate the candidate.
</span><span class="cx">                     if (nodeIndex == block-&gt;size() &amp;&amp; candidate-&gt;owner != block) {
</span><ins>+                        if (verbose)
+                            dataLog(&quot;eliminating candidate: &quot;, candidate, &quot; because it is clobbered by: &quot;, block-&gt;at(nodeIndex), &quot;\n&quot;);
</ins><span class="cx">                         m_candidates.remove(candidate);
</span><span class="cx">                         return;
</span><span class="cx">                     }
</span><span class="lines">@@ -344,6 +350,8 @@
</span><span class="cx">                             NoOpClobberize());
</span><span class="cx">                         
</span><span class="cx">                         if (found) {
</span><ins>+                            if (verbose)
+                                dataLog(&quot;eliminating candidate: &quot;, candidate, &quot; because it is clobbered by &quot;, block-&gt;at(nodeIndex), &quot;\n&quot;);
</ins><span class="cx">                             m_candidates.remove(candidate);
</span><span class="cx">                             return;
</span><span class="cx">                         }
</span><span class="lines">@@ -412,6 +420,22 @@
</span><span class="cx">                     node-&gt;convertToGetStack(data);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><ins>+
+                case GetByOffset: {
+                    Node* candidate = node-&gt;child2().node();
+                    if (!m_candidates.contains(candidate))
+                        break;
+
+                    if (node-&gt;child2()-&gt;op() != PhantomClonedArguments)
+                        break;
+
+                    ASSERT(node-&gt;storageAccessData().offset == clonedArgumentsLengthPropertyOffset);
+
+                    // Meh, this is kind of hackish - we use an Identity so that we can reuse the
+                    // getArrayLength() helper.
+                    node-&gt;convertToIdentityOn(getArrayLength(candidate));
+                    break;
+                }
</ins><span class="cx">                     
</span><span class="cx">                 case GetArrayLength: {
</span><span class="cx">                     Node* candidate = node-&gt;child1().node();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -4582,11 +4582,11 @@
</span><span class="cx">             NEXT_OPCODE(op_create_scoped_arguments);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_create_out_of_band_arguments: {
</del><ins>+        case op_create_cloned_arguments: {
</ins><span class="cx">             noticeArgumentsUse();
</span><span class="cx">             Node* createArguments = addToGraph(CreateClonedArguments);
</span><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), createArguments);
</span><del>-            NEXT_OPCODE(op_create_out_of_band_arguments);
</del><ins>+            NEXT_OPCODE(op_create_cloned_arguments);
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case op_get_from_arguments: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -193,7 +193,7 @@
</span><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><del>-    case op_create_out_of_band_arguments:
</del><ins>+    case op_create_cloned_arguments:
</ins><span class="cx">     case op_get_from_arguments:
</span><span class="cx">     case op_put_to_arguments:
</span><span class="cx">     case op_jneq_ptr:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -961,16 +961,15 @@
</span><span class="cx">     
</span><span class="cx">     unsigned length = argumentCount - 1;
</span><span class="cx">     ClonedArguments* result = ClonedArguments::createEmpty(
</span><del>-        vm, codeBlock-&gt;globalObject()-&gt;outOfBandArgumentsStructure(), callee);
</del><ins>+        vm, codeBlock-&gt;globalObject()-&gt;clonedArgumentsStructure(), callee, length);
</ins><span class="cx">     
</span><span class="cx">     Register* arguments =
</span><span class="cx">         exec-&gt;registers() + (inlineCallFrame ? inlineCallFrame-&gt;stackOffset : 0) +
</span><span class="cx">         CallFrame::argumentOffset(0);
</span><span class="cx">     for (unsigned i = length; i--;)
</span><del>-        result-&gt;putDirectIndex(exec, i, arguments[i].jsValue());
</del><ins>+        result-&gt;initializeIndex(vm, i, arguments[i].jsValue());
+
</ins><span class="cx">     
</span><del>-    result-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(length));
-    
</del><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -5966,7 +5966,7 @@
</span><span class="cx">         1, [&amp;] (GPRReg destGPR) {
</span><span class="cx">             m_jit.move(
</span><span class="cx">                 TrustedImmPtr(
</span><del>-                    m_jit.globalObjectFor(node-&gt;origin.semantic)-&gt;outOfBandArgumentsStructure()),
</del><ins>+                    m_jit.globalObjectFor(node-&gt;origin.semantic)-&gt;clonedArgumentsStructure()),
</ins><span class="cx">                 destGPR);
</span><span class="cx">         });
</span><span class="cx">     m_jit.setupArgument(0, [&amp;] (GPRReg destGPR) { m_jit.move(GPRInfo::callFrameRegister, destGPR); });
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStructureRegistrationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -136,7 +136,11 @@
</span><span class="cx">                 case CreateScopedArguments:
</span><span class="cx">                     registerStructure(m_graph.globalObjectFor(node-&gt;origin.semantic)-&gt;scopedArgumentsStructure());
</span><span class="cx">                     break;
</span><del>-                    
</del><ins>+
+                case CreateClonedArguments:
+                    registerStructure(m_graph.globalObjectFor(node-&gt;origin.semantic)-&gt;clonedArgumentsStructure());
+                    break;
+
</ins><span class="cx">                 case NewRegexp:
</span><span class="cx">                     registerStructure(m_graph.globalObjectFor(node-&gt;origin.semantic)-&gt;regExpStructure());
</span><span class="cx">                     break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (node-&gt;op() == PhantomClonedArguments) {
</span><del>-        recovery = ValueRecovery::outOfBandArgumentsThatWereNotCreated(node-&gt;id());
</del><ins>+        recovery = ValueRecovery::clonedArgumentsThatWereNotCreated(node-&gt;id());
</ins><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -3500,7 +3500,7 @@
</span><span class="cx">         LValue result = vmCall(
</span><span class="cx">             m_out.int64, m_out.operation(operationCreateClonedArguments), m_callFrame,
</span><span class="cx">             weakPointer(
</span><del>-                m_graph.globalObjectFor(m_node-&gt;origin.semantic)-&gt;outOfBandArgumentsStructure()),
</del><ins>+                m_graph.globalObjectFor(m_node-&gt;origin.semantic)-&gt;clonedArgumentsStructure()),
</ins><span class="cx">             getArgumentsStart(), getArgumentsLength().value, getCurrentCallee());
</span><span class="cx">         
</span><span class="cx">         setJSValue(result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -328,7 +328,7 @@
</span><span class="cx">         case PhantomClonedArguments: {
</span><span class="cx">             unsigned length = argumentCount - 1;
</span><span class="cx">             ClonedArguments* result = ClonedArguments::createEmpty(
</span><del>-                vm, codeBlock-&gt;globalObject()-&gt;outOfBandArgumentsStructure(), callee);
</del><ins>+                vm, codeBlock-&gt;globalObject()-&gt;clonedArgumentsStructure(), callee, length);
</ins><span class="cx">             
</span><span class="cx">             for (unsigned i = materialization-&gt;properties().size(); i--;) {
</span><span class="cx">                 const ExitPropertyValue&amp; property = materialization-&gt;properties()[i];
</span><span class="lines">@@ -338,10 +338,9 @@
</span><span class="cx">                 unsigned index = property.location().info();
</span><span class="cx">                 if (index &gt;= length)
</span><span class="cx">                     continue;
</span><del>-                result-&gt;putDirectIndex(exec, index, JSValue::decode(values[i]));
</del><ins>+                result-&gt;initializeIndex(vm, index, JSValue::decode(values[i]));
</ins><span class="cx">             }
</span><span class="cx">             
</span><del>-            result-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(length));
</del><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -214,7 +214,7 @@
</span><span class="cx">         DEFINE_OP(op_to_this)
</span><span class="cx">         DEFINE_OP(op_create_direct_arguments)
</span><span class="cx">         DEFINE_OP(op_create_scoped_arguments)
</span><del>-        DEFINE_OP(op_create_out_of_band_arguments)
</del><ins>+        DEFINE_OP(op_create_cloned_arguments)
</ins><span class="cx">         DEFINE_OP(op_copy_rest)
</span><span class="cx">         DEFINE_OP(op_get_rest_length)
</span><span class="cx">         DEFINE_OP(op_check_tdz)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -490,7 +490,7 @@
</span><span class="cx">         void emit_op_to_this(Instruction*);
</span><span class="cx">         void emit_op_create_direct_arguments(Instruction*);
</span><span class="cx">         void emit_op_create_scoped_arguments(Instruction*);
</span><del>-        void emit_op_create_out_of_band_arguments(Instruction*);
</del><ins>+        void emit_op_create_cloned_arguments(Instruction*);
</ins><span class="cx">         void emit_op_copy_rest(Instruction*);
</span><span class="cx">         void emit_op_get_rest_length(Instruction*);
</span><span class="cx">         void emit_op_check_tdz(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -1393,9 +1393,9 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_create_out_of_band_arguments(Instruction* currentInstruction)
</del><ins>+void JIT::emit_op_create_cloned_arguments(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><del>-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_out_of_band_arguments);
</del><ins>+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_cloned_arguments);
</ins><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -1212,9 +1212,9 @@
</span><span class="cx">     dispatch(3)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-_llint_op_create_out_of_band_arguments:
</del><ins>+_llint_op_create_cloned_arguments:
</ins><span class="cx">     traceExecution()
</span><del>-    callSlowPath(_slow_path_create_out_of_band_arguments)
</del><ins>+    callSlowPath(_slow_path_create_cloned_arguments)
</ins><span class="cx">     dispatch(2)
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeClonedArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/ClonedArguments.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -36,28 +36,40 @@
</span><span class="cx"> 
</span><span class="cx"> const ClassInfo ClonedArguments::s_info = { &quot;Arguments&quot;, &amp;Base::s_info, 0, CREATE_METHOD_TABLE(ClonedArguments) };
</span><span class="cx"> 
</span><del>-ClonedArguments::ClonedArguments(VM&amp; vm, Structure* structure)
-    : Base(vm, structure, nullptr)
</del><ins>+ClonedArguments::ClonedArguments(VM&amp; vm, Structure* structure, Butterfly* butterfly)
+    : Base(vm, structure, butterfly)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ClonedArguments* ClonedArguments::createEmpty(
</span><del>-    VM&amp; vm, Structure* structure, JSFunction* callee)
</del><ins>+    VM&amp; vm, Structure* structure, JSFunction* callee, unsigned length)
</ins><span class="cx"> {
</span><ins>+    unsigned vectorLength = std::max(BASE_VECTOR_LEN, length);
+    if (vectorLength &gt; MAX_STORAGE_VECTOR_LENGTH)
+        return 0;
+
+    void* temp;
+    if (!vm.heap.tryAllocateStorage(0, Butterfly::totalSize(0, structure-&gt;outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)), &amp;temp))
+        return 0;
+    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure-&gt;outOfLineCapacity());
+    butterfly-&gt;setVectorLength(vectorLength);
+    butterfly-&gt;setPublicLength(length);
+
</ins><span class="cx">     ClonedArguments* result =
</span><span class="cx">         new (NotNull, allocateCell&lt;ClonedArguments&gt;(vm.heap))
</span><del>-        ClonedArguments(vm, structure);
</del><ins>+        ClonedArguments(vm, structure, butterfly);
</ins><span class="cx">     result-&gt;finishCreation(vm);
</span><ins>+
</ins><span class="cx">     result-&gt;m_callee.set(vm, result, callee);
</span><ins>+    result-&gt;putDirect(vm, clonedArgumentsLengthPropertyOffset, jsNumber(length));
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ClonedArguments* ClonedArguments::createEmpty(ExecState* exec, JSFunction* callee)
</del><ins>+ClonedArguments* ClonedArguments::createEmpty(ExecState* exec, JSFunction* callee, unsigned length)
</ins><span class="cx"> {
</span><span class="cx">     // NB. Some clients might expect that the global object of of this object is the global object
</span><span class="cx">     // of the callee. We don't do this for now, but maybe we should.
</span><del>-    return createEmpty(
-        exec-&gt;vm(), exec-&gt;lexicalGlobalObject()-&gt;outOfBandArgumentsStructure(), callee);
</del><ins>+    return createEmpty(exec-&gt;vm(), exec-&gt;lexicalGlobalObject()-&gt;clonedArgumentsStructure(), callee, length);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode)
</span><span class="lines">@@ -71,7 +83,7 @@
</span><span class="cx">     else
</span><span class="cx">         callee = jsCast&lt;JSFunction*&gt;(targetFrame-&gt;callee());
</span><span class="cx"> 
</span><del>-    ClonedArguments* result = createEmpty(myFrame, callee);
</del><ins>+    ClonedArguments* result;
</ins><span class="cx">     
</span><span class="cx">     unsigned length = 0; // Initialize because VC needs it.
</span><span class="cx">     switch (mode) {
</span><span class="lines">@@ -82,25 +94,26 @@
</span><span class="cx">             else
</span><span class="cx">                 length = inlineCallFrame-&gt;arguments.size();
</span><span class="cx">             length--;
</span><del>-            
</del><ins>+            result = createEmpty(myFrame, callee, length);
+
</ins><span class="cx">             for (unsigned i = length; i--;)
</span><del>-                result-&gt;putDirectIndex(myFrame, i, inlineCallFrame-&gt;arguments[i + 1].recover(targetFrame));
</del><ins>+                result-&gt;initializeIndex(vm, i, inlineCallFrame-&gt;arguments[i + 1].recover(targetFrame));
</ins><span class="cx">         } else {
</span><span class="cx">             length = targetFrame-&gt;argumentCount();
</span><del>-            
</del><ins>+            result = createEmpty(myFrame, callee, length);
+
</ins><span class="cx">             for (unsigned i = length; i--;)
</span><del>-                result-&gt;putDirectIndex(myFrame, i, targetFrame-&gt;uncheckedArgument(i));
</del><ins>+                result-&gt;initializeIndex(vm, i, targetFrame-&gt;uncheckedArgument(i));
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case ArgumentsMode::FakeValues: {
</span><del>-        length = 0;
</del><ins>+        result = createEmpty(myFrame, callee, 0);
</ins><span class="cx">         break;
</span><span class="cx">     } }
</span><del>-    
-    result-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(length), DontEnum);
-    
</del><ins>+
+    ASSERT(myFrame-&gt;lexicalGlobalObject()-&gt;clonedArgumentsStructure() == result-&gt;structure());
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -114,18 +127,24 @@
</span><span class="cx">     JSFunction* callee)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    ClonedArguments* result = createEmpty(vm, structure, callee);
</del><ins>+    ClonedArguments* result = createEmpty(vm, structure, callee, length);
</ins><span class="cx">     
</span><span class="cx">     for (unsigned i = length; i--;)
</span><del>-        result-&gt;putDirectIndex(exec, i, argumentStart[i].jsValue());
-    
-    result-&gt;putDirect(vm, vm.propertyNames-&gt;length, jsNumber(length), DontEnum);
</del><ins>+        result-&gt;initializeIndex(vm, i, argumentStart[i].jsValue());
+
+    ASSERT(exec-&gt;lexicalGlobalObject()-&gt;clonedArgumentsStructure() == result-&gt;structure());
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Structure* ClonedArguments::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span><span class="cx"> {
</span><del>-    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</del><ins>+    // We use contiguous storage because optimizations in the FTL assume that cloned arguments creation always produces the same initial structure.
+
+    Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), NonArrayWithContiguous);
+    PropertyOffset offset;
+    structure = structure-&gt;addPropertyTransition(vm, structure, vm.propertyNames-&gt;length, DontEnum, offset);
+    ASSERT(offset == clonedArgumentsLengthPropertyOffset);
+    return structure;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot&amp; slot)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeClonedArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ClonedArguments.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ClonedArguments.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/ClonedArguments.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -44,11 +44,11 @@
</span><span class="cx">     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    ClonedArguments(VM&amp;, Structure*);
</del><ins>+    ClonedArguments(VM&amp;, Structure*, Butterfly*);
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><del>-    static ClonedArguments* createEmpty(VM&amp;, Structure*, JSFunction* callee);
-    static ClonedArguments* createEmpty(ExecState*, JSFunction* callee);
</del><ins>+    static ClonedArguments* createEmpty(VM&amp;, Structure*, JSFunction* callee, unsigned length);
+    static ClonedArguments* createEmpty(ExecState*, JSFunction* callee, unsigned length);
</ins><span class="cx">     static ClonedArguments* createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame*, ArgumentsMode);
</span><span class="cx">     static ClonedArguments* createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode);
</span><span class="cx">     static ClonedArguments* createByCopyingFrom(ExecState*, Structure*, Register* argumentsStart, unsigned length, JSFunction* callee);
</span><span class="lines">@@ -73,6 +73,8 @@
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_callee; // Set to nullptr when we materialize all of our special properties.
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+static const PropertyOffset clonedArgumentsLengthPropertyOffset = 100;
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ClonedArguments_h
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -212,7 +212,7 @@
</span><span class="cx">     RETURN(ScopedArguments::createByCopying(exec, table, scope));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SLOW_PATH_DECL(slow_path_create_out_of_band_arguments)
</del><ins>+SLOW_PATH_DECL(slow_path_create_cloned_arguments)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     RETURN(ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -188,7 +188,7 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_direct_arguments);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_scoped_arguments);
</span><del>-SLOW_PATH_HIDDEN_DECL(slow_path_create_out_of_band_arguments);
</del><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_create_cloned_arguments);
</ins><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_enter);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -341,7 +341,7 @@
</span><span class="cx">     m_callbackFunctionStructure.set(vm, this, JSCallbackFunction::createStructure(vm, this, m_functionPrototype.get()));
</span><span class="cx">     m_directArgumentsStructure.set(vm, this, DirectArguments::createStructure(vm, this, m_objectPrototype.get()));
</span><span class="cx">     m_scopedArgumentsStructure.set(vm, this, ScopedArguments::createStructure(vm, this, m_objectPrototype.get()));
</span><del>-    m_outOfBandArgumentsStructure.set(vm, this, ClonedArguments::createStructure(vm, this, m_objectPrototype.get()));
</del><ins>+    m_clonedArgumentsStructure.set(vm, this, ClonedArguments::createStructure(vm, this, m_objectPrototype.get()));
</ins><span class="cx">     m_callbackConstructorStructure.set(vm, this, JSCallbackConstructor::createStructure(vm, this, m_objectPrototype.get()));
</span><span class="cx">     m_callbackObjectStructure.set(vm, this, JSCallbackObject&lt;JSDestructibleObject&gt;::createStructure(vm, this, m_objectPrototype.get()));
</span><span class="cx"> 
</span><span class="lines">@@ -887,7 +887,7 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_moduleEnvironmentStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_directArgumentsStructure);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_scopedArgumentsStructure);
</span><del>-    visitor.append(&amp;thisObject-&gt;m_outOfBandArgumentsStructure);
</del><ins>+    visitor.append(&amp;thisObject-&gt;m_clonedArgumentsStructure);
</ins><span class="cx">     for (unsigned i = 0; i &lt; NumberOfIndexingShapes; ++i)
</span><span class="cx">         visitor.append(&amp;thisObject-&gt;m_originalArrayStructureForIndexingShape[i]);
</span><span class="cx">     for (unsigned i = 0; i &lt; NumberOfIndexingShapes; ++i)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h (198153 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2016-03-14 20:54:15 UTC (rev 198153)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -246,7 +246,7 @@
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_moduleEnvironmentStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_directArgumentsStructure;
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_scopedArgumentsStructure;
</span><del>-    WriteBarrier&lt;Structure&gt; m_outOfBandArgumentsStructure;
</del><ins>+    WriteBarrier&lt;Structure&gt; m_clonedArgumentsStructure;
</ins><span class="cx">         
</span><span class="cx">     // Lists the actual structures used for having these particular indexing shapes.
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_originalArrayStructureForIndexingShape[NumberOfIndexingShapes];
</span><span class="lines">@@ -479,7 +479,7 @@
</span><span class="cx">     Structure* moduleEnvironmentStructure() const { return m_moduleEnvironmentStructure.get(); }
</span><span class="cx">     Structure* directArgumentsStructure() const { return m_directArgumentsStructure.get(); }
</span><span class="cx">     Structure* scopedArgumentsStructure() const { return m_scopedArgumentsStructure.get(); }
</span><del>-    Structure* outOfBandArgumentsStructure() const { return m_outOfBandArgumentsStructure.get(); }
</del><ins>+    Structure* clonedArgumentsStructure() const { return m_clonedArgumentsStructure.get(); }
</ins><span class="cx">     Structure* originalArrayStructureForIndexingType(IndexingType indexingType) const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(indexingType &amp; IsArray);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressclonedargumentseliminationjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/cloned-arguments-elimination.js (0 => 198154)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/cloned-arguments-elimination.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/cloned-arguments-elimination.js        2016-03-14 20:55:15 UTC (rev 198154)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+function testModifyLength() {
+    &quot;use strict&quot;;
+
+    arguments.length = 10;
+    return arguments.length;
+}
+noInline(testModifyLength);
+
+function testAddOtherProperty() {
+    &quot;use strict&quot;;
+
+    arguments.foo = 1;
+    return arguments.length;
+}
+noInline(testAddOtherProperty);
+
+function testAddOtherPropertyInBranch() {
+    &quot;use strict&quot;;
+
+    if (arguments[0] % 2)
+        arguments.foo = 1;
+    return arguments.length;
+}
+noInline(testAddOtherPropertyInBranch);
+
+for (i = 0; i &lt; 100000; i++) {
+    if (testModifyLength(1) !== 10)
+        throw &quot;bad&quot;;
+    if (testAddOtherProperty(1) !== 1)
+        throw &quot;bad&quot;;
+    if (testAddOtherPropertyInBranch(i) !== 1)
+        throw &quot;bad&quot;;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>