<!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>[204439] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/204439">204439</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-08-12 19:14:42 -0700 (Fri, 12 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Inline store loop for CopyRest in DFG and FTL for certain array modes
https://bugs.webkit.org/show_bug.cgi?id=159612

Reviewed by Filip Pizlo.

JSTests:

* stress/rest-parameter-having-a-bad-time.js: Added.
* stress/rest-parameter-many-arguments.js: Added.
* stress/rest-parameter-various-types.js: Added.

Source/JavaScriptCore:

This patch changes the old copy_rest bytecode to actually allocate the rest array itself.
The bytecode is now called create_rest with an analogous CreateRest node in the DFG/FTL.
This allows the bytecode to be in control of what type of indexingType the array is allocated
with. We always allocate using ArrayWithContiguous storage unless we're havingABadTime().
This also makes allocating and writing into the array fast. On the fast path, the DFG/FTL
JIT will fast allocate the array and its storage, and we will do a memmove from the rest
region of arguments into the array's storage.

I'm seeing a 1-2% speedup on ES6SampleBench, and about a 2x speedup
on micro benchmarks that just test rest creation speed.

* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitRestParameter):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
(JSC::DFG::CallArrayAllocatorWithVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableSizeSlowPathGenerator):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::uses):
(JSC::DFG::Graph::isWatchingHavingABadTimeWatchpoint):
(JSC::DFG::Graph::compilation):
* dfg/DFGNode.h:
(JSC::DFG::Node::numberOfArgumentsToSkip):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
(JSC::DFG::SpeculativeJIT::compileCreateRest):
(JSC::DFG::SpeculativeJIT::compileGetRestLength):
(JSC::DFG::SpeculativeJIT::compileCopyRest): Deleted.
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileArithRandom):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileArithRandom):
(JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateClonedArguments):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateRest):
(JSC::FTL::DFG::LowerDFGToB3::compileGetRestLength):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
(JSC::FTL::DFG::LowerDFGToB3::compileAllocateArrayWithSize):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
(JSC::FTL::DFG::LowerDFGToB3::compileCopyRest): Deleted.
* interpreter/CallFrame.h:
(JSC::ExecState::addressOfArgumentsStart):
(JSC::ExecState::argument):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_argument_count):
(JSC::JIT::emit_op_create_rest):
(JSC::JIT::emit_op_copy_rest): Deleted.
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:

LayoutTests:

* js/regress/rest-parameter-construction-performance-expected.txt: Added.
* js/regress/rest-parameter-construction-performance.html: Added.
* js/regress/script-tests/rest-parameter-construction-performance.js: Added.
(foo):
(test1):
(test2.foo):
(test2):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<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="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCallArrayAllocatorSlowPathGeneratorh">trunk/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</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="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterCallFrameh">trunk/Source/JavaScriptCore/interpreter/CallFrame.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="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressrestparameterhavingabadtimejs">trunk/JSTests/stress/rest-parameter-having-a-bad-time.js</a></li>
<li><a href="#trunkJSTestsstressrestparametermanyargumentsjs">trunk/JSTests/stress/rest-parameter-many-arguments.js</a></li>
<li><a href="#trunkJSTestsstressrestparametervarioustypesjs">trunk/JSTests/stress/rest-parameter-various-types.js</a></li>
<li><a href="#trunkLayoutTestsjsregressrestparameterconstructionperformanceexpectedtxt">trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressrestparameterconstructionperformancehtml">trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsrestparameterconstructionperformancejs">trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/JSTests/ChangeLog        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2016-08-12  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Inline store loop for CopyRest in DFG and FTL for certain array modes
+        https://bugs.webkit.org/show_bug.cgi?id=159612
+
+        Reviewed by Filip Pizlo.
+
+        * stress/rest-parameter-having-a-bad-time.js: Added.
+        * stress/rest-parameter-many-arguments.js: Added.
+        * stress/rest-parameter-various-types.js: Added.
+
</ins><span class="cx"> 2016-08-12  Skachkov Oleksandr  &lt;gskachkov@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES2016] Implement Object.entries
</span></span></pre></div>
<a id="trunkJSTestsstressrestparameterhavingabadtimejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/rest-parameter-having-a-bad-time.js (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/rest-parameter-having-a-bad-time.js                                (rev 0)
+++ trunk/JSTests/stress/rest-parameter-having-a-bad-time.js        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad!&quot;)
+}
+noInline(assert);
+
+function test1() {
+    function foo(...c) {
+        return c;
+    }
+    noInline(foo);
+
+    let arr = [1,2,3];
+    for (let i = 0; i &lt; 10000; i++) {
+        let result = foo(...arr);
+        assert(result.length === 3);
+        assert(result.length === arr.length);
+        assert(result[0] === arr[0]);
+        assert(result[1] === arr[1]);
+        assert(result[2] === arr[2]);
+    }
+
+    let called = false;
+    Reflect.defineProperty(Array.prototype, &quot;10&quot;, {
+        get() { return 35; },
+        set(x) { called = true; }
+    });
+    let called2 = false;
+    Reflect.defineProperty(Array.prototype, &quot;0&quot;, {
+        get: function() { print(&quot;In get!&quot;); return 35; },
+        set: function(x) { called2 = true; }
+    });
+
+    for (let i = 0; i &lt; 10000; i++) {
+        let result = foo(...arr);
+        assert(result.length === 3);
+        assert(result[0] === arr[0]);
+        assert(result[0] === 1);
+        assert(result[1] === arr[1]);
+        assert(result[2] === arr[2]);
+        result[10] = 25;
+        assert(result[10] === 35);
+        assert(called);
+        called = false;
+
+        result[0] = &quot;foo&quot;;
+        assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+    }
+
+    for (let i = 0; i &lt; 10000; i++) {
+        let result = foo(...arr);
+        assert(result.length === 3);
+        assert(result[0] === arr[0]);
+        assert(result[0] === 1);
+        assert(result[1] === arr[1]);
+        assert(result[2] === arr[2]);
+        result[11] = 35;
+        assert(result.length === 12);
+        result[10] = 25;
+        assert(result[10] === 35);
+        assert(called);
+        called = false;
+
+        result[0] = &quot;foo&quot;;
+        assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+    }
+}
+test1();
</ins></span></pre></div>
<a id="trunkJSTestsstressrestparametermanyargumentsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/rest-parameter-many-arguments.js (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/rest-parameter-many-arguments.js                                (rev 0)
+++ trunk/JSTests/stress/rest-parameter-many-arguments.js        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad!&quot;)
+}
+noInline(assert);
+
+let calledGet = false;
+let definedAccessor = false;
+function test() {
+    function foo(...rest) {
+        return rest;
+    }
+    noInline(foo);
+
+    for (let i = 0; i &lt; 10000; i++) {
+        const size = 800;
+        let arr = new Array(size);
+        for (let i = 0; i &lt; size; i++)
+            arr[i] = i;
+        let result = foo(...arr);
+
+        assert(result.length === arr.length);
+        assert(result.length === size);
+        for (let i = 0; i &lt; arr.length; i++) {
+            assert(arr[i] === result[i]);
+            assert(result[i] === i);
+        }
+        if (definedAccessor) {
+            calledGet = false;
+            result[0];
+            assert(!calledGet);
+            arr[0];
+            assert(calledGet);
+
+            let testArr = [...arr];
+            calledGet = false;
+            testArr[0];
+            assert(!calledGet);
+        }
+    }
+}
+test();
+
+definedAccessor = true;
+Reflect.defineProperty(Array.prototype, &quot;0&quot;, {
+    get() { calledGet = true; return 0; },
+    set(x) {  }
+});
+test();
</ins></span></pre></div>
<a id="trunkJSTestsstressrestparametervarioustypesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/rest-parameter-various-types.js (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/rest-parameter-various-types.js                                (rev 0)
+++ trunk/JSTests/stress/rest-parameter-various-types.js        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad!&quot;);
+}
+noInline(assert);
+
+function foo(a, b, ...c) {
+    return c;
+}
+noInline(foo);
+function bar(a, b, ...c) {
+    return c;
+}
+noInline(bar);
+
+function baz(a, b, ...c) { // allow this to be inlined
+    return c;
+}
+
+noInline(isNaN);
+
+function test1(f, iters) {
+    for (let i = 0; i &lt; iters; i++) {
+        let result = f(10, 20, 20.5, 22.45, 23.50);
+        assert(result.length === 3);
+        assert(result[0] === 20.5)
+        assert(result[1] === 22.45)
+        assert(result[2] === 23.50);
+    }
+
+    let o = {};
+    let result = f(10, 20, 20.4, o, 20.2);
+    assert(result.length === 3);
+    assert(result[0] === 20.4)
+    assert(result[1] === o)
+    assert(result[2] === 20.2);
+
+    result = f(10, 20, 20.4, 20.45, NaN);
+    assert(result.length === 3);
+    assert(result[0] === 20.4)
+    assert(result[1] === 20.45)
+    assert(isNaN(result[2]));
+}
+test1(foo, 1000);
+test1(bar, 10000);
+test1(baz, 10000);
+
+function makeTest2() {
+    return eval(`${Math.random()};
+        ;(function test2(f, iters) {
+            let a = 10;
+            let b = 20;
+            for (let i = 0; i &lt; iters; i++) {
+                if (i === iters - 2) {
+                    b = {};
+                } else if (i === iters - 1) {
+                    b = NaN;
+                }
+
+                let r = f(a, b);
+                assert(r.length === 2);
+                assert(r[0] === a || (isNaN(a) &amp;&amp; isNaN(r[0])));
+                assert(r[1] === b || (isNaN(b) &amp;&amp; isNaN(r[1])));
+            }
+        })`);
+}
+function f1(...rest) { return rest; }
+function f2(...rest) { return rest; }
+function f3(...rest) { return rest; }
+makeTest2()(f1, 1000);
+makeTest2()(f2, 10000);
+makeTest2()(f3, 500000);
+
+function test3(f, iters) {
+    let o = {};
+    for (let i = 0; i &lt; iters; i++) {
+        let r = f(i, o, 25);
+        assert(r.length === 2 || r.length === 10000);
+        assert(r[0] === o);
+        assert(r[1] === 25);
+        if (r.length === 10000)
+            assert(r[9999] === 30);
+    }
+}
+
+function f11(i, ...rest) {
+    if (i === 999)
+        rest[9999] = 30;
+    return rest;
+}
+function f22(i, ...rest) {
+    if (i === 49999)
+        rest[9999] = 30;
+    return rest;
+}
+test3(f11, 1000);
+test3(f22, 50000);
+
</ins></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/LayoutTests/ChangeLog        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-08-12  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Inline store loop for CopyRest in DFG and FTL for certain array modes
+        https://bugs.webkit.org/show_bug.cgi?id=159612
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/rest-parameter-construction-performance-expected.txt: Added.
+        * js/regress/rest-parameter-construction-performance.html: Added.
+        * js/regress/script-tests/rest-parameter-construction-performance.js: Added.
+        (foo):
+        (test1):
+        (test2.foo):
+        (test2):
+
</ins><span class="cx"> 2016-08-12  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add mac-wk1 baseline for js/dom/global-constructors-attributes.html after r204396.
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressrestparameterconstructionperformanceexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/rest-parameter-construction-performance
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressrestparameterconstructionperformancehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/rest-parameter-construction-performance.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsrestparameterconstructionperformancejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js (0 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+&quot;use strict&quot;;
+
+function foo(...rest) {
+    return rest;
+}
+noInline(foo);
+
+const iters = 900000;
+function test1() {
+    let o = {};
+    let a = [];
+    for (let i = 0; i &lt; iters; i++)
+        foo(10, 20, o, 55, a, 120.341, a, o);
+}
+
+function test2() {
+    function foo(...rest) { // Allow this to be inlined.
+        return rest;
+    }
+    let o = {};
+    let a = [];
+    for (let i = 0; i &lt; iters; i++)
+        foo(10, 20, o, 55, a, 120.341, a, o);
+}
+
+test1();
+test2();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2016-08-12  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        Inline store loop for CopyRest in DFG and FTL for certain array modes
+        https://bugs.webkit.org/show_bug.cgi?id=159612
+
+        Reviewed by Filip Pizlo.
+
+        This patch changes the old copy_rest bytecode to actually allocate the rest array itself.
+        The bytecode is now called create_rest with an analogous CreateRest node in the DFG/FTL.
+        This allows the bytecode to be in control of what type of indexingType the array is allocated
+        with. We always allocate using ArrayWithContiguous storage unless we're havingABadTime().
+        This also makes allocating and writing into the array fast. On the fast path, the DFG/FTL
+        JIT will fast allocate the array and its storage, and we will do a memmove from the rest
+        region of arguments into the array's storage.
+
+        I'm seeing a 1-2% speedup on ES6SampleBench, and about a 2x speedup
+        on micro benchmarks that just test rest creation speed.
+
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitRestParameter):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
+        (JSC::DFG::CallArrayAllocatorWithVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableSizeSlowPathGenerator):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::uses):
+        (JSC::DFG::Graph::isWatchingHavingABadTimeWatchpoint):
+        (JSC::DFG::Graph::compilation):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::numberOfArgumentsToSkip):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCreateClonedArguments):
+        (JSC::DFG::SpeculativeJIT::compileCreateRest):
+        (JSC::DFG::SpeculativeJIT::compileGetRestLength):
+        (JSC::DFG::SpeculativeJIT::compileCopyRest): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::compileArithRandom):
+        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::compileArithRandom):
+        (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateClonedArguments):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateRest):
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetRestLength):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
+        (JSC::FTL::DFG::LowerDFGToB3::compileAllocateArrayWithSize):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCopyRest): Deleted.
+        * interpreter/CallFrame.h:
+        (JSC::ExecState::addressOfArgumentsStart):
+        (JSC::ExecState::argument):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_argument_count):
+        (JSC::JIT::emit_op_create_rest):
+        (JSC::JIT::emit_op_copy_rest): Deleted.
+        * jit/JITOperations.h:
+        * llint/LowLevelInterpreter.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+
</ins><span class="cx"> 2016-08-12  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Add a helper class for enumerating elements in an iterable object
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -141,7 +141,7 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_enumerator_generic_pname&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_to_index_string&quot;, &quot;length&quot; : 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_assert&quot;, &quot;length&quot; : 3 },
</span><del>-            { &quot;name&quot; : &quot;op_copy_rest&quot;, &quot;length&quot;: 4 },
</del><ins>+            { &quot;name&quot; : &quot;op_create_rest&quot;, &quot;length&quot;: 4 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_get_rest_length&quot;, &quot;length&quot;: 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_save&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_resume&quot;, &quot;length&quot; : 3 },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -90,8 +90,7 @@
</span><span class="cx">     case op_jngreatereq:
</span><span class="cx">     case op_jless:
</span><span class="cx">     case op_set_function_name:
</span><del>-    case op_log_shadow_chicken_tail:
-    case op_copy_rest: {
</del><ins>+    case op_log_shadow_chicken_tail: {
</ins><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 2);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="lines">@@ -190,6 +189,7 @@
</span><span class="cx">     case op_new_generator_func:
</span><span class="cx">     case op_get_parent_scope:
</span><span class="cx">     case op_create_scoped_arguments:
</span><ins>+    case op_create_rest:
</ins><span class="cx">     case op_get_from_arguments: {
</span><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 2);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="lines">@@ -318,7 +318,6 @@
</span><span class="cx">     OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instruction-&gt;u.opcode);
</span><span class="cx">     switch (opcodeID) {
</span><span class="cx">     // These don't define anything.
</span><del>-    case op_copy_rest:
</del><span class="cx">     case op_put_to_scope:
</span><span class="cx">     case op_end:
</span><span class="cx">     case op_throw:
</span><span class="lines">@@ -464,6 +463,7 @@
</span><span class="cx">     case op_del_by_val:
</span><span class="cx">     case op_unsigned:
</span><span class="cx">     case op_get_from_arguments: 
</span><ins>+    case op_create_rest:
</ins><span class="cx">     case op_get_rest_length: {
</span><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 1);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -832,11 +832,11 @@
</span><span class="cx">             printLocationOpAndRegisterOperand(out, exec, location, it, &quot;argument_count&quot;, r0);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        case op_copy_rest: {
</del><ins>+        case op_create_rest: {
</ins><span class="cx">             int r0 = (++it)-&gt;u.operand;
</span><span class="cx">             int r1 = (++it)-&gt;u.operand;
</span><span class="cx">             unsigned argumentOffset = (++it)-&gt;u.unsignedValue;
</span><del>-            printLocationAndOp(out, exec, location, it, &quot;copy_rest&quot;);
</del><ins>+            printLocationAndOp(out, exec, location, it, &quot;create_rest&quot;);
</ins><span class="cx">             out.printf(&quot;%s, %s, &quot;, registerName(r0).data(), registerName(r1).data());
</span><span class="cx">             out.printf(&quot;ArgumentsOffset: %u&quot;, argumentOffset);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -4435,9 +4435,7 @@
</span><span class="cx">     instructions().append(restArrayLength-&gt;index());
</span><span class="cx">     instructions().append(numParametersToSkip);
</span><span class="cx"> 
</span><del>-    emitNewArrayWithSize(result, restArrayLength.get());
-
-    emitOpcode(op_copy_rest);
</del><ins>+    emitOpcode(op_create_rest);
</ins><span class="cx">     instructions().append(result-&gt;index());
</span><span class="cx">     instructions().append(restArrayLength-&gt;index());
</span><span class="cx">     instructions().append(numParametersToSkip);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -2861,7 +2861,10 @@
</span><span class="cx">     case CheckTypeInfoFlags:
</span><span class="cx">         break;
</span><span class="cx"> 
</span><del>-    case CopyRest:
</del><ins>+    case CreateRest:
+        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) // This means we're already having a bad time.
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
+        forNode(node).setType(m_graph, SpecArray);
</ins><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case Check: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -3734,13 +3734,12 @@
</span><span class="cx">             NEXT_OPCODE(op_get_rest_length);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_copy_rest: {
</del><ins>+        case op_create_rest: {
</ins><span class="cx">             noticeArgumentsUse();
</span><del>-            Node* array = get(VirtualRegister(currentInstruction[1].u.operand));
</del><span class="cx">             Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand));
</span><del>-            addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue),
-                array, arrayLength);
-            NEXT_OPCODE(op_copy_rest);
</del><ins>+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(CreateRest, OpInfo(currentInstruction[3].u.unsignedValue), arrayLength));
+            NEXT_OPCODE(op_create_rest);
</ins><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         // === Bitwise operations ===
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCallArrayAllocatorSlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">         , m_function(function)
</span><span class="cx">         , m_resultGPR(resultGPR)
</span><span class="cx">         , m_contiguousStructure(contiguousStructure)
</span><del>-        , m_arrayStorageStructure(arrayStorageStructure)
</del><ins>+        , m_arrayStorageOrContiguousStructure(arrayStorageStructure)
</ins><span class="cx">         , m_sizeGPR(sizeGPR)
</span><span class="cx">     {
</span><span class="cx">         jit-&gt;silentSpillAllRegistersImpl(false, m_plans, resultGPR);
</span><span class="lines">@@ -97,12 +97,15 @@
</span><span class="cx">         for (unsigned i = 0; i &lt; m_plans.size(); ++i)
</span><span class="cx">             jit-&gt;silentSpill(m_plans[i]);
</span><span class="cx">         GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR);
</span><del>-        MacroAssembler::Jump bigLength = jit-&gt;m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
-        jit-&gt;m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
-        MacroAssembler::Jump done = jit-&gt;m_jit.jump();
-        bigLength.link(&amp;jit-&gt;m_jit);
-        jit-&gt;m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageStructure), scratchGPR);
-        done.link(&amp;jit-&gt;m_jit);
</del><ins>+        if (m_contiguousStructure != m_arrayStorageOrContiguousStructure) {
+            MacroAssembler::Jump bigLength = jit-&gt;m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
+            jit-&gt;m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
+            MacroAssembler::Jump done = jit-&gt;m_jit.jump();
+            bigLength.link(&amp;jit-&gt;m_jit);
+            jit-&gt;m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageOrContiguousStructure), scratchGPR);
+            done.link(&amp;jit-&gt;m_jit);
+        } else
+            jit-&gt;m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
</ins><span class="cx">         jit-&gt;callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
</span><span class="cx">         GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
</span><span class="cx">         for (unsigned i = m_plans.size(); i--;)
</span><span class="lines">@@ -115,7 +118,7 @@
</span><span class="cx">     P_JITOperation_EStZ m_function;
</span><span class="cx">     GPRReg m_resultGPR;
</span><span class="cx">     Structure* m_contiguousStructure;
</span><del>-    Structure* m_arrayStorageStructure;
</del><ins>+    Structure* m_arrayStorageOrContiguousStructure;
</ins><span class="cx">     GPRReg m_sizeGPR;
</span><span class="cx">     Vector&lt;SilentRegisterSavePlan, 2&gt; m_plans;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -235,7 +235,7 @@
</span><span class="cx">     case op_create_lexical_environment:
</span><span class="cx">     case op_get_parent_scope:
</span><span class="cx">     case op_catch:
</span><del>-    case op_copy_rest:
</del><ins>+    case op_create_rest:
</ins><span class="cx">     case op_get_rest_length:
</span><span class="cx">     case op_log_shadow_chicken_prologue:
</span><span class="cx">     case op_log_shadow_chicken_tail:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1097,9 +1097,16 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CopyRest: {
</del><ins>+    case CreateRest: {
+        if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
+            // This means we're already having a bad time.
+            read(World);
+            write(Heap);
+            return;
+        }
</ins><span class="cx">         read(Stack);
</span><del>-        write(Heap);
</del><ins>+        read(HeapObjectCount);
+        write(HeapObjectCount);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -245,7 +245,6 @@
</span><span class="cx">     case GetStack:
</span><span class="cx">     case GetFromArguments:
</span><span class="cx">     case PutToArguments:
</span><del>-    case CopyRest:
</del><span class="cx">     case LogShadowChickenPrologue:
</span><span class="cx">     case LogShadowChickenTail:
</span><span class="cx">     case GetDynamicVar:
</span><span class="lines">@@ -285,6 +284,7 @@
</span><span class="cx">     case StrCat:
</span><span class="cx">     case StringReplace:
</span><span class="cx">     case StringReplaceRegExp:
</span><ins>+    case CreateRest:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1500,9 +1500,9 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case CopyRest: {
-            fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
-            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child2());
</del><ins>+        case CreateRest: {
+            watchHavingABadTime(node);
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child1());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -659,6 +659,12 @@
</span><span class="cx">         doToChildren(node, [&amp;] (Edge edge) { result |= edge == child; });
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+
+    bool isWatchingHavingABadTimeWatchpoint(Node* node)
+    {
+        JSGlobalObject* globalObject = globalObjectFor(node-&gt;origin.semantic);
+        return watchpoints().isWatched(globalObject-&gt;havingABadTimeWatchpoint());
+    }
</ins><span class="cx">     
</span><span class="cx">     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -2319,7 +2319,7 @@
</span><span class="cx"> 
</span><span class="cx">     unsigned numberOfArgumentsToSkip()
</span><span class="cx">     {
</span><del>-        ASSERT(op() == CopyRest || op() == GetRestLength);
</del><ins>+        ASSERT(op() == CreateRest || op() == GetRestLength);
</ins><span class="cx">         return static_cast&lt;unsigned&gt;(m_opInfo);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -291,7 +291,7 @@
</span><span class="cx">     macro(NewRegexp, NodeResultJS) \
</span><span class="cx">     /* Rest Parameter */\
</span><span class="cx">     macro(GetRestLength, NodeResultInt32) \
</span><del>-    macro(CopyRest, NodeMustGenerate) \
</del><ins>+    macro(CreateRest, NodeResultJS | NodeMustGenerate) \
</ins><span class="cx">     \
</span><span class="cx">     /* Support for allocation sinking. */\
</span><span class="cx">     macro(PhantomNewObject, NodeResultJS | NodeMustGenerate) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1102,17 +1102,16 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
</del><ins>+JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
</ins><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><del>-    ASSERT(arraySize);
-    JSArray* array = jsCast&lt;JSArray*&gt;(arrayAsCell);
-    ASSERT(arraySize == array-&gt;length());
-    array-&gt;setLength(exec, arraySize);
-    for (unsigned i = 0; i &lt; arraySize; i++)
-        array-&gt;putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
</del><ins>+    JSGlobalObject* globalObject = exec-&gt;lexicalGlobalObject();
+    Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
+    static_assert(sizeof(Register) == sizeof(JSValue), &quot;This is a strong assumption here.&quot;);
+    JSValue* argumentsToCopyRegion = bitwise_cast&lt;JSValue*&gt;(argumentStart) + numberOfParamsToSkip;
+    return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment*);
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
</span><span class="cx"> JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
</span><del>-void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize);
</del><ins>+JSCell* JIT_OPERATION operationCreateRest(ExecState*, Register* argumentStart, unsigned numberOfArgumentsToSkip, unsigned arraySize);
</ins><span class="cx"> double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationObjectIsFunction(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -836,6 +836,7 @@
</span><span class="cx">             
</span><span class="cx">         case NewArray:
</span><span class="cx">         case NewArrayWithSize:
</span><ins>+        case CreateRest:
</ins><span class="cx">         case NewArrayBuffer: {
</span><span class="cx">             setPrediction(SpecArray);
</span><span class="cx">             break;
</span><span class="lines">@@ -1063,7 +1064,6 @@
</span><span class="cx">         case ExitOK:
</span><span class="cx">         case LoadVarargs:
</span><span class="cx">         case ForwardVarargs:
</span><del>-        case CopyRest:
</del><span class="cx">         case PutDynamicVar:
</span><span class="cx">             break;
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -346,7 +346,7 @@
</span><span class="cx">     case GetMyArgumentByVal:
</span><span class="cx">     case GetMyArgumentByValOutOfBounds:
</span><span class="cx">     case ForwardVarargs:
</span><del>-    case CopyRest:
</del><ins>+    case CreateRest:
</ins><span class="cx">     case StringReplace:
</span><span class="cx">     case StringReplaceRegExp:
</span><span class="cx">     case GetRegExpObjectLastIndex:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -6482,30 +6482,75 @@
</span><span class="cx">     cellResult(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileCopyRest(Node* node)
</del><ins>+void SpeculativeJIT::compileCreateRest(Node* node)
</ins><span class="cx"> {
</span><del>-    ASSERT(node-&gt;op() == CopyRest);
</del><ins>+    ASSERT(node-&gt;op() == CreateRest);
</ins><span class="cx"> 
</span><del>-    SpeculateCellOperand array(this, node-&gt;child1());
</del><ins>+#if !CPU(X86)
+    if (m_jit.graph().isWatchingHavingABadTimeWatchpoint(node)) {
+        SpeculateStrictInt32Operand arrayLength(this, node-&gt;child1());
+        GPRTemporary arrayResult(this);
+
+        GPRReg arrayLengthGPR = arrayLength.gpr();
+        GPRReg arrayResultGPR = arrayResult.gpr();
+
+        bool shouldAllowForArrayStorageStructureForLargeArrays = false;
+        compileAllocateNewArrayWithSize(m_jit.graph().globalObjectFor(node-&gt;origin.semantic), arrayResultGPR, arrayLengthGPR, ArrayWithContiguous, shouldAllowForArrayStorageStructureForLargeArrays);
+
+        GPRTemporary argumentsStart(this);
+        GPRReg argumentsStartGPR = argumentsStart.gpr();
+
+        emitGetArgumentStart(node-&gt;origin.semantic, argumentsStartGPR);
+
+        GPRTemporary butterfly(this);
+        GPRTemporary currentLength(this);
+#if USE(JSVALUE64)
+        GPRTemporary value(this);
+        JSValueRegs valueRegs = JSValueRegs(value.gpr());
+#else
+        GPRTemporary valueTag(this);
+        GPRTemporary valuePayload(this);
+        JSValueRegs valueRegs = JSValueRegs(valueTag.gpr(), valuePayload.gpr());
+#endif
+
+        GPRReg currentLengthGPR = currentLength.gpr();
+        GPRReg butterflyGPR = butterfly.gpr();
+
+        m_jit.loadPtr(MacroAssembler::Address(arrayResultGPR, JSObject::butterflyOffset()), butterflyGPR);
+
+        CCallHelpers::Jump skipLoop = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
+        m_jit.zeroExtend32ToPtr(arrayLengthGPR, currentLengthGPR);
+        m_jit.addPtr(Imm32(sizeof(Register) * node-&gt;numberOfArgumentsToSkip()), argumentsStartGPR);
+
+        auto loop = m_jit.label();
+        m_jit.sub32(TrustedImm32(1), currentLengthGPR);
+        m_jit.loadValue(JITCompiler::BaseIndex(argumentsStartGPR, currentLengthGPR, MacroAssembler::TimesEight), valueRegs);
+        m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(butterflyGPR, currentLengthGPR, MacroAssembler::TimesEight));
+        m_jit.branch32(MacroAssembler::NotEqual, currentLengthGPR, TrustedImm32(0)).linkTo(loop, &amp;m_jit);
+
+        skipLoop.link(&amp;m_jit);
+        cellResult(arrayResultGPR, node);
+        return;
+    }
+#endif // !CPU(X86)
+
+    SpeculateStrictInt32Operand arrayLength(this, node-&gt;child1());
</ins><span class="cx">     GPRTemporary argumentsStart(this);
</span><del>-    SpeculateStrictInt32Operand arrayLength(this, node-&gt;child2());
</del><ins>+    GPRTemporary numberOfArgumentsToSkip(this);
</ins><span class="cx"> 
</span><del>-    GPRReg arrayGPR = array.gpr();
</del><ins>+    GPRReg arrayLengthGPR = arrayLength.gpr();
</ins><span class="cx">     GPRReg argumentsStartGPR = argumentsStart.gpr();
</span><del>-    GPRReg arrayLengthGPR = arrayLength.gpr();
</del><span class="cx"> 
</span><del>-    CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
</del><ins>+    emitGetArgumentStart(node-&gt;origin.semantic, argumentsStartGPR);
</ins><span class="cx"> 
</span><del>-    emitGetArgumentStart(node-&gt;origin.semantic, argumentsStartGPR);
-    silentSpillAllRegisters(argumentsStartGPR);
-    // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
-    callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, Imm32(node-&gt;numberOfArgumentsToSkip()), arrayLengthGPR);
-    silentFillAllRegisters(argumentsStartGPR);
</del><ins>+    flushRegisters();
+
+    GPRFlushedCallResult result(this);
+    GPRReg resultGPR = result.gpr();
+    callOperation(operationCreateRest, resultGPR, argumentsStartGPR, Imm32(node-&gt;numberOfArgumentsToSkip()), arrayLengthGPR);
</ins><span class="cx">     m_jit.exceptionCheck();
</span><span class="cx"> 
</span><del>-    done.link(&amp;m_jit);
-
-    noResult(node);
</del><ins>+    cellResult(resultGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileGetRestLength(Node* node)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -760,6 +760,8 @@
</span><span class="cx">     void compileIsTypedArrayView(Node*);
</span><span class="cx"> 
</span><span class="cx">     void emitCall(Node*);
</span><ins>+
+    void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
</ins><span class="cx">     
</span><span class="cx">     // Called once a node has completed code generation but prior to setting
</span><span class="cx">     // its result, to free up its children. (This must happen prior to setting
</span><span class="lines">@@ -1274,10 +1276,10 @@
</span><span class="cx">         return appendCall(operation);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, Imm32 arg3, GPRReg arg4)
</del><ins>+    JITCompiler::Call callOperation(C_JITOperation_ERUiUi operation, GPRReg result, GPRReg arg1, Imm32 arg2, GPRReg arg3)
</ins><span class="cx">     {
</span><del>-        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.asTrustedImm32(), arg4);
-        return appendCall(operation);
</del><ins>+        m_jit.setupArgumentsWithExecState(arg1, arg2.asTrustedImm32(), arg3);
+        return appendCallSetResult(operation, result);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JITCompiler::Call callOperation(C_JITOperation_EJscI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* impl)
</span><span class="lines">@@ -2487,7 +2489,7 @@
</span><span class="cx">     void compilePutToArguments(Node*);
</span><span class="cx">     void compileCreateScopedArguments(Node*);
</span><span class="cx">     void compileCreateClonedArguments(Node*);
</span><del>-    void compileCopyRest(Node*);
</del><ins>+    void compileCreateRest(Node*);
</ins><span class="cx">     void compileGetRestLength(Node*);
</span><span class="cx">     void compileNotifyWrite(Node*);
</span><span class="cx">     bool compileRegExpExec(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -3890,51 +3890,11 @@
</span><span class="cx">         if (!globalObject-&gt;isHavingABadTime() &amp;&amp; !hasAnyArrayStorage(node-&gt;indexingType())) {
</span><span class="cx">             SpeculateStrictInt32Operand size(this, node-&gt;child1());
</span><span class="cx">             GPRTemporary result(this);
</span><del>-            GPRTemporary storage(this);
-            GPRTemporary scratch(this);
-            GPRTemporary scratch2(this);
-            
</del><ins>+
</ins><span class="cx">             GPRReg sizeGPR = size.gpr();
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><del>-            GPRReg storageGPR = storage.gpr();
-            GPRReg scratchGPR = scratch.gpr();
-            GPRReg scratch2GPR = scratch2.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
-            
-            ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
-            m_jit.move(sizeGPR, scratchGPR);
-            m_jit.lshift32(TrustedImm32(3), scratchGPR);
-            m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
-            slowCases.append(
-                emitAllocateBasicStorage(resultGPR, storageGPR));
-            m_jit.subPtr(scratchGPR, storageGPR);
-            Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(node-&gt;indexingType());
-            emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
-            
-            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
-            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-            
-            if (hasDouble(node-&gt;indexingType())) {
-                JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
-                
-                m_jit.move(sizeGPR, scratchGPR);
-                MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
-                MacroAssembler::Label loop = m_jit.label();
-                m_jit.sub32(TrustedImm32(1), scratchGPR);
-                m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
-                m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-                m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &amp;m_jit);
-                done.link(&amp;m_jit);
-            }
-            
-            addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorWithVariableSizeSlowPathGenerator&gt;(
-                    slowCases, this, operationNewArrayWithSize, resultGPR,
-                    globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(node-&gt;indexingType()),
-                    globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
-                    sizeGPR));
-            
</del><ins>+
+            compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node-&gt;indexingType());
</ins><span class="cx">             cellResult(resultGPR, node);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -4908,8 +4868,8 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CopyRest: {
-        compileCopyRest(node);
</del><ins>+    case CreateRest: {
+        compileCreateRest(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -5438,6 +5398,53 @@
</span><span class="cx">     doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
+{
+    GPRTemporary storage(this);
+    GPRTemporary scratch(this);
+    GPRTemporary scratch2(this);
+    
+    GPRReg storageGPR = storage.gpr();
+    GPRReg scratchGPR = scratch.gpr();
+    GPRReg scratch2GPR = scratch2.gpr();
+    
+    MacroAssembler::JumpList slowCases;
+    if (shouldConvertLargeSizeToArrayStorage)
+        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
+    
+    ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
+    m_jit.move(sizeGPR, scratchGPR);
+    m_jit.lshift32(TrustedImm32(3), scratchGPR);
+    m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
+    slowCases.append(
+        emitAllocateBasicStorage(resultGPR, storageGPR));
+    m_jit.subPtr(scratchGPR, storageGPR);
+    Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
+    
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+    
+    if (hasDouble(indexingType)) {
+        JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
+        
+        m_jit.move(sizeGPR, scratchGPR);
+        MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
+        MacroAssembler::Label loop = m_jit.label();
+        m_jit.sub32(TrustedImm32(1), scratchGPR);
+        m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+        m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &amp;m_jit);
+        done.link(&amp;m_jit);
+    }
+    
+    addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorWithVariableSizeSlowPathGenerator&gt;(
+        slowCases, this, operationNewArrayWithSize, resultGPR,
+        structure,
+        shouldConvertLargeSizeToArrayStorage ? globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        sizeGPR));
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -3852,49 +3852,9 @@
</span><span class="cx">         if (!globalObject-&gt;isHavingABadTime() &amp;&amp; !hasAnyArrayStorage(node-&gt;indexingType())) {
</span><span class="cx">             SpeculateStrictInt32Operand size(this, node-&gt;child1());
</span><span class="cx">             GPRTemporary result(this);
</span><del>-            GPRTemporary storage(this);
-            GPRTemporary scratch(this);
-            GPRTemporary scratch2(this);
-            
</del><span class="cx">             GPRReg sizeGPR = size.gpr();
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><del>-            GPRReg storageGPR = storage.gpr();
-            GPRReg scratchGPR = scratch.gpr();
-            GPRReg scratch2GPR = scratch2.gpr();
-            
-            MacroAssembler::JumpList slowCases;
-            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
-            
-            ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
-            m_jit.move(sizeGPR, scratchGPR);
-            m_jit.lshift32(TrustedImm32(3), scratchGPR);
-            m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
-            slowCases.append(
-                emitAllocateBasicStorage(resultGPR, storageGPR));
-            m_jit.subPtr(scratchGPR, storageGPR);
-            Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(node-&gt;indexingType());
-            emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
-            
-            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
-            m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-            
-            if (hasDouble(node-&gt;indexingType())) {
-                m_jit.move(TrustedImm64(bitwise_cast&lt;int64_t&gt;(PNaN)), scratchGPR);
-                m_jit.move(sizeGPR, scratch2GPR);
-                MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
-                MacroAssembler::Label loop = m_jit.label();
-                m_jit.sub32(TrustedImm32(1), scratch2GPR);
-                m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
-                m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &amp;m_jit);
-                done.link(&amp;m_jit);
-            }
-            
-            addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorWithVariableSizeSlowPathGenerator&gt;(
-                    slowCases, this, operationNewArrayWithSize, resultGPR,
-                    globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(node-&gt;indexingType()),
-                    globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
-                    sizeGPR));
-            
</del><ins>+            compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node-&gt;indexingType());
</ins><span class="cx">             cellResult(resultGPR, node);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -4855,8 +4815,8 @@
</span><span class="cx">         compileCreateClonedArguments(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-    case CopyRest: {
-        compileCopyRest(node);
</del><ins>+    case CreateRest: {
+        compileCreateRest(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -5505,6 +5465,51 @@
</span><span class="cx">     doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
+{
+    GPRTemporary storage(this);
+    GPRTemporary scratch(this);
+    GPRTemporary scratch2(this);
+    
+    GPRReg storageGPR = storage.gpr();
+    GPRReg scratchGPR = scratch.gpr();
+    GPRReg scratch2GPR = scratch2.gpr();
+    
+    MacroAssembler::JumpList slowCases;
+    if (shouldConvertLargeSizeToArrayStorage)
+        slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
+    
+    ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
+    m_jit.move(sizeGPR, scratchGPR);
+    m_jit.lshift32(TrustedImm32(3), scratchGPR);
+    m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
+    slowCases.append(
+        emitAllocateBasicStorage(resultGPR, storageGPR));
+    m_jit.subPtr(scratchGPR, storageGPR);
+    Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
+    
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
+    
+    if (hasDouble(indexingType)) {
+        m_jit.move(TrustedImm64(bitwise_cast&lt;int64_t&gt;(PNaN)), scratchGPR);
+        m_jit.move(sizeGPR, scratch2GPR);
+        MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
+        MacroAssembler::Label loop = m_jit.label();
+        m_jit.sub32(TrustedImm32(1), scratch2GPR);
+        m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
+        m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &amp;m_jit);
+        done.link(&amp;m_jit);
+    }
+    
+    addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorWithVariableSizeSlowPathGenerator&gt;(
+        slowCases, this, operationNewArrayWithSize, resultGPR,
+        structure,
+        shouldConvertLargeSizeToArrayStorage ? globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        sizeGPR));
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -229,7 +229,7 @@
</span><span class="cx">     case PutGetterSetterById:
</span><span class="cx">     case PutGetterByVal:
</span><span class="cx">     case PutSetterByVal:
</span><del>-    case CopyRest:
</del><ins>+    case CreateRest:
</ins><span class="cx">     case GetRestLength:
</span><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -972,8 +972,8 @@
</span><span class="cx">         case CheckWatchdogTimer:
</span><span class="cx">             compileCheckWatchdogTimer();
</span><span class="cx">             break;
</span><del>-        case CopyRest:
-            compileCopyRest();
</del><ins>+        case CreateRest:
+            compileCreateRest();
</ins><span class="cx">             break;
</span><span class="cx">         case GetRestLength:
</span><span class="cx">             compileGetRestLength();
</span><span class="lines">@@ -3863,26 +3863,40 @@
</span><span class="cx">         setJSValue(result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileCopyRest()
-    {            
-        LBasicBlock doCopyRest = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
</del><ins>+    void compileCreateRest()
+    {
+        if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) {
+            LBasicBlock continuation = m_out.newBlock();
+            LValue arrayLength = lowInt32(m_node-&gt;child1());
+            LBasicBlock loopStart = m_out.newBlock();
+            bool shouldLargeArraySizeCreateArrayStorage = false;
+            LValue array = compileAllocateArrayWithSize(arrayLength, ArrayWithContiguous, shouldLargeArraySizeCreateArrayStorage);
</ins><span class="cx"> 
</span><del>-        LValue arrayLength = lowInt32(m_node-&gt;child2());
</del><ins>+            LValue butterfly = m_out.loadPtr(array, m_heaps.JSObject_butterfly);
+            ValueFromBlock startLength = m_out.anchor(arrayLength);
+            LValue argumentRegion = m_out.add(getArgumentsStart(), m_out.constInt64(sizeof(Register) * m_node-&gt;numberOfArgumentsToSkip()));
+            m_out.branch(m_out.equal(arrayLength, m_out.constInt32(0)),
+                unsure(continuation), unsure(loopStart));
</ins><span class="cx"> 
</span><del>-        m_out.branch(
-            m_out.equal(arrayLength, m_out.constInt32(0)),
-            unsure(continuation), unsure(doCopyRest));
-            
-        LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
-        // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
</del><ins>+            LBasicBlock lastNext = m_out.appendTo(loopStart, continuation);
+            LValue phiOffset = m_out.phi(Int32, startLength);
+            LValue currentOffset = m_out.sub(phiOffset, m_out.int32One);
+            m_out.addIncomingToPhi(phiOffset, m_out.anchor(currentOffset));
+            LValue loadedValue = m_out.load64(m_out.baseIndex(m_heaps.variables, argumentRegion, m_out.zeroExtPtr(currentOffset)));
+            IndexedAbstractHeap&amp; heap = m_heaps.indexedContiguousProperties;
+            m_out.store(loadedValue, m_out.baseIndex(heap, butterfly, m_out.zeroExtPtr(currentOffset)), Output::Store64);
+            m_out.branch(m_out.equal(currentOffset, m_out.constInt32(0)), unsure(continuation), unsure(loopStart));
+
+            m_out.appendTo(continuation, lastNext);
+            setJSValue(array);
+            return;
+        }
+
+        LValue arrayLength = lowInt32(m_node-&gt;child1());
+        LValue argumentStart = getArgumentsStart();
</ins><span class="cx">         LValue numberOfArgumentsToSkip = m_out.constInt32(m_node-&gt;numberOfArgumentsToSkip());
</span><del>-        vmCall(
-            Void,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node-&gt;child1()),
-            getArgumentsStart(), numberOfArgumentsToSkip, arrayLength);
-        m_out.jump(continuation);
-
-        m_out.appendTo(continuation, lastNext);
</del><ins>+        setJSValue(vmCall(
+            Int64, m_out.operation(operationCreateRest), m_callFrame, argumentStart, numberOfArgumentsToSkip, arrayLength));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void compileGetRestLength()
</span><span class="lines">@@ -4028,81 +4042,99 @@
</span><span class="cx">             m_out.constIntPtr(structure), m_out.constIntPtr(m_node-&gt;startConstant()),
</span><span class="cx">             m_out.constIntPtr(m_node-&gt;numConstants())));
</span><span class="cx">     }
</span><del>-    
-    void compileNewArrayWithSize()
</del><ins>+
+    LValue compileAllocateArrayWithSize(LValue publicLength, IndexingType indexingType, bool shouldLargeArraySizeCreateArrayStorage = true)
</ins><span class="cx">     {
</span><del>-        LValue publicLength = lowInt32(m_node-&gt;child1());
-        
</del><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
</span><del>-        Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(
-            m_node-&gt;indexingType());
-        
-        if (!globalObject-&gt;isHavingABadTime() &amp;&amp; !hasAnyArrayStorage(m_node-&gt;indexingType())) {
-            ASSERT(
-                hasUndecided(structure-&gt;indexingType())
-                || hasInt32(structure-&gt;indexingType())
-                || hasDouble(structure-&gt;indexingType())
-                || hasContiguous(structure-&gt;indexingType()));
</del><ins>+        Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
+        ASSERT(
+            hasUndecided(structure-&gt;indexingType())
+            || hasInt32(structure-&gt;indexingType())
+            || hasDouble(structure-&gt;indexingType())
+            || hasContiguous(structure-&gt;indexingType()));
</ins><span class="cx"> 
</span><del>-            LBasicBlock fastCase = m_out.newBlock();
-            LBasicBlock largeCase = m_out.newBlock();
-            LBasicBlock failCase = m_out.newBlock();
-            LBasicBlock slowCase = m_out.newBlock();
-            LBasicBlock continuation = m_out.newBlock();
-            
</del><ins>+        LBasicBlock fastCase = m_out.newBlock();
+        LBasicBlock largeCase = shouldLargeArraySizeCreateArrayStorage ? m_out.newBlock() : nullptr;
+        LBasicBlock failCase = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+        LBasicBlock lastNext = nullptr;
+        if (shouldLargeArraySizeCreateArrayStorage) {
</ins><span class="cx">             m_out.branch(
</span><span class="cx">                 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)),
</span><span class="cx">                 rarely(largeCase), usually(fastCase));
</span><ins>+            lastNext = m_out.appendTo(fastCase, largeCase);
+        }
</ins><span class="cx"> 
</span><del>-            LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase);
-            
-            // We don't round up to BASE_VECTOR_LEN for new Array(blah).
-            LValue vectorLength = publicLength;
-            
-            LValue payloadSize =
-                m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
-            
-            LValue butterflySize = m_out.add(
-                payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
-            
-            LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
-            
-            LValue butterfly = m_out.sub(endOfStorage, payloadSize);
-            
-            LValue object = allocateObject&lt;JSArray&gt;(structure, butterfly, failCase);
-            
-            m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
-            m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
</del><ins>+        
+        // We don't round up to BASE_VECTOR_LEN for new Array(blah).
+        LValue vectorLength = publicLength;
+        
+        LValue payloadSize =
+            m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
+        
+        LValue butterflySize = m_out.add(
+            payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
+        
+        LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
+        
+        LValue butterfly = m_out.sub(endOfStorage, payloadSize);
+        
+        LValue object = allocateObject&lt;JSArray&gt;(structure, butterfly, failCase);
+        
+        m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
+        m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
</ins><span class="cx"> 
</span><del>-            initializeArrayElements(m_node-&gt;indexingType(), vectorLength, butterfly);
-            
-            ValueFromBlock fastResult = m_out.anchor(object);
-            m_out.jump(continuation);
-            
</del><ins>+        initializeArrayElements(indexingType, vectorLength, butterfly);
+        
+        ValueFromBlock fastResult = m_out.anchor(object);
+        m_out.jump(continuation);
+        
+        LValue structureValue;
+        if (shouldLargeArraySizeCreateArrayStorage) {
+            LBasicBlock slowCase = m_out.newBlock();
+
</ins><span class="cx">             m_out.appendTo(largeCase, failCase);
</span><span class="cx">             ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
</span><span class="cx">                 globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
</span><span class="cx">             m_out.jump(slowCase);
</span><del>-            
</del><ins>+
</ins><span class="cx">             m_out.appendTo(failCase, slowCase);
</span><span class="cx">             ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
</span><span class="cx">             m_out.jump(slowCase);
</span><del>-            
</del><ins>+
</ins><span class="cx">             m_out.appendTo(slowCase, continuation);
</span><del>-            LValue structureValue = m_out.phi(
</del><ins>+            structureValue = m_out.phi(
</ins><span class="cx">                 pointerType(), largeStructure, failStructure);
</span><del>-            LValue slowResultValue = lazySlowPath(
-                [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
-                    return createLazyCallGenerator(
-                        operationNewArrayWithSize, locations[0].directGPR(),
-                        locations[1].directGPR(), locations[2].directGPR());
-                },
-                structureValue, publicLength);
-            ValueFromBlock slowResult = m_out.anchor(slowResultValue);
-            m_out.jump(continuation);
-            
-            m_out.appendTo(continuation, lastNext);
-            setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
</del><ins>+        } else {
+            ASSERT(!lastNext);
+            lastNext = m_out.appendTo(failCase, continuation);
+            structureValue = m_out.constIntPtr(structure);
+        }
+
+        LValue slowResultValue = lazySlowPath(
+            [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
+                return createLazyCallGenerator(
+                    operationNewArrayWithSize, locations[0].directGPR(),
+                    locations[1].directGPR(), locations[2].directGPR());
+            },
+            structureValue, publicLength);
+        ValueFromBlock slowResult = m_out.anchor(slowResultValue);
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        return m_out.phi(pointerType(), fastResult, slowResult);
+    }
+    
+    void compileNewArrayWithSize()
+    {
+        LValue publicLength = lowInt32(m_node-&gt;child1());
+        
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
+        Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(
+            m_node-&gt;indexingType());
+        
+        if (!globalObject-&gt;isHavingABadTime() &amp;&amp; !hasAnyArrayStorage(m_node-&gt;indexingType())) {
+            setJSValue(compileAllocateArrayWithSize(publicLength, m_node-&gt;indexingType()));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterCallFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/CallFrame.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/interpreter/CallFrame.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -211,6 +211,7 @@
</span><span class="cx">         // arguments(0) will not fetch the 'this' value. To get/set 'this',
</span><span class="cx">         // use thisValue() and setThisValue() below.
</span><span class="cx"> 
</span><ins>+        JSValue* addressOfArgumentsStart() const { return bitwise_cast&lt;JSValue*&gt;(this + argumentOffset(0)); }
</ins><span class="cx">         JSValue argument(size_t argument)
</span><span class="cx">         {
</span><span class="cx">             if (argument &gt;= argumentCount())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -231,7 +231,7 @@
</span><span class="cx">         DEFINE_OP(op_create_scoped_arguments)
</span><span class="cx">         DEFINE_OP(op_create_cloned_arguments)
</span><span class="cx">         DEFINE_OP(op_argument_count)
</span><del>-        DEFINE_OP(op_copy_rest)
</del><ins>+        DEFINE_OP(op_create_rest)
</ins><span class="cx">         DEFINE_OP(op_get_rest_length)
</span><span class="cx">         DEFINE_OP(op_check_tdz)
</span><span class="cx">         DEFINE_OP(op_assert)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -493,7 +493,7 @@
</span><span class="cx">         void emit_op_create_scoped_arguments(Instruction*);
</span><span class="cx">         void emit_op_create_cloned_arguments(Instruction*);
</span><span class="cx">         void emit_op_argument_count(Instruction*);
</span><del>-        void emit_op_copy_rest(Instruction*);
</del><ins>+        void emit_op_create_rest(Instruction*);
</ins><span class="cx">         void emit_op_get_rest_length(Instruction*);
</span><span class="cx">         void emit_op_check_tdz(Instruction*);
</span><span class="cx">         void emit_op_assert(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1458,9 +1458,9 @@
</span><span class="cx">     emitPutVirtualRegister(dst, result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_copy_rest(Instruction* currentInstruction)
</del><ins>+void JIT::emit_op_create_rest(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><del>-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);
</del><ins>+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_rest);
</ins><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -262,7 +262,7 @@
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_EVm)(ExecState*, VM*);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_J)(EncodedJSValue);
</span><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_Z)(int32_t);
</span><del>-typedef void (JIT_OPERATION *V_JITOperation_ECRUiUi)(ExecState*, JSCell*, Register*, uint32_t, uint32_t);
</del><ins>+typedef JSCell* (JIT_OPERATION *C_JITOperation_ERUiUi)(ExecState*, Register*, uint32_t, uint32_t);
</ins><span class="cx"> typedef void (JIT_OPERATION *V_JITOperation_EOJIUi)(ExecState*, JSObject*, EncodedJSValue, UniquedStringImpl*, uint32_t);
</span><span class="cx"> typedef char* (JIT_OPERATION *P_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef char* (JIT_OPERATION *P_JITOperation_EC)(ExecState*, JSCell*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -1762,9 +1762,9 @@
</span><span class="cx">     callOpcodeSlowPath(_slow_path_to_index_string)
</span><span class="cx">     dispatch(3)
</span><span class="cx"> 
</span><del>-_llint_op_copy_rest:
</del><ins>+_llint_op_create_rest:
</ins><span class="cx">     traceExecution()
</span><del>-    callOpcodeSlowPath(_slow_path_copy_rest)
</del><ins>+    callOpcodeSlowPath(_slow_path_create_rest)
</ins><span class="cx">     dispatch(4)
</span><span class="cx"> 
</span><span class="cx"> _llint_op_instanceof:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -848,20 +848,15 @@
</span><span class="cx">     RETURN(resolvedScope);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SLOW_PATH_DECL(slow_path_copy_rest)
</del><ins>+SLOW_PATH_DECL(slow_path_create_rest)
</ins><span class="cx"> {
</span><span class="cx">     BEGIN();
</span><span class="cx">     unsigned arraySize = OP_C(2).jsValue().asUInt32();
</span><del>-    if (!arraySize) {
-        ASSERT(!jsCast&lt;JSArray*&gt;(OP(1).jsValue())-&gt;length());
-        END();
-    }
-    JSArray* array = jsCast&lt;JSArray*&gt;(OP(1).jsValue());
-    ASSERT(arraySize == array-&gt;length());
</del><ins>+    JSGlobalObject* globalObject = exec-&gt;lexicalGlobalObject();
+    Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
</ins><span class="cx">     unsigned numParamsToSkip = pc[3].u.unsignedValue;
</span><del>-    for (unsigned i = 0; i &lt; arraySize; i++)
-        array-&gt;putDirectIndex(exec, i, exec-&gt;uncheckedArgument(i + numParamsToSkip));
-    END();
</del><ins>+    JSValue* argumentsToCopyRegion = exec-&gt;addressOfArgumentsStart() + numParamsToSkip;
+    RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> SLOW_PATH_DECL(slow_path_get_by_id_with_this)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (204438 => 204439)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-08-13 02:14:42 UTC (rev 204439)
</span><span class="lines">@@ -253,7 +253,7 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
</span><del>-SLOW_PATH_HIDDEN_DECL(slow_path_copy_rest);
</del><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_create_rest);
</ins><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_with_this);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val_with_this);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id_with_this);
</span></span></pre>
</div>
</div>

</body>
</html>