Title: [204439] trunk
Revision
204439
Author
sbar...@apple.com
Date
2016-08-12 19:14:42 -0700 (Fri, 12 Aug 2016)

Log Message

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/_javascript_Core:

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<AbstractStateType>::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):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (204438 => 204439)


--- trunk/JSTests/ChangeLog	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/JSTests/ChangeLog	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,14 @@
+2016-08-12  Saam Barati  <sbar...@apple.com>
+
+        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.
+
 2016-08-12  Skachkov Oleksandr  <gskach...@gmail.com>
 
         [ES2016] Implement Object.entries

Added: trunk/JSTests/stress/rest-parameter-having-a-bad-time.js (0 => 204439)


--- 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)
@@ -0,0 +1,68 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad!")
+}
+noInline(assert);
+
+function test1() {
+    function foo(...c) {
+        return c;
+    }
+    noInline(foo);
+
+    let arr = [1,2,3];
+    for (let i = 0; i < 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, "10", {
+        get() { return 35; },
+        set(x) { called = true; }
+    });
+    let called2 = false;
+    Reflect.defineProperty(Array.prototype, "0", {
+        get: function() { print("In get!"); return 35; },
+        set: function(x) { called2 = true; }
+    });
+
+    for (let i = 0; i < 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] = "foo";
+        assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+    }
+
+    for (let i = 0; i < 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] = "foo";
+        assert(!called2); // Creating a rest should defineProperty, ensuring we don't call the setter.
+    }
+}
+test1();

Added: trunk/JSTests/stress/rest-parameter-many-arguments.js (0 => 204439)


--- 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)
@@ -0,0 +1,49 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad!")
+}
+noInline(assert);
+
+let calledGet = false;
+let definedAccessor = false;
+function test() {
+    function foo(...rest) {
+        return rest;
+    }
+    noInline(foo);
+
+    for (let i = 0; i < 10000; i++) {
+        const size = 800;
+        let arr = new Array(size);
+        for (let i = 0; i < size; i++)
+            arr[i] = i;
+        let result = foo(...arr);
+
+        assert(result.length === arr.length);
+        assert(result.length === size);
+        for (let i = 0; i < 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, "0", {
+    get() { calledGet = true; return 0; },
+    set(x) {  }
+});
+test();

Added: trunk/JSTests/stress/rest-parameter-various-types.js (0 => 204439)


--- 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)
@@ -0,0 +1,98 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad!");
+}
+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 < 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 < 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) && isNaN(r[0])));
+                assert(r[1] === b || (isNaN(b) && 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 < 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);
+

Modified: trunk/LayoutTests/ChangeLog (204438 => 204439)


--- trunk/LayoutTests/ChangeLog	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/LayoutTests/ChangeLog	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,18 @@
+2016-08-12  Saam Barati  <sbar...@apple.com>
+
+        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):
+
 2016-08-12  Ryan Haddad  <ryanhad...@apple.com>
 
         Add mac-wk1 baseline for js/dom/global-constructors-attributes.html after r204396.

Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance-expected.txt (0 => 204439)


--- 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)
@@ -0,0 +1,10 @@
+JSRegress/rest-parameter-construction-performance
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/rest-parameter-construction-performance.html (0 => 204439)


--- 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)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/rest-parameter-construction-performance.js (0 => 204439)


--- 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)
@@ -0,0 +1,27 @@
+"use strict";
+
+function foo(...rest) {
+    return rest;
+}
+noInline(foo);
+
+const iters = 900000;
+function test1() {
+    let o = {};
+    let a = [];
+    for (let i = 0; i < 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 < iters; i++)
+        foo(10, 20, o, 55, a, 120.341, a, o);
+}
+
+test1();
+test2();

Modified: trunk/Source/_javascript_Core/ChangeLog (204438 => 204439)


--- trunk/Source/_javascript_Core/ChangeLog	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1,3 +1,97 @@
+2016-08-12  Saam Barati  <sbar...@apple.com>
+
+        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<AbstractStateType>::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:
+
 2016-08-12  Ryosuke Niwa  <rn...@webkit.org>
 
         Add a helper class for enumerating elements in an iterable object

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeList.json (204438 => 204439)


--- trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeList.json	2016-08-13 02:14:42 UTC (rev 204439)
@@ -141,7 +141,7 @@
             { "name" : "op_enumerator_generic_pname", "length" : 4 },
             { "name" : "op_to_index_string", "length" : 3 },
             { "name" : "op_assert", "length" : 3 },
-            { "name" : "op_copy_rest", "length": 4 },
+            { "name" : "op_create_rest", "length": 4 },
             { "name" : "op_get_rest_length", "length": 3 },
             { "name" : "op_save", "length" : 4 },
             { "name" : "op_resume", "length" : 3 },

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h (204438 => 204439)


--- trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeUseDef.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -90,8 +90,7 @@
     case op_jngreatereq:
     case op_jless:
     case op_set_function_name:
-    case op_log_shadow_chicken_tail:
-    case op_copy_rest: {
+    case op_log_shadow_chicken_tail: {
         ASSERT(opcodeLengths[opcodeID] > 2);
         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -190,6 +189,7 @@
     case op_new_generator_func:
     case op_get_parent_scope:
     case op_create_scoped_arguments:
+    case op_create_rest:
     case op_get_from_arguments: {
         ASSERT(opcodeLengths[opcodeID] > 2);
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -318,7 +318,6 @@
     OpcodeID opcodeID = interpreter->getOpcodeID(instruction->u.opcode);
     switch (opcodeID) {
     // These don't define anything.
-    case op_copy_rest:
     case op_put_to_scope:
     case op_end:
     case op_throw:
@@ -464,6 +463,7 @@
     case op_del_by_val:
     case op_unsigned:
     case op_get_from_arguments: 
+    case op_create_rest:
     case op_get_rest_length: {
         ASSERT(opcodeLengths[opcodeID] > 1);
         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -832,11 +832,11 @@
             printLocationOpAndRegisterOperand(out, exec, location, it, "argument_count", r0);
             break;
         }
-        case op_copy_rest: {
+        case op_create_rest: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             unsigned argumentOffset = (++it)->u.unsignedValue;
-            printLocationAndOp(out, exec, location, it, "copy_rest");
+            printLocationAndOp(out, exec, location, it, "create_rest");
             out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
             out.printf("ArgumentsOffset: %u", argumentOffset);
             break;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -4435,9 +4435,7 @@
     instructions().append(restArrayLength->index());
     instructions().append(numParametersToSkip);
 
-    emitNewArrayWithSize(result, restArrayLength.get());
-
-    emitOpcode(op_copy_rest);
+    emitOpcode(op_create_rest);
     instructions().append(result->index());
     instructions().append(restArrayLength->index());
     instructions().append(numParametersToSkip);

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -2861,7 +2861,10 @@
     case CheckTypeInfoFlags:
         break;
 
-    case CopyRest:
+    case CreateRest:
+        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) // This means we're already having a bad time.
+            clobberWorld(node->origin.semantic, clobberLimit);
+        forNode(node).setType(m_graph, SpecArray);
         break;
             
     case Check: {

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -3734,13 +3734,12 @@
             NEXT_OPCODE(op_get_rest_length);
         }
 
-        case op_copy_rest: {
+        case op_create_rest: {
             noticeArgumentsUse();
-            Node* array = get(VirtualRegister(currentInstruction[1].u.operand));
             Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand));
-            addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue),
-                array, arrayLength);
-            NEXT_OPCODE(op_copy_rest);
+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(CreateRest, OpInfo(currentInstruction[3].u.unsignedValue), arrayLength));
+            NEXT_OPCODE(op_create_rest);
         }
             
         // === Bitwise operations ===

Modified: trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGCallArrayAllocatorSlowPathGenerator.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -84,7 +84,7 @@
         , m_function(function)
         , m_resultGPR(resultGPR)
         , m_contiguousStructure(contiguousStructure)
-        , m_arrayStorageStructure(arrayStorageStructure)
+        , m_arrayStorageOrContiguousStructure(arrayStorageStructure)
         , m_sizeGPR(sizeGPR)
     {
         jit->silentSpillAllRegistersImpl(false, m_plans, resultGPR);
@@ -97,12 +97,15 @@
         for (unsigned i = 0; i < m_plans.size(); ++i)
             jit->silentSpill(m_plans[i]);
         GPRReg scratchGPR = AssemblyHelpers::selectScratchGPR(m_sizeGPR);
-        MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
-        jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
-        MacroAssembler::Jump done = jit->m_jit.jump();
-        bigLength.link(&jit->m_jit);
-        jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageStructure), scratchGPR);
-        done.link(&jit->m_jit);
+        if (m_contiguousStructure != m_arrayStorageOrContiguousStructure) {
+            MacroAssembler::Jump bigLength = jit->m_jit.branch32(MacroAssembler::AboveOrEqual, m_sizeGPR, MacroAssembler::TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH));
+            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
+            MacroAssembler::Jump done = jit->m_jit.jump();
+            bigLength.link(&jit->m_jit);
+            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_arrayStorageOrContiguousStructure), scratchGPR);
+            done.link(&jit->m_jit);
+        } else
+            jit->m_jit.move(MacroAssembler::TrustedImmPtr(m_contiguousStructure), scratchGPR);
         jit->callOperation(m_function, m_resultGPR, scratchGPR, m_sizeGPR);
         GPRReg canTrample = SpeculativeJIT::pickCanTrample(m_resultGPR);
         for (unsigned i = m_plans.size(); i--;)
@@ -115,7 +118,7 @@
     P_JITOperation_EStZ m_function;
     GPRReg m_resultGPR;
     Structure* m_contiguousStructure;
-    Structure* m_arrayStorageStructure;
+    Structure* m_arrayStorageOrContiguousStructure;
     GPRReg m_sizeGPR;
     Vector<SilentRegisterSavePlan, 2> m_plans;
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -235,7 +235,7 @@
     case op_create_lexical_environment:
     case op_get_parent_scope:
     case op_catch:
-    case op_copy_rest:
+    case op_create_rest:
     case op_get_rest_length:
     case op_log_shadow_chicken_prologue:
     case op_log_shadow_chicken_tail:

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1097,9 +1097,16 @@
         return;
     }
 
-    case CopyRest: {
+    case CreateRest: {
+        if (!graph.isWatchingHavingABadTimeWatchpoint(node)) {
+            // This means we're already having a bad time.
+            read(World);
+            write(Heap);
+            return;
+        }
         read(Stack);
-        write(Heap);
+        read(HeapObjectCount);
+        write(HeapObjectCount);
         return;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -245,7 +245,6 @@
     case GetStack:
     case GetFromArguments:
     case PutToArguments:
-    case CopyRest:
     case LogShadowChickenPrologue:
     case LogShadowChickenTail:
     case GetDynamicVar:
@@ -285,6 +284,7 @@
     case StrCat:
     case StringReplace:
     case StringReplaceRegExp:
+    case CreateRest:
         return true;
         
     case MultiPutByOffset:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1500,9 +1500,9 @@
             break;
         }
 
-        case CopyRest: {
-            fixEdge<KnownCellUse>(node->child1());
-            fixEdge<KnownInt32Use>(node->child2());
+        case CreateRest: {
+            watchHavingABadTime(node);
+            fixEdge<KnownInt32Use>(node->child1());
             break;
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -659,6 +659,12 @@
         doToChildren(node, [&] (Edge edge) { result |= edge == child; });
         return result;
     }
+
+    bool isWatchingHavingABadTimeWatchpoint(Node* node)
+    {
+        JSGlobalObject* globalObject = globalObjectFor(node->origin.semantic);
+        return watchpoints().isWatched(globalObject->havingABadTimeWatchpoint());
+    }
     
     Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -2319,7 +2319,7 @@
 
     unsigned numberOfArgumentsToSkip()
     {
-        ASSERT(op() == CopyRest || op() == GetRestLength);
+        ASSERT(op() == CreateRest || op() == GetRestLength);
         return static_cast<unsigned>(m_opInfo);
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -291,7 +291,7 @@
     macro(NewRegexp, NodeResultJS) \
     /* Rest Parameter */\
     macro(GetRestLength, NodeResultInt32) \
-    macro(CopyRest, NodeMustGenerate) \
+    macro(CreateRest, NodeResultJS | NodeMustGenerate) \
     \
     /* Support for allocation sinking. */\
     macro(PhantomNewObject, NodeResultJS | NodeMustGenerate) \

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1102,17 +1102,16 @@
     return result;
 }
 
-void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
+JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
 {
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
 
-    ASSERT(arraySize);
-    JSArray* array = jsCast<JSArray*>(arrayAsCell);
-    ASSERT(arraySize == array->length());
-    array->setLength(exec, arraySize);
-    for (unsigned i = 0; i < arraySize; i++)
-        array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
+    static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
+    JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
+    return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
 }
 
 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -121,7 +121,7 @@
 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment*);
 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
-void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize);
+JSCell* JIT_OPERATION operationCreateRest(ExecState*, Register* argumentStart, unsigned numberOfArgumentsToSkip, unsigned arraySize);
 double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
 size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
 size_t JIT_OPERATION operationObjectIsFunction(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -836,6 +836,7 @@
             
         case NewArray:
         case NewArrayWithSize:
+        case CreateRest:
         case NewArrayBuffer: {
             setPrediction(SpecArray);
             break;
@@ -1063,7 +1064,6 @@
         case ExitOK:
         case LoadVarargs:
         case ForwardVarargs:
-        case CopyRest:
         case PutDynamicVar:
             break;
             

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -346,7 +346,7 @@
     case GetMyArgumentByVal:
     case GetMyArgumentByValOutOfBounds:
     case ForwardVarargs:
-    case CopyRest:
+    case CreateRest:
     case StringReplace:
     case StringReplaceRegExp:
     case GetRegExpObjectLastIndex:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -6482,30 +6482,75 @@
     cellResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileCopyRest(Node* node)
+void SpeculativeJIT::compileCreateRest(Node* node)
 {
-    ASSERT(node->op() == CopyRest);
+    ASSERT(node->op() == CreateRest);
 
-    SpeculateCellOperand array(this, node->child1());
+#if !CPU(X86)
+    if (m_jit.graph().isWatchingHavingABadTimeWatchpoint(node)) {
+        SpeculateStrictInt32Operand arrayLength(this, node->child1());
+        GPRTemporary arrayResult(this);
+
+        GPRReg arrayLengthGPR = arrayLength.gpr();
+        GPRReg arrayResultGPR = arrayResult.gpr();
+
+        bool shouldAllowForArrayStorageStructureForLargeArrays = false;
+        compileAllocateNewArrayWithSize(m_jit.graph().globalObjectFor(node->origin.semantic), arrayResultGPR, arrayLengthGPR, ArrayWithContiguous, shouldAllowForArrayStorageStructureForLargeArrays);
+
+        GPRTemporary argumentsStart(this);
+        GPRReg argumentsStartGPR = argumentsStart.gpr();
+
+        emitGetArgumentStart(node->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->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, &m_jit);
+
+        skipLoop.link(&m_jit);
+        cellResult(arrayResultGPR, node);
+        return;
+    }
+#endif // !CPU(X86)
+
+    SpeculateStrictInt32Operand arrayLength(this, node->child1());
     GPRTemporary argumentsStart(this);
-    SpeculateStrictInt32Operand arrayLength(this, node->child2());
+    GPRTemporary numberOfArgumentsToSkip(this);
 
-    GPRReg arrayGPR = array.gpr();
+    GPRReg arrayLengthGPR = arrayLength.gpr();
     GPRReg argumentsStartGPR = argumentsStart.gpr();
-    GPRReg arrayLengthGPR = arrayLength.gpr();
 
-    CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
+    emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
 
-    emitGetArgumentStart(node->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->numberOfArgumentsToSkip()), arrayLengthGPR);
-    silentFillAllRegisters(argumentsStartGPR);
+    flushRegisters();
+
+    GPRFlushedCallResult result(this);
+    GPRReg resultGPR = result.gpr();
+    callOperation(operationCreateRest, resultGPR, argumentsStartGPR, Imm32(node->numberOfArgumentsToSkip()), arrayLengthGPR);
     m_jit.exceptionCheck();
 
-    done.link(&m_jit);
-
-    noResult(node);
+    cellResult(resultGPR, node);
 }
 
 void SpeculativeJIT::compileGetRestLength(Node* node)

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -760,6 +760,8 @@
     void compileIsTypedArrayView(Node*);
 
     void emitCall(Node*);
+
+    void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
     
     // Called once a node has completed code generation but prior to setting
     // its result, to free up its children. (This must happen prior to setting
@@ -1274,10 +1276,10 @@
         return appendCall(operation);
     }
 
-    JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, Imm32 arg3, GPRReg arg4)
+    JITCompiler::Call callOperation(C_JITOperation_ERUiUi operation, GPRReg result, GPRReg arg1, Imm32 arg2, GPRReg arg3)
     {
-        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.asTrustedImm32(), arg4);
-        return appendCall(operation);
+        m_jit.setupArgumentsWithExecState(arg1, arg2.asTrustedImm32(), arg3);
+        return appendCallSetResult(operation, result);
     }
 
     JITCompiler::Call callOperation(C_JITOperation_EJscI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* impl)
@@ -2487,7 +2489,7 @@
     void compilePutToArguments(Node*);
     void compileCreateScopedArguments(Node*);
     void compileCreateClonedArguments(Node*);
-    void compileCopyRest(Node*);
+    void compileCreateRest(Node*);
     void compileGetRestLength(Node*);
     void compileNotifyWrite(Node*);
     bool compileRegExpExec(Node*);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -3890,51 +3890,11 @@
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
             SpeculateStrictInt32Operand size(this, node->child1());
             GPRTemporary result(this);
-            GPRTemporary storage(this);
-            GPRTemporary scratch(this);
-            GPRTemporary scratch2(this);
-            
+
             GPRReg sizeGPR = size.gpr();
             GPRReg resultGPR = result.gpr();
-            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 << 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->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
-            emitAllocateJSObject<JSArray>(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->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, &m_jit);
-                done.link(&m_jit);
-            }
-            
-            addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
-                    slowCases, this, operationNewArrayWithSize, resultGPR,
-                    globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
-                    globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
-                    sizeGPR));
-            
+
+            compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node->indexingType());
             cellResult(resultGPR, node);
             break;
         }
@@ -4908,8 +4868,8 @@
         break;
     }
 
-    case CopyRest: {
-        compileCopyRest(node);
+    case CreateRest: {
+        compileCreateRest(node);
         break;
     }
 
@@ -5438,6 +5398,53 @@
     doubleResult(result.fpr(), node);
 }
 
+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 << 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->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    emitAllocateJSObject<JSArray>(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, &m_jit);
+        done.link(&m_jit);
+    }
+    
+    addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
+        slowCases, this, operationNewArrayWithSize, resultGPR,
+        structure,
+        shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        sizeGPR));
+}
+
 #endif
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -3852,49 +3852,9 @@
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
             SpeculateStrictInt32Operand size(this, node->child1());
             GPRTemporary result(this);
-            GPRTemporary storage(this);
-            GPRTemporary scratch(this);
-            GPRTemporary scratch2(this);
-            
             GPRReg sizeGPR = size.gpr();
             GPRReg resultGPR = result.gpr();
-            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 << 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->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
-            emitAllocateJSObject<JSArray>(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->indexingType())) {
-                m_jit.move(TrustedImm64(bitwise_cast<int64_t>(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, &m_jit);
-                done.link(&m_jit);
-            }
-            
-            addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
-                    slowCases, this, operationNewArrayWithSize, resultGPR,
-                    globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()),
-                    globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage),
-                    sizeGPR));
-            
+            compileAllocateNewArrayWithSize(globalObject, resultGPR, sizeGPR, node->indexingType());
             cellResult(resultGPR, node);
             break;
         }
@@ -4855,8 +4815,8 @@
         compileCreateClonedArguments(node);
         break;
     }
-    case CopyRest: {
-        compileCopyRest(node);
+    case CreateRest: {
+        compileCreateRest(node);
         break;
     }
 
@@ -5505,6 +5465,51 @@
     doubleResult(result.fpr(), node);
 }
 
+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 << 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->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+    emitAllocateJSObject<JSArray>(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<int64_t>(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, &m_jit);
+        done.link(&m_jit);
+    }
+    
+    addSlowPathGenerator(std::make_unique<CallArrayAllocatorWithVariableSizeSlowPathGenerator>(
+        slowCases, this, operationNewArrayWithSize, resultGPR,
+        structure,
+        shouldConvertLargeSizeToArrayStorage ? globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage) : structure,
+        sizeGPR));
+}
+
 #endif
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -229,7 +229,7 @@
     case PutGetterSetterById:
     case PutGetterByVal:
     case PutSetterByVal:
-    case CopyRest:
+    case CreateRest:
     case GetRestLength:
     case RegExpExec:
     case RegExpTest:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -972,8 +972,8 @@
         case CheckWatchdogTimer:
             compileCheckWatchdogTimer();
             break;
-        case CopyRest:
-            compileCopyRest();
+        case CreateRest:
+            compileCreateRest();
             break;
         case GetRestLength:
             compileGetRestLength();
@@ -3863,26 +3863,40 @@
         setJSValue(result);
     }
 
-    void compileCopyRest()
-    {            
-        LBasicBlock doCopyRest = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
+    void compileCreateRest()
+    {
+        if (m_graph.isWatchingHavingABadTimeWatchpoint(m_node)) {
+            LBasicBlock continuation = m_out.newBlock();
+            LValue arrayLength = lowInt32(m_node->child1());
+            LBasicBlock loopStart = m_out.newBlock();
+            bool shouldLargeArraySizeCreateArrayStorage = false;
+            LValue array = compileAllocateArrayWithSize(arrayLength, ArrayWithContiguous, shouldLargeArraySizeCreateArrayStorage);
 
-        LValue arrayLength = lowInt32(m_node->child2());
+            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->numberOfArgumentsToSkip()));
+            m_out.branch(m_out.equal(arrayLength, m_out.constInt32(0)),
+                unsure(continuation), unsure(loopStart));
 
-        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
+            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& 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->child1());
+        LValue argumentStart = getArgumentsStart();
         LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
-        vmCall(
-            Void,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()),
-            getArgumentsStart(), numberOfArgumentsToSkip, arrayLength);
-        m_out.jump(continuation);
-
-        m_out.appendTo(continuation, lastNext);
+        setJSValue(vmCall(
+            Int64, m_out.operation(operationCreateRest), m_callFrame, argumentStart, numberOfArgumentsToSkip, arrayLength));
     }
 
     void compileGetRestLength()
@@ -4028,81 +4042,99 @@
             m_out.constIntPtr(structure), m_out.constIntPtr(m_node->startConstant()),
             m_out.constIntPtr(m_node->numConstants())));
     }
-    
-    void compileNewArrayWithSize()
+
+    LValue compileAllocateArrayWithSize(LValue publicLength, IndexingType indexingType, bool shouldLargeArraySizeCreateArrayStorage = true)
     {
-        LValue publicLength = lowInt32(m_node->child1());
-        
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
-            m_node->indexingType());
-        
-        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
-            ASSERT(
-                hasUndecided(structure->indexingType())
-                || hasInt32(structure->indexingType())
-                || hasDouble(structure->indexingType())
-                || hasContiguous(structure->indexingType()));
+        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
+        ASSERT(
+            hasUndecided(structure->indexingType())
+            || hasInt32(structure->indexingType())
+            || hasDouble(structure->indexingType())
+            || hasContiguous(structure->indexingType()));
 
-            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();
-            
+        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) {
             m_out.branch(
                 m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)),
                 rarely(largeCase), usually(fastCase));
+            lastNext = m_out.appendTo(fastCase, largeCase);
+        }
 
-            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<JSArray>(structure, butterfly, failCase);
-            
-            m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
-            m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
+        
+        // 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<JSArray>(structure, butterfly, failCase);
+        
+        m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
+        m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
 
-            initializeArrayElements(m_node->indexingType(), vectorLength, butterfly);
-            
-            ValueFromBlock fastResult = m_out.anchor(object);
-            m_out.jump(continuation);
-            
+        initializeArrayElements(indexingType, vectorLength, butterfly);
+        
+        ValueFromBlock fastResult = m_out.anchor(object);
+        m_out.jump(continuation);
+        
+        LValue structureValue;
+        if (shouldLargeArraySizeCreateArrayStorage) {
+            LBasicBlock slowCase = m_out.newBlock();
+
             m_out.appendTo(largeCase, failCase);
             ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
                 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
             m_out.jump(slowCase);
-            
+
             m_out.appendTo(failCase, slowCase);
             ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
             m_out.jump(slowCase);
-            
+
             m_out.appendTo(slowCase, continuation);
-            LValue structureValue = m_out.phi(
+            structureValue = m_out.phi(
                 pointerType(), largeStructure, failStructure);
-            LValue slowResultValue = lazySlowPath(
-                [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
-                    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));
+        } else {
+            ASSERT(!lastNext);
+            lastNext = m_out.appendTo(failCase, continuation);
+            structureValue = m_out.constIntPtr(structure);
+        }
+
+        LValue slowResultValue = lazySlowPath(
+            [=] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
+                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->child1());
+        
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
+        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
+            m_node->indexingType());
+        
+        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
+            setJSValue(compileAllocateArrayWithSize(publicLength, m_node->indexingType()));
             return;
         }
         

Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (204438 => 204439)


--- trunk/Source/_javascript_Core/interpreter/CallFrame.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -211,6 +211,7 @@
         // arguments(0) will not fetch the 'this' value. To get/set 'this',
         // use thisValue() and setThisValue() below.
 
+        JSValue* addressOfArgumentsStart() const { return bitwise_cast<JSValue*>(this + argumentOffset(0)); }
         JSValue argument(size_t argument)
         {
             if (argument >= argumentCount())

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -231,7 +231,7 @@
         DEFINE_OP(op_create_scoped_arguments)
         DEFINE_OP(op_create_cloned_arguments)
         DEFINE_OP(op_argument_count)
-        DEFINE_OP(op_copy_rest)
+        DEFINE_OP(op_create_rest)
         DEFINE_OP(op_get_rest_length)
         DEFINE_OP(op_check_tdz)
         DEFINE_OP(op_assert)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (204438 => 204439)


--- trunk/Source/_javascript_Core/jit/JIT.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -493,7 +493,7 @@
         void emit_op_create_scoped_arguments(Instruction*);
         void emit_op_create_cloned_arguments(Instruction*);
         void emit_op_argument_count(Instruction*);
-        void emit_op_copy_rest(Instruction*);
+        void emit_op_create_rest(Instruction*);
         void emit_op_get_rest_length(Instruction*);
         void emit_op_check_tdz(Instruction*);
         void emit_op_assert(Instruction*);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1458,9 +1458,9 @@
     emitPutVirtualRegister(dst, result);
 }
 
-void JIT::emit_op_copy_rest(Instruction* currentInstruction)
+void JIT::emit_op_create_rest(Instruction* currentInstruction)
 {
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_copy_rest);
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_rest);
     slowPathCall.call();
 }
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (204438 => 204439)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -262,7 +262,7 @@
 typedef void (JIT_OPERATION *V_JITOperation_EVm)(ExecState*, VM*);
 typedef void (JIT_OPERATION *V_JITOperation_J)(EncodedJSValue);
 typedef void (JIT_OPERATION *V_JITOperation_Z)(int32_t);
-typedef void (JIT_OPERATION *V_JITOperation_ECRUiUi)(ExecState*, JSCell*, Register*, uint32_t, uint32_t);
+typedef JSCell* (JIT_OPERATION *C_JITOperation_ERUiUi)(ExecState*, Register*, uint32_t, uint32_t);
 typedef void (JIT_OPERATION *V_JITOperation_EOJIUi)(ExecState*, JSObject*, EncodedJSValue, UniquedStringImpl*, uint32_t);
 typedef char* (JIT_OPERATION *P_JITOperation_E)(ExecState*);
 typedef char* (JIT_OPERATION *P_JITOperation_EC)(ExecState*, JSCell*);

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (204438 => 204439)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2016-08-13 02:14:42 UTC (rev 204439)
@@ -1762,9 +1762,9 @@
     callOpcodeSlowPath(_slow_path_to_index_string)
     dispatch(3)
 
-_llint_op_copy_rest:
+_llint_op_create_rest:
     traceExecution()
-    callOpcodeSlowPath(_slow_path_copy_rest)
+    callOpcodeSlowPath(_slow_path_create_rest)
     dispatch(4)
 
 _llint_op_instanceof:

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (204438 => 204439)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2016-08-13 02:14:42 UTC (rev 204439)
@@ -848,20 +848,15 @@
     RETURN(resolvedScope);
 }
 
-SLOW_PATH_DECL(slow_path_copy_rest)
+SLOW_PATH_DECL(slow_path_create_rest)
 {
     BEGIN();
     unsigned arraySize = OP_C(2).jsValue().asUInt32();
-    if (!arraySize) {
-        ASSERT(!jsCast<JSArray*>(OP(1).jsValue())->length());
-        END();
-    }
-    JSArray* array = jsCast<JSArray*>(OP(1).jsValue());
-    ASSERT(arraySize == array->length());
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
     unsigned numParamsToSkip = pc[3].u.unsignedValue;
-    for (unsigned i = 0; i < arraySize; i++)
-        array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
-    END();
+    JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
+    RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
 }
 
 SLOW_PATH_DECL(slow_path_get_by_id_with_this)

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (204438 => 204439)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2016-08-13 02:02:04 UTC (rev 204438)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2016-08-13 02:14:42 UTC (rev 204439)
@@ -253,7 +253,7 @@
 SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
 SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
 SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
-SLOW_PATH_HIDDEN_DECL(slow_path_copy_rest);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_rest);
 SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_with_this);
 SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val_with_this);
 SLOW_PATH_HIDDEN_DECL(slow_path_put_by_id_with_this);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to