Unreviewed, rolling out r208208 and r208210.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Nov 2016 17:20:25 +0000 (17:20 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 1 Nov 2016 17:20:25 +0000 (17:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164276

This change caused 28 JSC test failures. (Requested by
ryanhaddad on #webkit).

Reverted changesets:

"We should be able to eliminate rest parameter allocations"
https://bugs.webkit.org/show_bug.cgi?id=163925
http://trac.webkit.org/changeset/208208

"Fix the EFL build."
http://trac.webkit.org/changeset/208210

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208224 268f45cc-cd09-0410-ab3c-d52691b4dbfc

29 files changed:
JSTests/ChangeLog
JSTests/microbenchmarks/rest-parameter-allocation-elimination.js [deleted file]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp
Source/JavaScriptCore/dfg/DFGArgumentsUtilities.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGPreciseLocalClobberize.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStructureRegistrationPhase.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOperations.cpp
Source/JavaScriptCore/jit/SetupVarargsFrame.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h

index d966130..2f02685 100644 (file)
@@ -1,3 +1,20 @@
+2016-11-01  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r208208 and r208210.
+        https://bugs.webkit.org/show_bug.cgi?id=164276
+
+        This change caused 28 JSC test failures. (Requested by
+        ryanhaddad on #webkit).
+
+        Reverted changesets:
+
+        "We should be able to eliminate rest parameter allocations"
+        https://bugs.webkit.org/show_bug.cgi?id=163925
+        http://trac.webkit.org/changeset/208208
+
+        "Fix the EFL build."
+        http://trac.webkit.org/changeset/208210
+
 2016-10-31  Filip Pizlo  <fpizlo@apple.com>
 
         JSC should support SharedArrayBuffer
diff --git a/JSTests/microbenchmarks/rest-parameter-allocation-elimination.js b/JSTests/microbenchmarks/rest-parameter-allocation-elimination.js
deleted file mode 100644 (file)
index d369e33..0000000
+++ /dev/null
@@ -1,613 +0,0 @@
-function assert(b, m = "") {
-    if (!b)
-        throw new Error("Bad assertion: " + m);
-}
-noInline(assert);
-
-const iterations = 20000;
-
-function test1() {
-    function bar(a, b, ...args) {
-        return args.length;
-    }
-    noInline(bar);
-    for (let i = 0; i < iterations; i++) {
-        assert(bar() === 0, bar());
-        assert(bar(i) === 0);
-        assert(bar(i, i) === 0);
-        assert(bar(i, i, i) === 1);
-        assert(bar(i, i, i, i, i) === 3);
-    }
-}
-
-function shallowEq(a, b) {
-    if (a.length !== b.length)
-        return false;
-    for (let i = 0; i < a.length; i++) {
-        if (a.length !== b.length)
-            return false;
-    }
-    return true;
-}
-noInline(shallowEq);
-
-function test2() {
-    function jaz(a, b, ...args) {
-        let result = [];
-        for (let i = 0; i < args.length; i++) {
-            result.push(args[i]);
-        }
-        return result;
-    }
-    noInline(jaz);
-
-    function jaz2(...args) {
-        function kaz(a, b, ...args) {
-            let result = [];
-            for (let i = 0; i < args.length; i++) {
-                result.push(args[i]);
-            }
-            return result;
-        }
-        return kaz.apply(null, args);
-    }
-    noInline(jaz2);
-
-    for (let f of [jaz, jaz2]) {
-        for (let i = 0; i < iterations; i++) {
-            let r = f();
-            assert(!r.length);
-
-            r = f(i);
-            assert(!r.length);
-
-            r = f(i, i)
-            assert(!r.length);
-
-            r = f(i, i, i)
-            assert(r.length === 1);
-            assert(shallowEq(r, [i]));
-
-            r = f(i, i, i)
-            assert(r.length === 1);
-            assert(shallowEq(r, [i]));
-
-            r = f(i, i, i, i*2, i*4)
-            assert(r.length === 3);
-            assert(shallowEq(r, [i, i*2, i*4]));
-        }
-    }
-}
-
-function test3() {
-    function foo(...args) {
-        return args;
-    }
-    function baz(a, b, c, ...args) {
-        return foo.apply(null, args);
-    }
-    function jaz(a, b, c, d, e, f) {
-        return baz(a, b, c, d, e, f);
-    }
-    noInline(jaz);
-
-    for (let i = 0; i < iterations; i++) {
-        let r = jaz();
-        assert(r.length === 3);
-        assert(shallowEq(r, [undefined, undefined, undefined]));
-
-        r = jaz(i, i);
-        assert(r.length === 3);
-        assert(shallowEq(r, [undefined, undefined, undefined]));
-
-        r = jaz(i, i, i);
-        assert(r.length === 3);
-        assert(shallowEq(r, [undefined, undefined, undefined]));
-
-        r = jaz(i, i, i, i);
-        assert(r.length === 3);
-        assert(shallowEq(r, [i, undefined, undefined]));
-
-        r = jaz(i, i, i, i, i, i);
-        assert(r.length === 3);
-        assert(shallowEq(r, [i, i, i]));
-    }
-}
-
-function test4() {
-    function baz(...args) {
-        return args;
-    }
-    function jaz(a, b, ...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    for (let i = 0; i < iterations; i++) {
-        let r = jaz();
-        assert(r.length === 0);
-
-        r = jaz(i);
-        assert(r.length === 0);
-
-        r = jaz(i, i);
-        assert(r.length === 0);
-
-        r = jaz(i, i, i);
-        assert(r.length === 1);
-        assert(shallowEq(r, [i]));
-
-        r = jaz(i, i, i, i*10);
-        assert(r.length === 2);
-        assert(shallowEq(r, [i, i*10]));
-
-        let o = {};
-        r = jaz(i, i, i, i*10, o);
-        assert(r.length === 3);
-        assert(shallowEq(r, [i, i*10, o]));
-    }
-}
-
-function test5() {
-    function baz(...args) {
-        return args;
-    }
-    noInline(baz);
-    function jaz(a, b, ...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    for (let i = 0; i < iterations; i++) {
-        let r = jaz();
-        assert(r.length === 0);
-
-        r = jaz(i);
-        assert(r.length === 0);
-
-        r = jaz(i, i);
-        assert(r.length === 0);
-
-        r = jaz(i, i, i);
-        assert(r.length === 1);
-        assert(shallowEq(r, [i]));
-
-        r = jaz(i, i, i, i*10);
-        assert(r.length === 2);
-        assert(shallowEq(r, [i, i*10]));
-
-        let o = {};
-        r = jaz(i, i, i, i*10, o);
-        assert(r.length === 3);
-        assert(shallowEq(r, [i, i*10, o]));
-    }
-}
-
-function test6() {
-    "use strict";
-    function baz(...args) {
-        return args;
-    }
-    noInline(baz);
-    function jaz(a, b, ...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    for (let i = 0; i < iterations; i++) {
-        let r = jaz();
-        assert(r.length === 0);
-
-        r = jaz(i);
-        assert(r.length === 0);
-
-        r = jaz(i, i);
-        assert(r.length === 0);
-
-        r = jaz(i, i, i);
-        assert(r.length === 1);
-        assert(shallowEq(r, [i]));
-
-        r = jaz(i, i, i, i*10);
-        assert(r.length === 2);
-        assert(shallowEq(r, [i, i*10]));
-
-        let o = {};
-        r = jaz(i, i, i, i*10, o);
-        assert(r.length === 3);
-        assert(shallowEq(r, [i, i*10, o]));
-    }
-}
-
-function test7() {
-    let shouldExit = false;
-    function baz(...args) {
-        if (shouldExit) {
-            OSRExit();
-            return [args.length, args[0], args[1], args[2]];
-        }
-        return [args.length, args[0], args[1], args[2]];
-    }
-    function jaz(a, b, ...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    function check(i) {
-        let [length, a, b, c] = jaz();
-        assert(length === 0);
-        assert(a === undefined);
-        assert(b === undefined);
-        assert(c === undefined);
-
-        [length, a, b, c] = jaz(i);
-        assert(length === 0);
-        assert(a === undefined);
-        assert(b === undefined);
-        assert(c === undefined);
-
-        [length, a, b, c] = jaz(i, i);
-        assert(length === 0);
-        assert(a === undefined);
-        assert(b === undefined);
-        assert(c === undefined);
-
-        [length, a, b, c] = jaz(i, i, i);
-        assert(length === 1);
-        assert(a === i, JSON.stringify(a));
-        assert(b === undefined);
-        assert(c === undefined);
-
-        [length, a, b, c] = jaz(i, i, i, i*10);
-        assert(length === 2);
-        assert(a === i);
-        assert(b === i*10);
-        assert(c === undefined);
-
-        let o = {oooo:20};
-        [length, a, b, c] = jaz(i, i, i, i*10, o);
-        assert(length === 3);
-        assert(a === i);
-        assert(b === i*10);
-        assert(c === o);
-    }
-
-    shouldExit = true;
-    for (let i = 0; i < 400; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    for (let i = 0; i < iterations; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    check(10);
-}
-
-function test8() {
-    let shouldExit = false;
-    function baz(...args) {
-        if (shouldExit) {
-            OSRExit();
-            return args;
-        }
-        return args;
-    }
-    function jaz(a, b, ...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    function check(i) {
-        let args = jaz();
-        assert(args.length === 0);
-
-        args = jaz(i);
-        assert(args.length === 0);
-
-        args = jaz(i, i);
-        assert(args.length === 0);
-
-        args = jaz(i, i, i);
-        assert(args.length === 1);
-        assert(args[0] === i);
-
-        args = jaz(i, i, i, i*10);
-        assert(args.length === 2);
-        assert(args[0] === i);
-        assert(args[1] === i*10);
-
-        let o = {oooo:20};
-        args = jaz(i, i, i, i*10, o);
-        assert(args.length === 3);
-        assert(args[0] === i);
-        assert(args[1] === i*10);
-        assert(args[2] === o);
-    }
-
-    shouldExit = true;
-    for (let i = 0; i < 400; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    for (let i = 0; i < iterations; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    check(10);
-}
-
-function test9() {
-    let shouldExit = false;
-    function baz(a, ...args) {
-        if (shouldExit) {
-            OSRExit();
-            return [args.length, args[0], args[1]];
-        }
-        return [args.length, args[0], args[1]];
-    }
-    function jaz(...args) {
-        return baz.apply(null, args);
-    }
-    noInline(jaz);
-
-    function check(i) {
-        let [length, a, b] = jaz();
-        assert(length === 0);
-
-        [length, a, b] = jaz(i);
-        assert(length === 0);
-        assert(a === undefined);
-        assert(b === undefined);
-
-        [length, a, b] = jaz(i, i + 1);
-        assert(length === 1);
-        assert(a === i+1);
-        assert(b === undefined);
-
-        [length, a, b] = jaz(i, i+1, i+2);
-        assert(length === 2);
-        assert(a === i+1);
-        assert(b === i+2);
-
-        let o = {oooo:20};
-        [length, a, b] = jaz(i, i+1, o);
-        assert(length === 2);
-        assert(a === i+1);
-        assert(b === o);
-    }
-
-    shouldExit = true;
-    for (let i = 0; i < 400; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    for (let i = 0; i < iterations; i++) {
-        check(i);
-    }
-
-    shouldExit = false;
-    check(10);
-}
-
-function test10() {
-    function baz(a, b, c, ...args) {
-        return [args.length, args[0], args[1], args[2], args[3]];
-    }
-    function jaz(a, b, c, d, e, f) {
-        return baz(a, b, c, d, e, f);
-    }
-    noInline(jaz);
-
-    for (let i = 0; i < iterations; i++) {
-        let [length, a, b, c, d] = jaz(1, 2, 3, 4, 5, 6);
-        assert(length === 3);
-        assert(a === 4);
-        assert(b === 5);
-        assert(c === 6);
-        assert(d === undefined);
-    }
-}
-
-function test11() {
-    function bar(...args) {
-        return args;
-    }
-    noInline(bar);
-
-    function foo(a, b, c, d, ...args) {
-        return bar.apply(null, args);
-    }
-    noInline(foo);
-
-    function makeArguments(args) {
-        return [1,2,3,4, ...args];
-    }
-    for (let i = 0; i < iterations; i++) {
-        function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); }
-        let a = [{}, 25, 50];
-        test();
-
-        a = [];
-        test();
-
-        a = [{foo: 20}];
-        test();
-
-        a = [10, 20, 30, 40, 50, 60, 70, 80];
-        test();
-    }
-}
-
-function test12() {
-    "use strict";
-    let thisValue = {};
-    function getThisValue() { return thisValue; }
-    noInline(getThisValue);
-
-    function bar(...args) {
-        assert(this === thisValue);
-        return args;
-    }
-    noInline(bar);
-
-    function foo(a, b, c, d, ...args) {
-        return bar.apply(getThisValue(), args);
-    }
-    noInline(foo);
-
-    function makeArguments(args) {
-        return [1,2,3,4, ...args];
-    }
-    for (let i = 0; i < iterations; i++) {
-        function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); }
-        let a = [{}, 25, 50];
-        test();
-
-        a = [];
-        test();
-
-        a = [{foo: 20}];
-        test();
-
-        a = [10, 20, 30, 40, 50, 60, 70, 80];
-        test();
-    }
-}
-
-function test13() {
-    "use strict";
-    function bar(...args) {
-        return args;
-    }
-    noInline(bar);
-
-    function top(a, b, c, d, ...args) {
-        return bar.apply(null, args);
-    }
-    function foo(...args) {
-        let r = top.apply(null, args);
-        return r;
-    }
-    noInline(foo);
-
-    function makeArguments(args) {
-        return [1,2,3,4, ...args];
-    }
-    for (let i = 0; i < iterations; i++) {
-        function test() { assert(shallowEq(a, foo.apply(null, makeArguments(a)))); }
-        let a = [{}, 25, 50];
-        test();
-
-        a = [];
-        test();
-
-        a = [10, 20, 30, 40, 50, 60, 70, 80];
-        test();
-    }
-}
-
-function test14() {
-    "use strict";
-    function bar(...args) {
-        return args;
-    }
-    noInline(bar);
-
-    function top(a, b, c, d, ...args) {
-        return bar.apply(null, args);
-    }
-    function foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) {
-        return top(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
-    }
-    noInline(foo);
-
-    function makeArguments(args) {
-        let r = [1,2,3,4, ...args];
-        while (r.length < foo.length)
-            r.push(undefined);
-        return r;
-    }
-    for (let i = 0; i < iterations; i++) {
-        function test()
-        {
-            let args = makeArguments(a);
-            assert(shallowEq(args.slice(4), foo.apply(null, args)));
-        }
-
-        let a = [{}, 25, 50];
-        test();
-
-        a = [];
-        test();
-
-        a = [10, 20, 30, 40, 50, 60, 70, 80];
-        test();
-    }
-}
-
-function test15() {
-    "use strict";
-    function bar(...args) {
-        return args;
-    }
-    noInline(bar);
-
-    function top(a, b, c, d, ...args) {
-        return bar.apply(null, args);
-    }
-    function foo(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) {
-        let r = top(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17);
-        return r;
-    }
-    noInline(foo);
-
-    function makeArguments(args) {
-        let r = [1,2,3,4, ...args];
-        while (r.length < foo.length)
-            r.push(undefined);
-        return r;
-    }
-    for (let i = 0; i < iterations; i++) {
-        function test()
-        {
-            let args = makeArguments(a);
-            assert(shallowEq(args.slice(4), foo.apply(null, args)));
-        }
-
-        let a = [{}, 25, 50];
-        test();
-
-        a = [];
-        test();
-
-        a = [10, 20, 30, 40, 50, 60, 70, 80];
-        test();
-    }
-}
-
-let start = Date.now();
-test1();
-test2();
-test3();
-test4();
-test5();
-test6();
-test7();
-test8();
-test9();
-test10();
-test11();
-test12();
-test13();
-test14();
-test15();
-const verbose = false;
-if (verbose)
-    print(Date.now() - start);
-
index 491bc9e..772144a 100644 (file)
@@ -1,3 +1,20 @@
+2016-11-01  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r208208 and r208210.
+        https://bugs.webkit.org/show_bug.cgi?id=164276
+
+        This change caused 28 JSC test failures. (Requested by
+        ryanhaddad on #webkit).
+
+        Reverted changesets:
+
+        "We should be able to eliminate rest parameter allocations"
+        https://bugs.webkit.org/show_bug.cgi?id=163925
+        http://trac.webkit.org/changeset/208208
+
+        "Fix the EFL build."
+        http://trac.webkit.org/changeset/208210
+
 2016-11-01  Ryosuke Niwa  <rniwa@webkit.org>
 
         Web Inspector: Add the support for custom elements
index 1067b22..586ff8c 100644 (file)
@@ -2360,13 +2360,6 @@ void CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             break;
         }
 
-        case op_create_rest: {
-            int numberOfArgumentsToSkip = instructions[i + 3].u.operand;
-            ASSERT_UNUSED(numberOfArgumentsToSkip, numberOfArgumentsToSkip >= 0);
-            ASSERT_WITH_MESSAGE(numberOfArgumentsToSkip == numParameters() - 1, "We assume that this is true when rematerializing the rest parameter during OSR exit in the FTL JIT.");
-            break;
-        }
-
         default:
             break;
         }
index 43b51a1..1d1f308 100644 (file)
@@ -1665,17 +1665,16 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
             // paths as unreachable, or to return undefined. We could implement that eventually.
             
-            unsigned argumentIndex = index.asUInt32() + node->numberOfArgumentsToSkip();
             if (inlineCallFrame) {
-                if (argumentIndex < inlineCallFrame->arguments.size() - 1) {
+                if (index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
                     forNode(node) = m_state.variables().operand(
-                        virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset);
+                        virtualRegisterForArgument(index.asInt32() + 1) + inlineCallFrame->stackOffset);
                     m_state.setFoundConstants(true);
                     break;
                 }
             } else {
-                if (argumentIndex < m_state.variables().numberOfArguments() - 1) {
-                    forNode(node) = m_state.variables().argument(argumentIndex + 1);
+                if (index.asUInt32() < m_state.variables().numberOfArguments() - 1) {
+                    forNode(node) = m_state.variables().argument(index.asInt32() + 1);
                     m_state.setFoundConstants(true);
                     break;
                 }
@@ -1686,7 +1685,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             // We have a bound on the types even though it's random access. Take advantage of this.
             
             AbstractValue result;
-            for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->arguments.size(); ++i) {
+            for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;) {
                 result.merge(
                     m_state.variables().operand(
                         virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
@@ -1951,7 +1950,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case PhantomCreateActivation:
     case PhantomDirectArguments:
     case PhantomClonedArguments:
-    case PhantomCreateRest:
     case BottomValue:
         m_state.setDidClobber(true); // Prevent constant folding.
         // This claims to return bottom.
@@ -2867,15 +2865,9 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
 
     case CreateRest:
-        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
-            // This means we're already having a bad time.
+        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;
-        }
-        forNode(node).set(
-            m_graph,
-            m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
+        forNode(node).setType(m_graph, SpecArray);
         break;
             
     case Check: {
index 97879bb..bdf2741 100644 (file)
@@ -97,17 +97,6 @@ private:
                 case CreateClonedArguments:
                     m_candidates.add(node);
                     break;
-
-                case CreateRest:
-                    if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
-                        // If we're watching the HavingABadTime watchpoint it means that we will be invalidated
-                        // when it fires (it may or may not have actually fired yet). We don't try to eliminate
-                        // this allocation when we're not watching the watchpoint because it could entail calling
-                        // indexed accessors (and probably more crazy things) on out of bound accesses to the
-                        // rest parameter. It's also much easier to reason about this way.
-                        m_candidates.add(node);
-                    }
-                    break;
                     
                 case CreateScopedArguments:
                     // FIXME: We could handle this if it wasn't for the fact that scoped arguments are
@@ -145,7 +134,7 @@ private:
                 break;
             
             case Array::Contiguous: {
-                if (edge->op() != CreateClonedArguments && edge->op() != CreateRest) {
+                if (edge->op() != CreateClonedArguments) {
                     escape(edge, source);
                     return;
                 }
@@ -233,32 +222,6 @@ private:
                     escapeBasedOnArrayMode(node->arrayMode(), node->child1(), node);
                     break;
 
-                case CheckStructure: {
-                    if (!m_candidates.contains(node->child1().node()))
-                        break;
-
-                    Structure* structure = nullptr;
-                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->child1().node()->origin.semantic);
-                    switch (node->child1().node()->op()) {
-                    case CreateDirectArguments:
-                        structure = globalObject->directArgumentsStructure();
-                        break;
-                    case CreateClonedArguments:
-                        structure = globalObject->clonedArgumentsStructure();
-                        break;
-                    case CreateRest:
-                        ASSERT(m_graph.isWatchingHavingABadTimeWatchpoint(node));
-                        structure = globalObject->restParameterStructure();
-                        break;
-                    default:
-                        RELEASE_ASSERT_NOT_REACHED();
-                    }
-                    ASSERT(structure);
-
-                    if (!node->structureSet().contains(structure))
-                        escape(node->child1(), node);
-                    break;
-                }
                     
                 // FIXME: We should be able to handle GetById/GetByOffset on callee.
                 // https://bugs.webkit.org/show_bug.cgi?id=143075
@@ -432,7 +395,7 @@ private:
     {
         InsertionSet insertionSet(m_graph);
         
-        for (BasicBlock* block : m_graph.blocksInPreOrder()) {
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                 Node* node = block->at(nodeIndex);
                 
@@ -440,16 +403,6 @@ private:
                     return emitCodeToGetArgumentsArrayLength(
                         insertionSet, candidate, nodeIndex, node->origin);
                 };
-
-                auto isEliminatedAllocation = [&] (Node* candidate) -> bool {
-                    if (!m_candidates.contains(candidate))
-                        return false;
-                    // We traverse in such a way that we are guaranteed to see a def before a use.
-                    // Therefore, we should have already transformed the allocation before the use
-                    // of an allocation.
-                    ASSERT(candidate->op() == PhantomCreateRest || candidate->op() == PhantomDirectArguments || candidate->op() == PhantomClonedArguments);
-                    return true;
-                };
         
                 switch (node->op()) {
                 case CreateDirectArguments:
@@ -458,16 +411,6 @@ private:
                     
                     node->setOpAndDefaultFlags(PhantomDirectArguments);
                     break;
-
-                case CreateRest:
-                    if (!m_candidates.contains(node))
-                        break;
-
-                    node->setOpAndDefaultFlags(PhantomCreateRest);
-                    // We don't need this parameter for OSR exit, we can find out all the information
-                    // we need via the static parameter count and the dynamic argument count.
-                    node->child1() = Edge(); 
-                    break;
                     
                 case CreateClonedArguments:
                     if (!m_candidates.contains(node))
@@ -478,11 +421,13 @@ private:
                     
                 case GetFromArguments: {
                     Node* candidate = node->child1().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
                     
                     DFG_ASSERT(
-                        m_graph, node, node->child1()->op() == PhantomDirectArguments);
+                        m_graph, node,
+                        node->child1()->op() == CreateDirectArguments
+                        || node->child1()->op() == PhantomDirectArguments);
                     VirtualRegister reg =
                         virtualRegisterForArgument(node->capturedArgumentsOffset().offset() + 1) +
                         node->origin.semantic.stackOffset();
@@ -493,10 +438,10 @@ private:
 
                 case GetByOffset: {
                     Node* candidate = node->child2().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
 
-                    if (node->child2()->op() != PhantomClonedArguments)
+                    if (node->child2()->op() != PhantomClonedArguments && node->child2()->op() != CreateClonedArguments)
                         break;
 
                     ASSERT(node->storageAccessData().offset == clonedArgumentsLengthPropertyOffset);
@@ -509,7 +454,7 @@ private:
                     
                 case GetArrayLength: {
                     Node* candidate = node->child1().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
                     
                     // Meh, this is kind of hackish - we use an Identity so that we can reuse the
@@ -527,18 +472,13 @@ private:
                     // https://bugs.webkit.org/show_bug.cgi?id=143076
                     
                     Node* candidate = node->child1().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
-
-                    unsigned numberOfArgumentsToSkip = 0;
-                    if (candidate->op() == PhantomCreateRest)
-                        numberOfArgumentsToSkip = candidate->numberOfArgumentsToSkip();
                     
                     Node* result = nullptr;
                     if (node->child2()->isInt32Constant()) {
                         unsigned index = node->child2()->asUInt32();
                         InlineCallFrame* inlineCallFrame = candidate->origin.semantic.inlineCallFrame;
-                        index += numberOfArgumentsToSkip;
                         
                         bool safeToGetStack;
                         if (inlineCallFrame)
@@ -572,10 +512,10 @@ private:
                         else
                             op = GetMyArgumentByValOutOfBounds;
                         result = insertionSet.insertNode(
-                            nodeIndex, node->prediction(), op, node->origin, OpInfo(numberOfArgumentsToSkip),
+                            nodeIndex, node->prediction(), op, node->origin,
                             node->child1(), node->child2());
                     }
-
+                    
                     // Need to do this because we may have a data format conversion here.
                     node->convertToIdentityOn(result);
                     break;
@@ -583,95 +523,83 @@ private:
                     
                 case LoadVarargs: {
                     Node* candidate = node->child1().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
                     
                     LoadVarargsData* varargsData = node->loadVarargsData();
-                    unsigned numberOfArgumentsToSkip = 0;
-                    if (candidate->op() == PhantomCreateRest)
-                        numberOfArgumentsToSkip = candidate->numberOfArgumentsToSkip();
-                    varargsData->offset += numberOfArgumentsToSkip;
-
                     InlineCallFrame* inlineCallFrame = candidate->origin.semantic.inlineCallFrame;
-
                     if (inlineCallFrame
-                        && !inlineCallFrame->isVarargs()) {
-
-                        unsigned argumentCountIncludingThis = inlineCallFrame->arguments.size();
-                        if (argumentCountIncludingThis > varargsData->offset)
-                            argumentCountIncludingThis -= varargsData->offset;
-                        else
-                            argumentCountIncludingThis = 1;
-                        RELEASE_ASSERT(argumentCountIncludingThis >= 1);
-
-                        if (argumentCountIncludingThis <= varargsData->limit) {
-                            // LoadVarargs can exit, so it better be exitOK.
-                            DFG_ASSERT(m_graph, node, node->origin.exitOK);
-                            bool canExit = true;
+                        && !inlineCallFrame->isVarargs()
+                        && inlineCallFrame->arguments.size() - varargsData->offset <= varargsData->limit) {
+                        
+                        // LoadVarargs can exit, so it better be exitOK.
+                        DFG_ASSERT(m_graph, node, node->origin.exitOK);
+                        bool canExit = true;
+                        
+                        Node* argumentCount = insertionSet.insertConstant(
+                            nodeIndex, node->origin.withExitOK(canExit),
+                            jsNumber(inlineCallFrame->arguments.size() - varargsData->offset));
+                        insertionSet.insertNode(
+                            nodeIndex, SpecNone, MovHint, node->origin.takeValidExit(canExit),
+                            OpInfo(varargsData->count.offset()), Edge(argumentCount));
+                        insertionSet.insertNode(
+                            nodeIndex, SpecNone, PutStack, node->origin.withExitOK(canExit),
+                            OpInfo(m_graph.m_stackAccessData.add(varargsData->count, FlushedInt32)),
+                            Edge(argumentCount, KnownInt32Use));
+                        
+                        DFG_ASSERT(m_graph, node, varargsData->limit - 1 >= varargsData->mandatoryMinimum);
+                        // Define our limit to not include "this", since that's a bit easier to reason about.
+                        unsigned limit = varargsData->limit - 1;
+                        Node* undefined = nullptr;
+                        for (unsigned storeIndex = 0; storeIndex < limit; ++storeIndex) {
+                            // First determine if we have an element we can load, and load it if
+                            // possible.
                             
-                            Node* argumentCountIncludingThisNode = insertionSet.insertConstant(
-                                nodeIndex, node->origin.withExitOK(canExit),
-                                jsNumber(argumentCountIncludingThis));
-                            insertionSet.insertNode(
-                                nodeIndex, SpecNone, MovHint, node->origin.takeValidExit(canExit),
-                                OpInfo(varargsData->count.offset()), Edge(argumentCountIncludingThisNode));
-                            insertionSet.insertNode(
-                                nodeIndex, SpecNone, PutStack, node->origin.withExitOK(canExit),
-                                OpInfo(m_graph.m_stackAccessData.add(varargsData->count, FlushedInt32)),
-                                Edge(argumentCountIncludingThisNode, KnownInt32Use));
+                            unsigned loadIndex = storeIndex + varargsData->offset;
                             
-                            DFG_ASSERT(m_graph, node, varargsData->limit - 1 >= varargsData->mandatoryMinimum);
-                            // Define our limit to exclude "this", since that's a bit easier to reason about.
-                            unsigned limit = varargsData->limit - 1;
-                            Node* undefined = nullptr;
-                            for (unsigned storeIndex = 0; storeIndex < limit; ++storeIndex) {
-                                // First determine if we have an element we can load, and load it if
-                                // possible.
+                            Node* value;
+                            if (loadIndex + 1 < inlineCallFrame->arguments.size()) {
+                                VirtualRegister reg =
+                                    virtualRegisterForArgument(loadIndex + 1) +
+                                    inlineCallFrame->stackOffset;
+                                StackAccessData* data = m_graph.m_stackAccessData.add(
+                                    reg, FlushedJSValue);
                                 
-                                unsigned loadIndex = storeIndex + varargsData->offset;
+                                value = insertionSet.insertNode(
+                                    nodeIndex, SpecNone, GetStack, node->origin.withExitOK(canExit),
+                                    OpInfo(data));
+                            } else {
+                                // FIXME: We shouldn't have to store anything if
+                                // storeIndex >= varargsData->mandatoryMinimum, but we will still
+                                // have GetStacks in that range. So if we don't do the stores, we'll
+                                // have degenerate IR: we'll have GetStacks of something that didn't
+                                // have PutStacks.
+                                // https://bugs.webkit.org/show_bug.cgi?id=147434
                                 
-                                Node* value;
-                                if (loadIndex + 1 < inlineCallFrame->arguments.size()) {
-                                    VirtualRegister reg = virtualRegisterForArgument(loadIndex + 1) + inlineCallFrame->stackOffset;
-                                    StackAccessData* data = m_graph.m_stackAccessData.add(
-                                        reg, FlushedJSValue);
-                                    
-                                    value = insertionSet.insertNode(
-                                        nodeIndex, SpecNone, GetStack, node->origin.withExitOK(canExit),
-                                        OpInfo(data));
-                                } else {
-                                    // FIXME: We shouldn't have to store anything if
-                                    // storeIndex >= varargsData->mandatoryMinimum, but we will still
-                                    // have GetStacks in that range. So if we don't do the stores, we'll
-                                    // have degenerate IR: we'll have GetStacks of something that didn't
-                                    // have PutStacks.
-                                    // https://bugs.webkit.org/show_bug.cgi?id=147434
-                                    
-                                    if (!undefined) {
-                                        undefined = insertionSet.insertConstant(
-                                            nodeIndex, node->origin.withExitOK(canExit), jsUndefined());
-                                    }
-                                    value = undefined;
+                                if (!undefined) {
+                                    undefined = insertionSet.insertConstant(
+                                        nodeIndex, node->origin.withExitOK(canExit), jsUndefined());
                                 }
-                                
-                                // Now that we have a value, store it.
-                                
-                                VirtualRegister reg = varargsData->start + storeIndex;
-                                StackAccessData* data =
-                                    m_graph.m_stackAccessData.add(reg, FlushedJSValue);
-                                
-                                insertionSet.insertNode(
-                                    nodeIndex, SpecNone, MovHint, node->origin.takeValidExit(canExit),
-                                    OpInfo(reg.offset()), Edge(value));
-                                insertionSet.insertNode(
-                                    nodeIndex, SpecNone, PutStack, node->origin.withExitOK(canExit),
-                                    OpInfo(data), Edge(value));
+                                value = undefined;
                             }
                             
-                            node->remove();
-                            node->origin.exitOK = canExit;
-                            break;
+                            // Now that we have a value, store it.
+                            
+                            VirtualRegister reg = varargsData->start + storeIndex;
+                            StackAccessData* data =
+                                m_graph.m_stackAccessData.add(reg, FlushedJSValue);
+                            
+                            insertionSet.insertNode(
+                                nodeIndex, SpecNone, MovHint, node->origin.takeValidExit(canExit),
+                                OpInfo(reg.offset()), Edge(value));
+                            insertionSet.insertNode(
+                                nodeIndex, SpecNone, PutStack, node->origin.withExitOK(canExit),
+                                OpInfo(data), Edge(value));
                         }
+                        
+                        node->remove();
+                        node->origin.exitOK = canExit;
+                        break;
                     }
                     
                     node->setOpAndDefaultFlags(ForwardVarargs);
@@ -683,15 +611,10 @@ private:
                 case TailCallVarargs:
                 case TailCallVarargsInlinedCaller: {
                     Node* candidate = node->child3().node();
-                    if (!isEliminatedAllocation(candidate))
+                    if (!m_candidates.contains(candidate))
                         break;
                     
-                    unsigned numberOfArgumentsToSkip = 0;
-                    if (candidate->op() == PhantomCreateRest)
-                        numberOfArgumentsToSkip = candidate->numberOfArgumentsToSkip();
                     CallVarargsData* varargsData = node->callVarargsData();
-                    varargsData->firstVarArgOffset += numberOfArgumentsToSkip;
-
                     InlineCallFrame* inlineCallFrame = candidate->origin.semantic.inlineCallFrame;
                     if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
                         Vector<Node*> arguments;
@@ -754,18 +677,11 @@ private:
                     
                 case CheckArray:
                 case GetButterfly: {
-                    if (!isEliminatedAllocation(node->child1().node()))
+                    if (!m_candidates.contains(node->child1().node()))
                         break;
                     node->remove();
                     break;
                 }
-
-                case CheckStructure:
-                    if (!isEliminatedAllocation(node->child1().node()))
-                        break;
-                    node->child1() = Edge(); // Remove the cell check since we've proven it's not needed and FTL lowering might botch this.
-                    node->remove();
-                    break;
                     
                 default:
                     break;
index 061a284..022e3b0 100644 (file)
@@ -64,23 +64,14 @@ Node* emitCodeToGetArgumentsArrayLength(
     DFG_ASSERT(
         graph, arguments,
         arguments->op() == CreateDirectArguments || arguments->op() == CreateScopedArguments
-        || arguments->op() == CreateClonedArguments || arguments->op() == CreateRest
-        || arguments->op() == PhantomDirectArguments || arguments->op() == PhantomClonedArguments || arguments->op() == PhantomCreateRest);
+        || arguments->op() == CreateClonedArguments || arguments->op() == PhantomDirectArguments
+        || arguments->op() == PhantomClonedArguments);
     
     InlineCallFrame* inlineCallFrame = arguments->origin.semantic.inlineCallFrame;
-
-    unsigned numberOfArgumentsToSkip = 0;
-    if (arguments->op() == CreateRest || arguments->op() == PhantomCreateRest)
-        numberOfArgumentsToSkip = arguments->numberOfArgumentsToSkip();
     
     if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
-        unsigned argumentsSize = inlineCallFrame->arguments.size() - 1;
-        if (argumentsSize >= numberOfArgumentsToSkip)
-            argumentsSize -= numberOfArgumentsToSkip;
-        else
-            argumentsSize = 0;
         return insertionSet.insertConstant(
-            nodeIndex, origin, jsNumber(argumentsSize));
+            nodeIndex, origin, jsNumber(inlineCallFrame->arguments.size() - 1));
     }
     
     Node* argumentCount;
@@ -93,23 +84,12 @@ Node* emitCodeToGetArgumentsArrayLength(
             nodeIndex, SpecInt32Only, GetStack, origin,
             OpInfo(graph.m_stackAccessData.add(argumentCountRegister, FlushedInt32)));
     }
-
-    Node* result = insertionSet.insertNode(
+    
+    return insertionSet.insertNode(
         nodeIndex, SpecInt32Only, ArithSub, origin, OpInfo(Arith::Unchecked),
         Edge(argumentCount, Int32Use),
         insertionSet.insertConstantForUse(
-            nodeIndex, origin, jsNumber(1 + numberOfArgumentsToSkip), Int32Use));
-
-    if (numberOfArgumentsToSkip) {
-        // The above subtraction may produce a negative number if this number is non-zero. We correct that here.
-        result = insertionSet.insertNode(
-            nodeIndex, SpecInt32Only, ArithMax, origin, 
-            Edge(result, Int32Use), 
-            insertionSet.insertConstantForUse(nodeIndex, origin, jsNumber(0), Int32Use));
-        result->setResult(NodeResultInt32);
-    }
-
-    return result;
+            nodeIndex, origin, jsNumber(1), Int32Use));
 }
 
 } } // namespace JSC::DFG
index b621ef0..5a3294d 100644 (file)
@@ -477,12 +477,6 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
         write(HeapObjectCount);
         return;
 
-    case PhantomCreateRest:
-        // Even though it's phantom, it still has the property that one can't be replaced with another.
-        read(HeapObjectCount);
-        write(HeapObjectCount);
-        return;
-
     case CallObjectConstructor:
     case ToThis:
     case CreateThis:
index 321dcf9..38b6402 100644 (file)
@@ -314,11 +314,9 @@ private:
                 
             case GetMyArgumentByVal:
             case GetMyArgumentByValOutOfBounds: {
-                JSValue indexValue = m_state.forNode(node->child2()).value();
-                if (!indexValue || !indexValue.isInt32())
+                JSValue index = m_state.forNode(node->child2()).value();
+                if (!index || !index.isInt32())
                     break;
-
-                unsigned index = indexValue.asUInt32() + node->numberOfArgumentsToSkip();
                 
                 Node* arguments = node->child1().node();
                 InlineCallFrame* inlineCallFrame = arguments->origin.semantic.inlineCallFrame;
@@ -337,10 +335,10 @@ private:
                 // GetMyArgumentByVal in such statically-out-of-bounds accesses; we just lose CFA unless
                 // GCSE removes the access entirely.
                 if (inlineCallFrame) {
-                    if (index >= inlineCallFrame->arguments.size() - 1)
+                    if (index.asUInt32() >= inlineCallFrame->arguments.size() - 1)
                         break;
                 } else {
-                    if (index >= m_state.variables().numberOfArguments() - 1)
+                    if (index.asUInt32() >= m_state.variables().numberOfArguments() - 1)
                         break;
                 }
                 
@@ -351,14 +349,15 @@ private:
                     data = m_graph.m_stackAccessData.add(
                         VirtualRegister(
                             inlineCallFrame->stackOffset +
-                            CallFrame::argumentOffset(index)),
+                            CallFrame::argumentOffset(index.asInt32())),
                         FlushedJSValue);
                 } else {
                     data = m_graph.m_stackAccessData.add(
-                        virtualRegisterForArgument(index + 1), FlushedJSValue);
+                        virtualRegisterForArgument(index.asInt32() + 1), FlushedJSValue);
                 }
                 
-                if (inlineCallFrame && !inlineCallFrame->isVarargs() && index < inlineCallFrame->arguments.size() - 1) {
+                if (inlineCallFrame && !inlineCallFrame->isVarargs()
+                    && index.asUInt32() < inlineCallFrame->arguments.size() - 1) {
                     node->convertToGetStack(data);
                     eliminated = true;
                     break;
index 97cd848..cb48e5c 100644 (file)
@@ -246,7 +246,6 @@ bool doesGC(Graph& graph, Node* node)
     case PhantomNewGeneratorFunction:
     case PhantomCreateActivation:
     case PhantomDirectArguments:
-    case PhantomCreateRest:
     case PhantomClonedArguments:
     case GetMyArgumentByVal:
     case GetMyArgumentByValOutOfBounds:
index 1d4e907..78fe0e9 100644 (file)
@@ -1399,7 +1399,6 @@ private:
         case PhantomNewGeneratorFunction:
         case PhantomCreateActivation:
         case PhantomDirectArguments:
-        case PhantomCreateRest:
         case PhantomClonedArguments:
         case GetMyArgumentByVal:
         case GetMyArgumentByValOutOfBounds:
index 1d1bd4c..a67b293 100644 (file)
@@ -458,7 +458,6 @@ public:
             
         case PhantomDirectArguments:
         case PhantomClonedArguments:
-        case PhantomCreateRest:
             // These pretend to be the empty value constant for the benefit of the DFG backend, which
             // otherwise wouldn't take kindly to a node that doesn't compute a value.
             return true;
@@ -472,7 +471,7 @@ public:
     {
         ASSERT(hasConstant());
         
-        if (op() == PhantomDirectArguments || op() == PhantomClonedArguments || op() == PhantomCreateRest) {
+        if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
             // These pretend to be the empty value constant for the benefit of the DFG backend, which
             // otherwise wouldn't take kindly to a node that doesn't compute a value.
             return FrozenValue::emptySingleton();
@@ -1746,7 +1745,6 @@ public:
         switch (op()) {
         case PhantomNewObject:
         case PhantomDirectArguments:
-        case PhantomCreateRest:
         case PhantomClonedArguments:
         case PhantomNewFunction:
         case PhantomNewGeneratorFunction:
@@ -2390,7 +2388,7 @@ public:
 
     unsigned numberOfArgumentsToSkip()
     {
-        ASSERT(op() == CreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
+        ASSERT(op() == CreateRest || op() == GetRestLength);
         return m_opInfo.as<unsigned>();
     }
 
index d975b76..cd24a44 100644 (file)
@@ -342,7 +342,6 @@ namespace JSC { namespace DFG {
     \
     macro(CreateDirectArguments, NodeResultJS) \
     macro(PhantomDirectArguments, NodeResultJS | NodeMustGenerate) \
-    macro(PhantomCreateRest, NodeResultJS | NodeMustGenerate) \
     macro(CreateScopedArguments, NodeResultJS) \
     macro(CreateClonedArguments, NodeResultJS) \
     macro(PhantomClonedArguments, NodeResultJS | NodeMustGenerate) \
index c188775..eb217e6 100644 (file)
@@ -165,7 +165,6 @@ void LocalOSRAvailabilityCalculator::executeNode(Node* node)
         break;
     }
         
-    case PhantomCreateRest:
     case PhantomDirectArguments:
     case PhantomClonedArguments: {
         InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
@@ -174,10 +173,6 @@ void LocalOSRAvailabilityCalculator::executeNode(Node* node)
             // given that we can read them from the stack.
             break;
         }
-
-        unsigned numberOfArgumentsToSkip = 0;
-        if (node->op() == PhantomCreateRest)
-            numberOfArgumentsToSkip = node->numberOfArgumentsToSkip();
         
         if (inlineCallFrame->isVarargs()) {
             // Record how to read each argument and the argument count.
@@ -193,7 +188,7 @@ void LocalOSRAvailabilityCalculator::executeNode(Node* node)
             m_availability.m_heap.set(PromotedHeapLocation(ArgumentsCalleePLoc, node), callee);
         }
         
-        for (unsigned i = numberOfArgumentsToSkip; i < inlineCallFrame->arguments.size() - 1; ++i) {
+        for (unsigned i = 0; i < inlineCallFrame->arguments.size() - 1; ++i) {
             Availability argument = m_availability.m_locals.operand(
                 inlineCallFrame->stackOffset + CallFrame::argumentOffset(i));
             
index e204d3e..fdf689d 100644 (file)
@@ -1358,7 +1358,7 @@ JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentSta
     NativeCallFrameTracer tracer(vm, exec);
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    Structure* structure = globalObject->restParameterStructure();
+    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);
index 6fbd7bd..70eb75f 100644 (file)
@@ -120,24 +120,15 @@ private:
                 inlineCallFrame = m_node->argumentsChild()->origin.semantic.inlineCallFrame;
             else
                 inlineCallFrame = m_node->origin.semantic.inlineCallFrame;
-
-            unsigned numberOfArgumentsToSkip = 0;
-            if (m_node->op() == GetMyArgumentByVal || m_node->op() == GetMyArgumentByValOutOfBounds) {
-                // The value of numberOfArgumentsToSkip guarantees that GetMyArgumentByVal* will never
-                // read any arguments below the number of arguments to skip. For example, if numberOfArgumentsToSkip is 2,
-                // we will never read argument 0 or argument 1.
-                numberOfArgumentsToSkip = m_node->numberOfArgumentsToSkip();
-            }
-
             if (!inlineCallFrame) {
                 // Read the outermost arguments and argument count.
-                for (unsigned i = 1 + numberOfArgumentsToSkip; i < static_cast<unsigned>(m_graph.m_codeBlock->numParameters()); i++)
+                for (unsigned i = m_graph.m_codeBlock->numParameters(); i-- > 1;)
                     m_read(virtualRegisterForArgument(i));
                 m_read(VirtualRegister(CallFrameSlot::argumentCount));
                 break;
             }
             
-            for (unsigned i = 1 + numberOfArgumentsToSkip; i < inlineCallFrame->arguments.size(); i++)
+            for (unsigned i = inlineCallFrame->arguments.size(); i-- > 1;)
                 m_read(VirtualRegister(inlineCallFrame->stackOffset + virtualRegisterForArgument(i).offset()));
             if (inlineCallFrame->isVarargs())
                 m_read(VirtualRegister(inlineCallFrame->stackOffset + CallFrameSlot::argumentCount));
index 6ed729b..397e999 100644 (file)
@@ -1004,7 +1004,6 @@ private:
         case PhantomNewGeneratorFunction:
         case PhantomCreateActivation:
         case PhantomDirectArguments:
-        case PhantomCreateRest:
         case PhantomClonedArguments:
         case GetMyArgumentByVal:
         case GetMyArgumentByValOutOfBounds:
index 2c99802..0a2ecd8 100644 (file)
@@ -354,7 +354,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case MaterializeNewObject:
     case MaterializeCreateActivation:
     case PhantomDirectArguments:
-    case PhantomCreateRest:
     case PhantomClonedArguments:
     case GetMyArgumentByVal:
     case GetMyArgumentByValOutOfBounds:
index 2732fe8..7b57b18 100644 (file)
@@ -6852,7 +6852,6 @@ void SpeculativeJIT::compileCreateRest(Node* node)
         GPRReg arrayResultGPR = arrayResult.gpr();
 
         bool shouldAllowForArrayStorageStructureForLargeArrays = false;
-        ASSERT(m_jit.graph().globalObjectFor(node->origin.semantic)->restParameterStructure()->indexingType() == ArrayWithContiguous);
         compileAllocateNewArrayWithSize(m_jit.graph().globalObjectFor(node->origin.semantic), arrayResultGPR, arrayLengthGPR, ArrayWithContiguous, shouldAllowForArrayStorageStructureForLargeArrays);
 
         GPRTemporary argumentsStart(this);
index cb04a5a..8f72b1e 100644 (file)
@@ -5601,7 +5601,6 @@ void SpeculativeJIT::compile(Node* node)
     case GetStack:
     case GetMyArgumentByVal:
     case GetMyArgumentByValOutOfBounds:
-    case PhantomCreateRest:
         DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend");
         break;
     }
index b41c6f3..f89c1e6 100644 (file)
@@ -5818,7 +5818,6 @@ void SpeculativeJIT::compile(Node* node)
     case PutStack:
     case KillStack:
     case GetStack:
-    case PhantomCreateRest:
         DFG_CRASH(m_jit.graph(), node, "Unexpected node");
         break;
     }
index 86b50dd..51cf489 100644 (file)
@@ -118,14 +118,6 @@ public:
                     registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage));
                     break;
                 }
-
-                case CreateRest: {
-                    if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
-                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                        registerStructure(globalObject->restParameterStructure());
-                    }
-                    break;
-                }
                     
                 case NewTypedArray:
                     registerStructure(m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(node->typedArrayType()));
index 423301c..918d8ad 100644 (file)
@@ -670,7 +670,6 @@ private:
                 case PhantomNewGeneratorFunction:
                 case PhantomCreateActivation:
                 case PhantomDirectArguments:
-                case PhantomCreateRest:
                 case PhantomClonedArguments:
                 case MovHint:
                 case Upsilon:
index 54f4e72..3af1cb7 100644 (file)
@@ -230,7 +230,6 @@ inline CapabilityLevel canCompile(Node* node)
     case MaterializeNewObject:
     case MaterializeCreateActivation:
     case PhantomDirectArguments:
-    case PhantomCreateRest:
     case PhantomClonedArguments:
     case GetMyArgumentByVal:
     case GetMyArgumentByValOutOfBounds:
index ad16157..3f09dcf 100644 (file)
@@ -1074,7 +1074,6 @@ private:
         case PhantomNewGeneratorFunction:
         case PhantomCreateActivation:
         case PhantomDirectArguments:
-        case PhantomCreateRest:
         case PhantomClonedArguments:
         case PutHint:
         case BottomValue:
@@ -3435,8 +3434,6 @@ private:
         InlineCallFrame* inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
         
         LValue index = lowInt32(m_node->child2());
-        if (m_node->numberOfArgumentsToSkip())
-            index = m_out.add(index, m_out.constInt32(m_node->numberOfArgumentsToSkip()));
         
         LValue limit;
         if (inlineCallFrame && !inlineCallFrame->isVarargs())
@@ -4160,7 +4157,7 @@ private:
             LValue arrayLength = lowInt32(m_node->child1());
             LBasicBlock loopStart = m_out.newBlock();
             JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-            Structure* structure = globalObject->restParameterStructure();
+            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
             ArrayValues arrayValues = allocateUninitializedContiguousJSArray(arrayLength, structure);
             LValue array = arrayValues.array;
             LValue butterfly = arrayValues.butterfly;
@@ -6288,47 +6285,17 @@ private:
             inlineCallFrame = m_node->child1()->origin.semantic.inlineCallFrame;
         else
             inlineCallFrame = m_node->origin.semantic.inlineCallFrame;
-
-        LValue length = nullptr; 
-        LValue lengthIncludingThis = nullptr;
-        ArgumentsLength argumentsLength = getArgumentsLength(inlineCallFrame);
-        if (argumentsLength.isKnown) {
-            unsigned knownLength = argumentsLength.known;
-            if (knownLength >= data->offset)
-                knownLength = knownLength - data->offset;
-            else
-                knownLength = 0;
-            length = m_out.constInt32(knownLength);
-            lengthIncludingThis = m_out.constInt32(knownLength + 1);
-        } else {
-            // We need to perform the same logical operation as the code above, but through dynamic operations.
-            if (!data->offset)
-                length = argumentsLength.value;
-            else {
-                LBasicBlock isLarger = m_out.newBlock();
-                LBasicBlock continuation = m_out.newBlock();
-
-                ValueFromBlock smallerOrEqualLengthResult = m_out.anchor(m_out.constInt32(0));
-                m_out.branch(
-                    m_out.above(argumentsLength.value, m_out.constInt32(data->offset)), unsure(isLarger), unsure(continuation));
-                LBasicBlock lastNext = m_out.appendTo(isLarger, continuation);
-                ValueFromBlock largerLengthResult = m_out.anchor(m_out.sub(argumentsLength.value, m_out.constInt32(data->offset)));
-                m_out.jump(continuation);
-
-                m_out.appendTo(continuation, lastNext);
-                length = m_out.phi(Int32, smallerOrEqualLengthResult, largerLengthResult);
-            }
-            lengthIncludingThis = m_out.add(length, m_out.constInt32(1));
-        }
-
+        
+        LValue length = getArgumentsLength(inlineCallFrame).value;
+        LValue lengthIncludingThis = m_out.add(length, m_out.constInt32(1 - data->offset));
+        
         speculate(
             VarargsOverflow, noValue(), nullptr,
             m_out.above(lengthIncludingThis, m_out.constInt32(data->limit)));
         
         m_out.store32(lengthIncludingThis, payloadFor(data->machineCount));
         
-        unsigned numberOfArgumentsToSkip = data->offset;
-        LValue sourceStart = getArgumentsStart(inlineCallFrame, numberOfArgumentsToSkip);
+        LValue sourceStart = getArgumentsStart(inlineCallFrame);
         LValue targetStart = addressFor(data->machineStart).value();
 
         LBasicBlock undefinedLoop = m_out.newBlock();
@@ -6361,7 +6328,9 @@ private:
         previousIndex = m_out.phi(pointerType(), loopBound);
         currentIndex = m_out.sub(previousIndex, m_out.intPtrOne);
         LValue value = m_out.load64(
-            m_out.baseIndex(m_heaps.variables, sourceStart, currentIndex));
+            m_out.baseIndex(
+                m_heaps.variables, sourceStart,
+                m_out.add(currentIndex, m_out.constIntPtr(data->offset))));
         m_out.store64(value, m_out.baseIndex(m_heaps.variables, targetStart, currentIndex));
         nextIndex = m_out.anchor(currentIndex);
         m_out.addIncomingToPhi(previousIndex, nextIndex);
@@ -8407,9 +8376,9 @@ private:
         return m_out.loadPtr(addressFor(CallFrameSlot::callee));
     }
     
-    LValue getArgumentsStart(InlineCallFrame* inlineCallFrame, unsigned offset = 0)
+    LValue getArgumentsStart(InlineCallFrame* inlineCallFrame)
     {
-        VirtualRegister start = AssemblyHelpers::argumentsStart(inlineCallFrame) + offset;
+        VirtualRegister start = AssemblyHelpers::argumentsStart(inlineCallFrame);
         return addressFor(start).value();
     }
     
index 6c8ef8e..beeebc0 100644 (file)
@@ -83,7 +83,6 @@ extern "C" void JIT_OPERATION operationPopulateObjectInOSR(
     case PhantomNewGeneratorFunction:
     case PhantomDirectArguments:
     case PhantomClonedArguments:
-    case PhantomCreateRest:
         // Those are completely handled by operationMaterializeObjectInOSR
         break;
 
@@ -235,7 +234,6 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
         return result;
     }
 
-    case PhantomCreateRest:
     case PhantomDirectArguments:
     case PhantomClonedArguments: {
         if (!materialization->origin().inlineCallFrame) {
@@ -244,17 +242,6 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
                 return DirectArguments::createByCopying(exec);
             case PhantomClonedArguments:
                 return ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned);
-            case PhantomCreateRest: {
-                CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
-                    materialization->origin(), exec->codeBlock());
-
-                unsigned numberOfArgumentsToSkip = codeBlock->numParameters() - 1;
-                JSGlobalObject* globalObject = codeBlock->globalObject();
-                Structure* structure = globalObject->restParameterStructure();
-                JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numberOfArgumentsToSkip;
-                unsigned arraySize = exec->argumentCount() > numberOfArgumentsToSkip ? exec->argumentCount() - numberOfArgumentsToSkip : 0;
-                return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
-            }
             default:
                 RELEASE_ASSERT_NOT_REACHED();
                 return nullptr;
@@ -268,12 +255,14 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
                 const ExitPropertyValue& property = materialization->properties()[i];
                 if (property.location() != PromotedLocationDescriptor(ArgumentCountPLoc))
                     continue;
+                
                 argumentCount = JSValue::decode(values[i]).asUInt32();
+                RELEASE_ASSERT(argumentCount);
                 break;
             }
+            RELEASE_ASSERT(argumentCount);
         } else
             argumentCount = materialization->origin().inlineCallFrame->arguments.size();
-        RELEASE_ASSERT(argumentCount);
         
         JSFunction* callee = nullptr;
         if (materialization->origin().inlineCallFrame->isClosureCall) {
@@ -341,56 +330,6 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
             
             return result;
         }
-        case PhantomCreateRest: {
-            unsigned numberOfArgumentsToSkip = codeBlock->numParameters() - 1;
-            JSGlobalObject* globalObject = codeBlock->globalObject();
-            Structure* structure = globalObject->restParameterStructure();
-            ASSERT(argumentCount > 0);
-            unsigned arraySize = (argumentCount - 1) > numberOfArgumentsToSkip ? argumentCount - 1 - numberOfArgumentsToSkip : 0;
-            JSArray* array = JSArray::tryCreateUninitialized(vm, structure, arraySize);
-            RELEASE_ASSERT(array);
-
-            for (unsigned i = materialization->properties().size(); i--;) {
-                const ExitPropertyValue& property = materialization->properties()[i];
-                if (property.location().kind() != ArgumentPLoc)
-                    continue;
-
-                unsigned argIndex = property.location().info();
-                if (numberOfArgumentsToSkip > argIndex)
-                    continue;
-                unsigned arrayIndex = argIndex - numberOfArgumentsToSkip;
-                if (arrayIndex >= arraySize)
-                    continue;
-                array->initializeIndex(vm, arrayIndex, JSValue::decode(values[i]));
-            }
-
-            if (!ASSERT_DISABLED) {
-                // We avoid this O(n^2) loop when asserts are disabled, but the condition checked here
-                // must hold to ensure the correctness of the above loop because of how we allocate the array.
-                for (unsigned targetIndex = 0; targetIndex < arraySize; ++targetIndex) {
-                    bool found = false;
-                    for (unsigned i = materialization->properties().size(); i--;) {
-                        const ExitPropertyValue& property = materialization->properties()[i];
-                        if (property.location().kind() != ArgumentPLoc)
-                            continue;
-
-                        unsigned argIndex = property.location().info();
-                        if (numberOfArgumentsToSkip > argIndex)
-                            continue;
-                        unsigned arrayIndex = argIndex - numberOfArgumentsToSkip;
-                        if (arrayIndex >= arraySize)
-                            continue;
-                        if (arrayIndex == targetIndex) {
-                            found = true;
-                            break;
-                        }
-                    }
-                    ASSERT_UNUSED(found, found);
-                }
-            }
-
-            return array;
-        }
         default:
             RELEASE_ASSERT_NOT_REACHED();
             return nullptr;
index d2d4515..194e979 100644 (file)
@@ -47,7 +47,7 @@ void emitSetVarargsFrame(CCallHelpers& jit, GPRReg lengthGPR, bool lengthInclude
     jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), resultGPR);
 
     jit.addPtr(lengthGPR, resultGPR);
-    jit.addPtr(CCallHelpers::TrustedImm32(CallFrame::headerSizeInRegisters + (lengthIncludesThis ? 0 : 1)), resultGPR);
+    jit.addPtr(CCallHelpers::TrustedImm32(CallFrame::headerSizeInRegisters + (lengthIncludesThis? 0 : 1)), resultGPR);
     
     // resultGPR now has the required frame size in Register units
     // Round resultGPR to next multiple of stackAlignmentRegisters()
index 9f64da0..947ae86 100644 (file)
@@ -851,7 +851,7 @@ SLOW_PATH_DECL(slow_path_create_rest)
     BEGIN();
     unsigned arraySize = OP_C(2).jsValue().asUInt32();
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    Structure* structure = globalObject->restParameterStructure();
+    Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
     unsigned numParamsToSkip = pc[3].u.unsignedValue;
     JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
     RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
index ea57506..01ec341 100644 (file)
@@ -623,7 +623,6 @@ public:
     Structure* callableProxyObjectStructure() const { return m_callableProxyObjectStructure.get(); }
     Structure* proxyRevokeStructure() const { return m_proxyRevokeStructure.get(); }
     Structure* moduleLoaderStructure() const { return m_moduleLoaderStructure.get(); }
-    Structure* restParameterStructure() const { return arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous); }
 
     JS_EXPORT_PRIVATE void setRemoteDebuggingEnabled(bool);
     JS_EXPORT_PRIVATE bool remoteDebuggingEnabled() const;