Unreviewed, rolling out r210476.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jan 2017 21:09:04 +0000 (21:09 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Jan 2017 21:09:04 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=166859

"4% JSBench regression" (Requested by keith_mi_ on #webkit).

Reverted changeset:

"Add a slice intrinsic to the DFG/FTL"
https://bugs.webkit.org/show_bug.cgi?id=166707
http://trac.webkit.org/changeset/210476

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

27 files changed:
JSTests/ChangeLog
JSTests/stress/array-slice-intrinsic.js [deleted file]
JSTests/stress/array-slice-jettison-on-constructor-change.js [deleted file]
JSTests/stress/array-slice-osr-exit-2.js [deleted file]
JSTests/stress/array-slice-osr-exit.js [deleted file]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/jit/AssemblyHelpers.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.h
Source/JavaScriptCore/runtime/Intrinsic.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h

index f97f13f..621806c 100644 (file)
@@ -1,3 +1,16 @@
+2017-01-09  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r210476.
+        https://bugs.webkit.org/show_bug.cgi?id=166859
+
+        "4% JSBench regression" (Requested by keith_mi_ on #webkit).
+
+        Reverted changeset:
+
+        "Add a slice intrinsic to the DFG/FTL"
+        https://bugs.webkit.org/show_bug.cgi?id=166707
+        http://trac.webkit.org/changeset/210476
+
 2017-01-06  Saam Barati  <sbarati@apple.com>
 
         Add a slice intrinsic to the DFG/FTL
diff --git a/JSTests/stress/array-slice-intrinsic.js b/JSTests/stress/array-slice-intrinsic.js
deleted file mode 100644 (file)
index 725a74d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-function assert(b) {
-    if (!b)
-        throw new Error("Bad")
-}
-noInline(assert);
-
-function shallowEq(a, b) {
-    assert(a.length === b.length);
-    for (let i = 0; i < a.length; i++)
-        assert(a[i] === b[i]);
-}
-noInline(shallowEq);
-
-let tests = [
-    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
-    [[1,2,3,4,5], [1,2,3,4,5], 0],
-    [[1,2,3,4,5], [4], -2, -1],
-    [[1,2,3,4,5], [5], -1],
-    [[1,2,3,4,5], [5], -1, 5],
-    [[1,2,3,4,5], [], -10, -20],
-    [[1,2,3,4,5], [], -20, -10],
-    [[1,2,3,4,5], [], 6, 4],
-    [[1,2,3,4,5], [], 3, 2],
-    [[1,2,3,4,5], [4,5], 3, 10],
-    [[1,2,3,4,5], [3,4,5], 2, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
-    [[1,2,3,4,5], [2,3,4,5], -4, 10],
-];
-
-function runTest1(a, b) {
-    return a.slice(b);
-}
-noInline(runTest1);
-
-function runTest2(a, b, c) {
-    return a.slice(b, c);
-}
-noInline(runTest2);
-
-for (let i = 0; i < 10000; i++) {
-    for (let [input, output, ...args] of tests) {
-        assert(args.length === 1 || args.length === 2);
-        if (args.length === 1)
-            shallowEq(runTest1(input, args[0]), output);
-        else
-            shallowEq(runTest2(input, args[0], args[1]), output);
-    }
-}
diff --git a/JSTests/stress/array-slice-jettison-on-constructor-change.js b/JSTests/stress/array-slice-jettison-on-constructor-change.js
deleted file mode 100644 (file)
index 4049da9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-function assert(b) {
-    if (!b)
-        throw new Error("Bad")
-}
-noInline(assert);
-
-let shouldBeNewConstructor = false;
-const newConstructor = {};
-
-function shallowEq(a, b) {
-    assert(a.length === b.length);
-    if (shouldBeNewConstructor)
-        assert(b.constructor === newConstructor);
-    for (let i = 0; i < a.length; i++)
-        assert(a[i] === b[i]);
-}
-noInline(shallowEq);
-
-let tests = [
-    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
-    [[1,2,3,4,5], [1,2,3,4,5], 0],
-    [[1,2,3,4,5], [4], -2, -1],
-    [[1,2,3,4,5], [5], -1],
-    [[1,2,3,4,5], [5], -1, 5],
-    [[1,2,3,4,5], [], -10, -20],
-    [[1,2,3,4,5], [], -20, -10],
-    [[1,2,3,4,5], [], 6, 4],
-    [[1,2,3,4,5], [], 3, 2],
-    [[1,2,3,4,5], [4,5], 3, 10],
-    [[1,2,3,4,5], [3,4,5], 2, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
-    [[1,2,3,4,5], [2,3,4,5], -4, 10],
-];
-
-function runTest1(a, b) {
-    let result = a.slice(b);
-    return result;
-}
-noInline(runTest1);
-
-function runTest2(a, b, c) {
-    let result = a.slice(b, c);
-    return result;
-}
-noInline(runTest2);
-
-function addRandomProperties(input) {
-    for (let i = 0; i < 4; i++) {
-        input["prop" + i + ((Math.random() * 100000) | 0)] = i;
-    }
-}
-noInline(addRandomProperties);
-
-function runTests() {
-    for (let i = 0; i < 10000; i++) {
-        for (let [input, output, ...args] of tests) {
-            addRandomProperties(input);
-            assert(args.length === 1 || args.length === 2);
-            if (args.length === 1)
-                shallowEq(runTest1(input, args[0]), output);
-            else
-                shallowEq(runTest2(input, args[0], args[1]), output);
-        }
-    }
-}
-
-runTests();
-
-Array.prototype.constructor = newConstructor;
-shouldBeNewConstructor = true;
-runTests();
diff --git a/JSTests/stress/array-slice-osr-exit-2.js b/JSTests/stress/array-slice-osr-exit-2.js
deleted file mode 100644 (file)
index 2db07ce..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-function assert(b) {
-    if (!b)
-        throw new Error("Bad")
-}
-noInline(assert);
-
-class Foo extends Array {
-    constructor(...args) {
-        super(...args);
-    }
-};
-function shallowEq(a, b) {
-    assert(a.length === b.length);
-    for (let i = 0; i < a.length; i++)
-        assert(a[i] === b[i]);
-}
-noInline(shallowEq);
-
-let tests = [
-    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
-    [[1,2,3,4,5], [1,2,3,4,5], 0],
-    [[1,2,3,4,5], [4], -2, -1],
-    [[1,2,3,4,5], [5], -1],
-    [[1,2,3,4,5], [5], -1, 5],
-    [[1,2,3,4,5], [], -10, -20],
-    [[1,2,3,4,5], [], -20, -10],
-    [[1,2,3,4,5], [], 6, 4],
-    [[1,2,3,4,5], [], 3, 2],
-    [[1,2,3,4,5], [4,5], 3, 10],
-    [[1,2,3,4,5], [3,4,5], 2, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
-    [[1,2,3,4,5], [2,3,4,5], -4, 10],
-];
-
-function runTest1(a, b) {
-    let result = a.slice(b);
-    assert(a instanceof Foo === result instanceof Foo);
-    return result;
-}
-noInline(runTest1);
-
-function runTest2(a, b, c) {
-    let result = a.slice(b, c);
-    assert(a instanceof Foo === result instanceof Foo);
-    return result;
-}
-noInline(runTest2);
-
-function addRandomProperties(input) {
-    for (let i = 0; i < 4; i++) {
-        input["prop" + i + ((Math.random() * 100000) | 0)] = i;
-    }
-}
-noInline(addRandomProperties);
-
-function runTests() {
-    for (let i = 0; i < 10000; i++) {
-        for (let [input, output, ...args] of tests) {
-            addRandomProperties(input);
-            assert(args.length === 1 || args.length === 2);
-            if (args.length === 1)
-                shallowEq(runTest1(input, args[0]), output);
-            else
-                shallowEq(runTest2(input, args[0], args[1]), output);
-        }
-    }
-}
-
-runTests();
-
-tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -10, 10]);
-tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -5, 10]);
-tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4, 10]);
-tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4]);
-runTests();
diff --git a/JSTests/stress/array-slice-osr-exit.js b/JSTests/stress/array-slice-osr-exit.js
deleted file mode 100644 (file)
index 93ed2bb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-function assert(b) {
-    if (!b)
-        throw new Error("Bad")
-}
-noInline(assert);
-
-class Foo extends Array {
-    constructor(...args) {
-        super(...args);
-    }
-};
-function shallowEq(a, b) {
-    assert(a.length === b.length);
-    for (let i = 0; i < a.length; i++)
-        assert(a[i] === b[i]);
-}
-noInline(shallowEq);
-
-let tests = [
-    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
-    [[1,2,3,4,5], [1,2,3,4,5], 0],
-    [[1,2,3,4,5], [4], -2, -1],
-    [[1,2,3,4,5], [5], -1],
-    [[1,2,3,4,5], [5], -1, 5],
-    [[1,2,3,4,5], [], -10, -20],
-    [[1,2,3,4,5], [], -20, -10],
-    [[1,2,3,4,5], [], 6, 4],
-    [[1,2,3,4,5], [], 3, 2],
-    [[1,2,3,4,5], [4,5], 3, 10],
-    [[1,2,3,4,5], [3,4,5], 2, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
-    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
-    [[1,2,3,4,5], [2,3,4,5], -4, 10],
-];
-tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -10, 10]);
-tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -5, 10]);
-tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4, 10]);
-tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4]);
-
-function runTest1(a, b) {
-    let result = a.slice(b);
-    assert(a instanceof Foo === result instanceof Foo);
-    return result;
-}
-noInline(runTest1);
-
-function runTest2(a, b, c) {
-    let result = a.slice(b, c);
-    assert(a instanceof Foo === result instanceof Foo);
-    return result;
-}
-noInline(runTest2);
-
-function addRandomProperties(input) {
-    for (let i = 0; i < 4; i++) {
-        input["prop" + i + ((Math.random() * 100000) | 0)] = i;
-    }
-}
-noInline(addRandomProperties);
-
-function runTests() {
-    for (let i = 0; i < 10000; i++) {
-        for (let [input, output, ...args] of tests) {
-            addRandomProperties(input);
-            assert(args.length === 1 || args.length === 2);
-            if (args.length === 1)
-                shallowEq(runTest1(input, args[0]), output);
-            else
-                shallowEq(runTest2(input, args[0], args[1]), output);
-        }
-    }
-}
-
-runTests();
index df11451..9dd94ba 100644 (file)
@@ -1,3 +1,16 @@
+2017-01-09  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r210476.
+        https://bugs.webkit.org/show_bug.cgi?id=166859
+
+        "4% JSBench regression" (Requested by keith_mi_ on #webkit).
+
+        Reverted changeset:
+
+        "Add a slice intrinsic to the DFG/FTL"
+        https://bugs.webkit.org/show_bug.cgi?id=166707
+        http://trac.webkit.org/changeset/210476
+
 2017-01-08  Andreas Kling  <akling@apple.com>
 
         Inject MarkedSpace size classes for a few more high-volume objects.
index a9021f5..2791aea 100644 (file)
@@ -1650,25 +1650,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).setType(SpecBytecodeNumber);
         break;
-
-    case ArraySlice:
-        IndexingType indexingType;
-        switch (node->arrayMode().type()) {
-        case Array::Double:
-            indexingType = ArrayWithDouble;
-            break;
-        case Array::Int32:
-            indexingType = ArrayWithInt32;
-            break;
-        case Array::Contiguous:
-            indexingType = ArrayWithContiguous;
-            break;
-        default:
-            DFG_CRASH(m_graph, node, "Bad array mode.");
-        }
-
-        forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(indexingType));
-        break;
             
     case ArrayPop:
         clobberWorld(node->origin.semantic, clobberLimit);
index 789337c..d452b92 100644 (file)
@@ -2246,92 +2246,6 @@ bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrin
             return false;
         }
     }
-
-    case ArraySliceIntrinsic: {
-#if USE(JSVALUE32_64)
-        if (isX86()) {
-            // There aren't enough registers for this to be done easily.
-            return false;
-        }
-#endif
-        if (argumentCountIncludingThis < 2)
-            return false;
-
-        if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
-            || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
-            || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
-            return false;
-
-        ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
-        if (!arrayMode.isJSArray())
-            return false;
-
-        if (arrayMode.arrayClass() != Array::OriginalArray)
-            return false;
-
-        switch (arrayMode.type()) {
-        case Array::Double:
-        case Array::Int32:
-        case Array::Contiguous: {
-            JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
-
-            InlineWatchpointSet& objectPrototypeTransition = globalObject->objectPrototype()->structure()->transitionWatchpointSet();
-            InlineWatchpointSet& arrayPrototypeTransition = globalObject->arrayPrototype()->structure()->transitionWatchpointSet();
-
-            // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
-            if (globalObject->arraySpeciesWatchpoint().isStillValid()
-                && globalObject->havingABadTimeWatchpoint()->isStillValid()
-                && arrayPrototypeTransition.isStillValid()
-                && objectPrototypeTransition.isStillValid()
-                && globalObject->arrayPrototypeChainIsSane()) {
-
-                m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
-                m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
-                m_graph.watchpoints().addLazily(arrayPrototypeTransition);
-                m_graph.watchpoints().addLazily(objectPrototypeTransition);
-
-                insertChecks();
-
-                Node* array = get(virtualRegisterForArgument(0, registerOffset));
-                // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
-                // 1. We ensure that the "constructor" property hasn't been changed (because the observable
-                // effects of slice require that we perform a Get(array, "constructor") and we can skip
-                // that if we're an original array structure.
-                //
-                // 2. We check that the array we're calling slice on has the same global object as the lexical
-                // global object that this code is running in. This requirement is necessary because we setup the
-                // watchpoints above on the lexical global object. This means that code that calls slice on
-                // arrays produced by other global objects won't get this optimization. We could relax this
-                // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
-                // we generate instead of registering it as a watchpoint that would invalidate the compilation.
-                //
-                // 3. By proving we're an original array structure, we guarantee that the incoming array
-                // isn't a subclass of Array.
-
-                Structure* structure = arrayMode.originalArrayStructure(m_graph, currentNodeOrigin().semantic);
-                RELEASE_ASSERT(structure);
-                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), array);
-
-                addVarArgChild(array);
-                addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
-                if (argumentCountIncludingThis >= 3)
-                    addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
-                addVarArgChild(addToGraph(GetButterfly, array));
-
-                Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(arrayMode.asWord()), OpInfo(prediction));
-                set(VirtualRegister(resultOperand), arraySlice);
-                return true;
-            }
-
-            return false;
-        }
-        default:
-            return false;
-        }
-
-        RELEASE_ASSERT_NOT_REACHED();
-        return false;
-    }
         
     case ArrayPopIntrinsic: {
         if (argumentCountIncludingThis != 1)
index c04e2ee..0ced522 100644 (file)
@@ -503,29 +503,6 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
         read(MiscFields);
         def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
         return;
-
-    case ArraySlice:
-        read(MiscFields);
-        read(JSCell_indexingType);
-        read(JSCell_structureID);
-        read(JSObject_butterfly);
-        read(Butterfly_publicLength);
-        switch (node->arrayMode().type()) {
-        case Array::Double:
-            read(IndexedDoubleProperties);
-            break;
-        case Array::Int32:
-            read(IndexedInt32Properties);
-            break;
-        case Array::Contiguous:
-            read(IndexedContiguousProperties);
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-        read(HeapObjectCount);
-        write(HeapObjectCount);
-        return;
         
     case GetById:
     case GetByIdFlush:
index cdc0406..e71f2b3 100644 (file)
@@ -309,7 +309,6 @@ bool doesGC(Graph& graph, Node* node)
     case ToLowerCase:
     case CallDOMGetter:
     case CallDOM:
-    case ArraySlice:
         return true;
         
     case MultiPutByOffset:
index 1ad7bc1..ca562b4 100644 (file)
@@ -931,14 +931,6 @@ private:
             fixEdge<KnownCellUse>(node->child1());
             break;
         }
-
-        case ArraySlice: {
-            fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
-            fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
-            if (node->numChildren() == 4)
-                fixEdge<Int32Use>(m_graph.varArgChild(node, 2));
-            break;
-        }
             
         case RegExpExec:
         case RegExpTest: {
index c636435..b28157f 100644 (file)
@@ -1472,7 +1472,6 @@ public:
         case GetArgument:
         case ArrayPop:
         case ArrayPush:
-        case ArraySlice:
         case RegExpExec:
         case RegExpTest:
         case GetGlobalVar:
@@ -1797,7 +1796,6 @@ public:
         case Arrayify:
         case ArrayifyToStructure:
         case ArrayPush:
-        case ArraySlice:
         case ArrayPop:
         case HasIndexedProperty:
             return true;
index 6af4b35..d45e4df 100644 (file)
@@ -248,7 +248,6 @@ namespace JSC { namespace DFG {
     /* Optimizations for array mutation. */\
     macro(ArrayPush, NodeResultJS | NodeMustGenerate) \
     macro(ArrayPop, NodeResultJS | NodeMustGenerate) \
-    macro(ArraySlice, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
     \
     /* Optimizations for regular expression matching. */\
     macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
index 3c0cd9e..356ef3e 100644 (file)
@@ -678,7 +678,6 @@ private:
 
         case ArrayPop:
         case ArrayPush:
-        case ArraySlice:
         case RegExpExec:
         case RegExpTest:
         case StringReplace:
index 60338fb..f3f7892 100644 (file)
@@ -402,7 +402,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case GetArrayLength:
     case ArrayPush:
     case ArrayPop:
-    case ArraySlice:
     case StringCharAt:
     case StringCharCodeAt:
         return node->arrayMode().alreadyChecked(graph, node, state.forNode(node->child1()));
index 665330e..82bbe2b 100644 (file)
@@ -7171,127 +7171,6 @@ void SpeculativeJIT::compileGetRestLength(Node* node)
     int32Result(resultGPR, node);
 }
 
-void SpeculativeJIT::compileArraySlice(Node* node)
-{
-    ASSERT(node->op() == ArraySlice);
-
-    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
-
-    GPRTemporary temp(this);
-    StorageOperand storage(this, node->numChildren() == 3 ? m_jit.graph().varArgChild(node, 2) : m_jit.graph().varArgChild(node, 3));
-    GPRTemporary result(this);
-    
-    GPRReg storageGPR = storage.gpr();
-    GPRReg resultGPR = result.gpr();
-    GPRReg tempGPR = temp.gpr();
-
-    IndexingType indexingType;
-    switch (node->arrayMode().type()) {
-    case Array::Int32:
-        indexingType = ArrayWithInt32;
-        break;
-    case Array::Contiguous:
-        indexingType = ArrayWithContiguous;
-        break;
-    case Array::Double:
-        indexingType = ArrayWithDouble;
-        break;
-    default:
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-
-    auto populateIndex = [&] (unsigned childIndex, GPRReg length, GPRReg result) {
-        SpeculateInt32Operand index(this, m_jit.graph().varArgChild(node, childIndex));
-        GPRReg indexGPR = index.gpr();
-        MacroAssembler::JumpList done;
-        auto isPositive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, indexGPR, TrustedImm32(0));
-        m_jit.move(length, result);
-        done.append(m_jit.branchAdd32(MacroAssembler::PositiveOrZero, indexGPR, result));
-        m_jit.move(TrustedImm32(0), result);
-        done.append(m_jit.jump());
-
-        isPositive.link(&m_jit);
-        m_jit.move(indexGPR, result);
-        done.append(m_jit.branch32(MacroAssembler::BelowOrEqual, result, length));
-        m_jit.move(length, result);
-
-        done.link(&m_jit);
-    };
-
-    {
-        GPRTemporary tempLength(this);
-        GPRReg lengthGPR = tempLength.gpr();
-        m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), lengthGPR);
-
-        if (node->numChildren() == 4)
-            populateIndex(2, lengthGPR, tempGPR);
-        else
-            m_jit.move(lengthGPR, tempGPR);
-
-        GPRTemporary tempStartIndex(this);
-        GPRReg startGPR = tempStartIndex.gpr();
-        populateIndex(1, lengthGPR, startGPR);
-
-        auto tooBig = m_jit.branch32(MacroAssembler::Above, startGPR, tempGPR);
-        m_jit.sub32(startGPR, tempGPR); // the size of the array we'll make.
-        auto done = m_jit.jump();
-
-        tooBig.link(&m_jit);
-        m_jit.move(TrustedImm32(0), tempGPR);
-        done.link(&m_jit);
-    }
-
-    const bool shouldConvertLargeSizeToArrayStorage = false;
-    compileAllocateNewArrayWithSize(globalObject, resultGPR, tempGPR, indexingType, shouldConvertLargeSizeToArrayStorage);
-
-    GPRTemporary temp3(this);
-    GPRTemporary temp4(this);
-    GPRReg tempValue = temp3.gpr();
-    GPRReg loadIndex = temp4.gpr();
-
-    m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), tempValue);
-    if (node->numChildren() == 4)
-        populateIndex(2, tempValue, tempGPR);
-    else
-        m_jit.move(tempValue, tempGPR);
-    populateIndex(1, tempValue, loadIndex);
-
-    GPRTemporary temp5(this);
-    GPRReg storeIndex = temp5.gpr();
-    m_jit.move(TrustedImmPtr(0), storeIndex);
-
-    GPRTemporary temp2(this);
-    GPRReg resultButterfly = temp2.gpr();
-
-    m_jit.loadPtr(MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()), resultButterfly);
-    m_jit.zeroExtend32ToPtr(tempGPR, tempGPR);
-    m_jit.zeroExtend32ToPtr(loadIndex, loadIndex);
-    auto done = m_jit.branchPtr(MacroAssembler::AboveOrEqual, loadIndex, tempGPR);
-
-    auto loop = m_jit.label();
-#if USE(JSVALUE64)
-    m_jit.load64(
-        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight), tempValue);
-    m_jit.store64(
-        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight));
-#else
-    m_jit.load32(
-        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight, PayloadOffset), tempValue);
-    m_jit.store32(
-        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight, PayloadOffset));
-    m_jit.load32(
-        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight, TagOffset), tempValue);
-    m_jit.store32(
-        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight, TagOffset));
-#endif // USE(JSVALUE64)
-    m_jit.addPtr(TrustedImm32(1), loadIndex);
-    m_jit.addPtr(TrustedImm32(1), storeIndex);
-    m_jit.branchPtr(MacroAssembler::Below, loadIndex, tempGPR).linkTo(loop, &m_jit);
-
-    done.link(&m_jit);
-    cellResult(resultGPR, node);
-}
-
 void SpeculativeJIT::compileNotifyWrite(Node* node)
 {
     WatchpointSet* set = node->watchpointSet();
index 9200873..b0f0e08 100644 (file)
@@ -2680,7 +2680,6 @@ public:
     void compileSpread(Node*);
     void compileNewArrayWithSpread(Node*);
     void compileGetRestLength(Node*);
-    void compileArraySlice(Node*);
     void compileNotifyWrite(Node*);
     bool compileRegExpExec(Node*);
     void compileIsObjectOrNull(Node*);
index c94000a..4fa8484 100644 (file)
@@ -3550,11 +3550,6 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
-    case ArraySlice: {
-        compileArraySlice(node);
-        break;
-    }
-
     case DFG::Jump: {
         jump(node->targetBlock());
         noResult(node);
index a532836..e51499d 100644 (file)
@@ -3462,11 +3462,6 @@ void SpeculativeJIT::compile(Node* node)
         }
         break;
     }
-
-    case ArraySlice: {
-        compileArraySlice(node);
-        break;
-    }
         
     case ArrayPop: {
         ASSERT(node->arrayMode().isJSArray());
index 4383f12..d42ff4a 100644 (file)
@@ -282,7 +282,6 @@ inline CapabilityLevel canCompile(Node* node)
     case CheckDOM:
     case CallDOM:
     case CallDOMGetter:
-    case ArraySlice:
         // These are OK.
         break;
 
index 98ba875..70ebf86 100644 (file)
@@ -706,9 +706,6 @@ private:
         case ArrayPop:
             compileArrayPop();
             break;
-        case ArraySlice:
-            compileArraySlice();
-            break;
         case CreateActivation:
             compileCreateActivation();
             break;
@@ -3863,83 +3860,6 @@ private:
             return;
         }
     }
-
-    void compileArraySlice()
-    {
-        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-
-        LValue sourceStorage = lowStorage(m_node->numChildren() == 3 ? m_graph.varArgChild(m_node, 2) : m_graph.varArgChild(m_node, 3));
-        LValue inputLength = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
-
-        LValue endBoundary;
-        if (m_node->numChildren() == 3)
-            endBoundary = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
-        else {
-            endBoundary = lowInt32(m_graph.varArgChild(m_node, 2));
-            endBoundary = m_out.select(m_out.greaterThanOrEqual(endBoundary, m_out.constInt32(0)),
-                m_out.select(m_out.above(endBoundary, inputLength), inputLength, endBoundary),
-                m_out.select(m_out.lessThan(m_out.add(inputLength, endBoundary), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, endBoundary)));
-        }
-
-        LValue startIndex = lowInt32(m_graph.varArgChild(m_node, 1));
-        startIndex = m_out.select(m_out.greaterThanOrEqual(startIndex, m_out.constInt32(0)),
-            m_out.select(m_out.above(startIndex, inputLength), inputLength, startIndex),
-            m_out.select(m_out.lessThan(m_out.add(inputLength, startIndex), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, startIndex)));
-
-        LValue resultLength = m_out.select(m_out.below(startIndex, endBoundary),
-            m_out.sub(endBoundary, startIndex),
-            m_out.constInt32(0));
-
-        IndexingType indexingType;
-        switch (m_node->arrayMode().type()) {
-        case Array::Int32:
-            indexingType = ArrayWithInt32;
-            break;
-        case Array::Contiguous:
-            indexingType = ArrayWithContiguous;
-            break;
-        case Array::Double:
-            indexingType = ArrayWithDouble;
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
-
-        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType);
-        auto arrayResult = allocateJSArray(resultLength, structure, false, false);
-
-        LBasicBlock loop = m_out.newBlock();
-        LBasicBlock continuation = m_out.newBlock();
-
-        resultLength = m_out.zeroExtPtr(resultLength);
-        ValueFromBlock startLoadIndex = m_out.anchor(m_out.zeroExtPtr(startIndex));
-        ValueFromBlock startStoreIndex = m_out.anchor(m_out.constIntPtr(0));
-
-        m_out.branch(
-            m_out.below(m_out.constIntPtr(0), resultLength), unsure(loop), unsure(continuation));
-
-        LBasicBlock lastNext = m_out.appendTo(loop, continuation);
-        LValue storeIndex = m_out.phi(pointerType(), startStoreIndex);
-        LValue loadIndex = m_out.phi(pointerType(), startLoadIndex);
-        IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());
-        if (indexingType == ArrayWithDouble) {
-            LValue value = m_out.loadDouble(m_out.baseIndex(heap, sourceStorage, loadIndex));
-            m_out.storeDouble(value, m_out.baseIndex(heap, arrayResult.butterfly, storeIndex));
-        } else {
-            LValue value = m_out.load64(m_out.baseIndex(heap, sourceStorage, loadIndex));
-            m_out.store64(value, m_out.baseIndex(heap, arrayResult.butterfly, storeIndex));
-        }
-        LValue nextStoreIndex = m_out.add(storeIndex, m_out.constIntPtr(1));
-        m_out.addIncomingToPhi(storeIndex, m_out.anchor(nextStoreIndex));
-        m_out.addIncomingToPhi(loadIndex, m_out.anchor(m_out.add(loadIndex, m_out.constIntPtr(1))));
-        m_out.branch(
-            m_out.below(nextStoreIndex, resultLength), unsure(loop), unsure(continuation));
-
-        m_out.appendTo(continuation, lastNext);
-
-        mutatorFence();
-        setJSValue(arrayResult.array);
-    }
     
     void compileArrayPop()
     {
index ba017e8..4b4cd8c 100644 (file)
@@ -447,7 +447,6 @@ void AssemblyHelpers::loadProperty(GPRReg object, GPRReg offset, JSValueRegs res
 void AssemblyHelpers::emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch)
 {
 #if USE(JSVALUE64)
-    ASSERT(dest != scratch);
     load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
     loadPtr(vm()->heap.structureIDTable().base(), scratch);
     loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
index d60bcdf..68edc38 100644 (file)
@@ -98,7 +98,7 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("reverse", arrayProtoFuncReverse, DontEnum, 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPublicName(), arrayProtoFuncShift, DontEnum, 0);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPrivateName(), arrayProtoFuncShift, DontEnum | DontDelete | ReadOnly, 0);
-    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayProtoFuncSlice, DontEnum, 2, ArraySliceIntrinsic);
+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayProtoFuncSlice, DontEnum, 2);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("sort", arrayPrototypeSortCodeGenerator, DontEnum);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("splice", arrayProtoFuncSplice, DontEnum, 2);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("unshift", arrayProtoFuncUnShift, DontEnum, 1);
@@ -191,12 +191,21 @@ static ALWAYS_INLINE void setLength(ExecState* exec, VM& vm, JSObject* obj, unsi
         throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
 }
 
-inline bool speciesWatchpointIsValid(JSObject* thisObject)
+inline bool speciesWatchpointsValid(ExecState* exec, JSObject* thisObject)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     ArrayPrototype* arrayPrototype = thisObject->globalObject()->arrayPrototype();
+    ArrayPrototype::SpeciesWatchpointStatus status = arrayPrototype->speciesWatchpointStatus();
+    if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized)) {
+        status = arrayPrototype->attemptToInitializeSpeciesWatchpoint(exec);
+        RETURN_IF_EXCEPTION(scope, false);
+    }
+    ASSERT(status != ArrayPrototype::SpeciesWatchpointStatus::Uninitialized);
     return !thisObject->hasCustomProperties()
         && arrayPrototype == thisObject->getPrototypeDirect()
-        && arrayPrototype->globalObject()->arraySpeciesWatchpoint().isStillValid();
+        && status == ArrayPrototype::SpeciesWatchpointStatus::Initialized;
 }
 
 enum class SpeciesConstructResult {
@@ -221,7 +230,8 @@ static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstru
     if (LIKELY(thisIsArray)) {
         // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal.
         // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default.
-        bool isValid = speciesWatchpointIsValid(thisObject);
+        bool isValid = speciesWatchpointsValid(exec, thisObject);
+        RETURN_IF_EXCEPTION(scope, exceptionResult());
         if (LIKELY(isValid))
             return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
 
@@ -910,29 +920,29 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 {
-    // https://tc39.github.io/ecma262/#sec-array.prototype.slice
+    // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
     ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
-        return { };
+        return encodedJSValue();
     unsigned length = getLength(exec, thisObj);
-    RETURN_IF_EXCEPTION(scope, { });
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
-    RETURN_IF_EXCEPTION(scope, { });
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
-    RETURN_IF_EXCEPTION(scope, { });
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, end - begin);
     // We can only get an exception if we call some user function.
     ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
     if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
-        return { };
+        return encodedJSValue();
 
     bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj) && length == getLength(exec, thisObj);
-    RETURN_IF_EXCEPTION(scope, { });
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (LIKELY(okToDoFastPath)) {
         if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin))
             return JSValue::encode(result);
@@ -943,16 +953,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
         result = speciesResult.second;
     else {
         result = constructEmptyArray(exec, nullptr, end - begin);
-        RETURN_IF_EXCEPTION(scope, { });
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
     }
 
     unsigned n = 0;
     for (unsigned k = begin; k < end; k++, n++) {
         JSValue v = getProperty(exec, thisObj, k);
-        RETURN_IF_EXCEPTION(scope, { });
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
         if (v) {
             result->putDirectIndex(exec, n, v, 0, PutDirectIndexShouldThrow);
-            RETURN_IF_EXCEPTION(scope, { });
+            RETURN_IF_EXCEPTION(scope, encodedJSValue());
         }
     }
     scope.release();
@@ -1239,7 +1249,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
         return JSValue::encode(jsNull());
 
     // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers.
-    bool isValid = speciesWatchpointIsValid(firstArray);
+    bool isValid = speciesWatchpointsValid(exec, firstArray);
+    ASSERT(!scope.exception() || !isValid);
     if (UNLIKELY(!isValid))
         return JSValue::encode(jsNull());
 
@@ -1331,18 +1342,15 @@ private:
     ArrayPrototype* m_arrayPrototype;
 };
 
-void ArrayPrototype::initializeSpeciesWatchpoint(ExecState* exec)
+ArrayPrototype::SpeciesWatchpointStatus ArrayPrototype::attemptToInitializeSpeciesWatchpoint(ExecState* exec)
 {
-    VM& vm = exec->vm();
-
-    RELEASE_ASSERT(!m_constructorWatchpoint);
-    RELEASE_ASSERT(!m_constructorSpeciesWatchpoint);
+    ASSERT(m_speciesWatchpointStatus == SpeciesWatchpointStatus::Uninitialized);
 
+    VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    UNUSED_PARAM(scope);
 
     if (verbose)
-        dataLog("Initializing Array species watchpoints for Array.prototype: ", pointerDump(this), " with structure: ", pointerDump(this->structure()), "\nand Array: ", pointerDump(this->globalObject()->arrayConstructor()), " with structure: ", pointerDump(this->globalObject()->arrayConstructor()->structure()), "\n");
+        dataLog("Attempting to initialize Array species watchpoints for Array.prototype: ", pointerDump(this), " with structure: ", pointerDump(this->structure()), "\nand Array: ", pointerDump(this->globalObject()->arrayConstructor()), " with structure: ", pointerDump(this->globalObject()->arrayConstructor()->structure()), "\n");
     // First we need to make sure that the Array.prototype.constructor property points to Array
     // and that Array[Symbol.species] is the primordial GetterSetter.
 
@@ -1356,22 +1364,24 @@ void ArrayPrototype::initializeSpeciesWatchpoint(ExecState* exec)
     ArrayConstructor* arrayConstructor = globalObject->arrayConstructor();
 
     PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry);
-    this->getOwnPropertySlot(this, exec, vm.propertyNames->constructor, constructorSlot);
-    ASSERT(!scope.exception());
-    ASSERT(constructorSlot.slotBase() == this);
-    ASSERT(constructorSlot.isCacheableValue());
-    RELEASE_ASSERT(constructorSlot.getValue(exec, vm.propertyNames->constructor) == arrayConstructor);
+    JSValue(this).get(exec, vm.propertyNames->constructor, constructorSlot);
+    if (UNLIKELY(scope.exception())
+        || constructorSlot.slotBase() != this
+        || !constructorSlot.isCacheableValue()
+        || constructorSlot.getValue(exec, vm.propertyNames->constructor) != arrayConstructor)
+        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
 
     Structure* constructorStructure = arrayConstructor->structure(vm);
     if (constructorStructure->isDictionary())
         constructorStructure = constructorStructure->flattenDictionaryStructure(vm, arrayConstructor);
 
     PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry);
-    arrayConstructor->getOwnPropertySlot(arrayConstructor, exec, vm.propertyNames->speciesSymbol, speciesSlot);
-    ASSERT(!scope.exception());
-    ASSERT(speciesSlot.slotBase() == arrayConstructor);
-    ASSERT(speciesSlot.isCacheableGetter());
-    RELEASE_ASSERT(speciesSlot.getterSetter() == globalObject->speciesGetterSetter());
+    JSValue(arrayConstructor).get(exec, vm.propertyNames->speciesSymbol, speciesSlot);
+    if (UNLIKELY(scope.exception())
+        || speciesSlot.slotBase() != arrayConstructor
+        || !speciesSlot.isCacheableGetter()
+        || speciesSlot.getterSetter() != globalObject->speciesGetterSetter())
+        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
 
     // Now we need to setup the watchpoints to make sure these conditions remain valid.
     prototypeStructure->startWatchingPropertyForReplacements(vm, constructorSlot.cachedOffset());
@@ -1380,14 +1390,16 @@ void ArrayPrototype::initializeSpeciesWatchpoint(ExecState* exec)
     ObjectPropertyCondition constructorCondition = ObjectPropertyCondition::equivalence(vm, this, this, vm.propertyNames->constructor.impl(), arrayConstructor);
     ObjectPropertyCondition speciesCondition = ObjectPropertyCondition::equivalence(vm, this, arrayConstructor, vm.propertyNames->speciesSymbol.impl(), globalObject->speciesGetterSetter());
 
-    RELEASE_ASSERT(constructorCondition.isWatchable());
-    RELEASE_ASSERT(speciesCondition.isWatchable());
+    if (!constructorCondition.isWatchable() || !speciesCondition.isWatchable())
+        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
 
     m_constructorWatchpoint = std::make_unique<ArrayPrototypeAdaptiveInferredPropertyWatchpoint>(constructorCondition, this);
     m_constructorWatchpoint->install();
 
     m_constructorSpeciesWatchpoint = std::make_unique<ArrayPrototypeAdaptiveInferredPropertyWatchpoint>(speciesCondition, this);
     m_constructorSpeciesWatchpoint->install();
+
+    return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Initialized;
 }
 
 ArrayPrototypeAdaptiveInferredPropertyWatchpoint::ArrayPrototypeAdaptiveInferredPropertyWatchpoint(const ObjectPropertyCondition& key, ArrayPrototype* prototype)
@@ -1406,8 +1418,7 @@ void ArrayPrototypeAdaptiveInferredPropertyWatchpoint::handleFire(const FireDeta
     if (verbose)
         WTF::dataLog(stringDetail, "\n");
 
-    JSGlobalObject* globalObject = m_arrayPrototype->globalObject();
-    globalObject->arraySpeciesWatchpoint().fireAll(globalObject->vm(), stringDetail);
+    m_arrayPrototype->m_speciesWatchpointStatus = ArrayPrototype::SpeciesWatchpointStatus::Fired;
 }
 
 } // namespace JSC
index 7e4d89f..f7b8432 100644 (file)
@@ -49,7 +49,8 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
     }
 
-    void initializeSpeciesWatchpoint(ExecState*);
+    SpeciesWatchpointStatus speciesWatchpointStatus() const { return m_speciesWatchpointStatus; }
+    SpeciesWatchpointStatus attemptToInitializeSpeciesWatchpoint(ExecState*);
 
     static const bool needsDestruction = false;
     // We don't need destruction since we use a finalizer.
@@ -63,6 +64,7 @@ private:
     friend ArrayPrototypeAdaptiveInferredPropertyWatchpoint;
     std::unique_ptr<ArrayPrototypeAdaptiveInferredPropertyWatchpoint> m_constructorWatchpoint;
     std::unique_ptr<ArrayPrototypeAdaptiveInferredPropertyWatchpoint> m_constructorSpeciesWatchpoint;
+    SpeciesWatchpointStatus m_speciesWatchpointStatus { SpeciesWatchpointStatus::Uninitialized };
 };
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*);
index adae5ef..e4f216a 100644 (file)
@@ -40,7 +40,6 @@ enum JS_EXPORT_PRIVATE Intrinsic {
     TanIntrinsic,
     ArrayPushIntrinsic,
     ArrayPopIntrinsic,
-    ArraySliceIntrinsic,
     CharCodeAtIntrinsic,
     CharAtIntrinsic,
     FromCharCodeIntrinsic,
index c005d80..a70ecf4 100644 (file)
@@ -332,7 +332,6 @@ JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectM
     , m_varInjectionWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
     , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
     , m_arrayIteratorProtocolWatchpoint(IsWatched)
-    , m_arraySpeciesWatchpoint(IsWatched)
     , m_templateRegistry(vm)
     , m_evalEnabled(true)
     , m_runtimeFlags()
@@ -945,8 +944,6 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
             m_arrayPrototypeSymbolIteratorWatchpoint = std::make_unique<ArrayIteratorAdaptiveWatchpoint>(condition, this);
             m_arrayPrototypeSymbolIteratorWatchpoint->install();
         }
-
-        this->arrayPrototype()->initializeSpeciesWatchpoint(exec);
     }
 
     resetPrototype(vm, getPrototypeDirect());
index 42f0409..b423c49 100644 (file)
@@ -399,11 +399,9 @@ public:
     WeakRandom m_weakRandom;
 
     InlineWatchpointSet& arrayIteratorProtocolWatchpoint() { return m_arrayIteratorProtocolWatchpoint; }
-    InlineWatchpointSet& arraySpeciesWatchpoint() { return m_arraySpeciesWatchpoint; }
     // If this hasn't been invalidated, it means the array iterator protocol
     // is not observable to user code yet.
     InlineWatchpointSet m_arrayIteratorProtocolWatchpoint;
-    InlineWatchpointSet m_arraySpeciesWatchpoint;
     std::unique_ptr<ArrayIteratorAdaptiveWatchpoint> m_arrayPrototypeSymbolIteratorWatchpoint;
     std::unique_ptr<ArrayIteratorAdaptiveWatchpoint> m_arrayIteratorPrototypeNext;