[BigInt] Add ValueSub into DFG
authorticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2018 13:55:32 +0000 (13:55 +0000)
committerticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2018 13:55:32 +0000 (13:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=186176

Reviewed by Yusuke Suzuki.

JSTests:

* stress/big-int-subtraction-jit.js:
* stress/value-sub-big-int-prediction-propagation.js: Added.
* stress/value-sub-big-int-untyped.js: Added.
* stress/value-sub-spec-none-case.js: Added.

Source/JavaScriptCore:

We are introducing in this patch a new node called ValueSub. This node
is necessary due to introduction of BigInt, making subtraction
operations result in non-Number values in some cases. In such case, ValueSub is
responsible to handle Untyped and BigInt operations.
In addition, we are also creating a speculative path when both
operands are BigInt. According to a simple BigInt subtraction microbenchmark,
this represents a speedup of ~1.2x faster.

big-int-simple-sub    14.6427+-0.5652    ^    11.9559+-0.6485   ^   definitely 1.2247x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::addSpeculationMode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileValueSub):
(JSC::DFG::SpeculativeJIT::compileArithSub):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValidate.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileValueSub):

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

24 files changed:
JSTests/ChangeLog
JSTests/stress/big-int-subtraction-jit.js
JSTests/stress/value-sub-big-int-prediction-propagation.js [new file with mode: 0644]
JSTests/stress/value-sub-big-int-untyped.js [new file with mode: 0644]
JSTests/stress/value-sub-spec-none-case.js [new file with mode: 0644]
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/DFGGraph.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.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/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

index 7386e23..0ee3965 100644 (file)
@@ -1,3 +1,15 @@
+2018-10-19  Caio Lima  <ticaiolima@gmail.com>
+
+        [BigInt] Add ValueSub into DFG
+        https://bugs.webkit.org/show_bug.cgi?id=186176
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/big-int-subtraction-jit.js:
+        * stress/value-sub-big-int-prediction-propagation.js: Added.
+        * stress/value-sub-big-int-untyped.js: Added.
+        * stress/value-sub-spec-none-case.js: Added.
+
 2018-10-18  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
 
         [JSC] JSC should have "parseFunction" to optimize Function constructor
index cb081aa..2e1f6ae 100644 (file)
@@ -8,12 +8,12 @@ let assert = {
 }
 
 function bigIntAddition(x, y) {
-    return x - y;
+    return x - y - 1n;
 }
 noInline(bigIntAddition);
 
 for (let i = 0; i < 10000; i++) {
     let r = bigIntAddition(3n, 10n);
-    assert.sameValue(r, -7n, 3n + " - " + 10n + " = " + r);
+    assert.sameValue(r, -8n, 3n + " - " + 10n + " - 1 = " + r);
 }
 
diff --git a/JSTests/stress/value-sub-big-int-prediction-propagation.js b/JSTests/stress/value-sub-big-int-prediction-propagation.js
new file mode 100644 (file)
index 0000000..44cbb28
--- /dev/null
@@ -0,0 +1,18 @@
+//@ runBigIntEnabled
+
+function assert(v, e) {
+    if (v !== e)
+        throw new Error("Expected value: " + e + " but got: " + v)
+}
+
+function bigIntPropagation(a, b) {
+    let c = a - b;
+    return c - 0n;
+}
+noInline(bigIntPropagation);
+
+for (let i = 0; i < 100000; i++) {
+    let out = bigIntPropagation(0xffffffffffffffffffffffffffffffn, 0x1n);
+    assert(out, 0xfffffffffffffffffffffffffffffen)
+}
+
diff --git a/JSTests/stress/value-sub-big-int-untyped.js b/JSTests/stress/value-sub-big-int-untyped.js
new file mode 100644 (file)
index 0000000..8c3f7ff
--- /dev/null
@@ -0,0 +1,26 @@
+//@ runBigIntEnabled
+
+function assert(v, e) {
+    if (v !== e)
+        throw new Error("Expected value: " + e + " but got: " + v)
+}
+
+function bigIntOperations(a, b) {
+    let c = a - b;
+    return a - c;
+}
+noInline(bigIntOperations);
+
+c = 0;
+let o = { valueOf: function () {
+    c++;
+    return 0b1111n;
+}};
+
+for (let i = 0; i < 100000; i++) {
+    let out = bigIntOperations(o, 0b1010n);
+    assert(out, 10n);
+}
+
+assert(c, 200000);
+
diff --git a/JSTests/stress/value-sub-spec-none-case.js b/JSTests/stress/value-sub-spec-none-case.js
new file mode 100644 (file)
index 0000000..2472cef
--- /dev/null
@@ -0,0 +1,22 @@
+function assert(a, e) {
+    if (a !== e)
+        throw new Error("Bad");
+}
+
+function valueSub() {
+    let sum = 0;
+    do {
+        // We trigger the JIT compilation of valueSub
+        // so Date.now() will have SpecNone as result
+        for (let i = 0; i < 10000; i++)
+            sum++;
+
+        sum += 0.5;
+    } while (Date.now() - sum  < 0);
+
+    assert(sum, 10000.5);
+}
+noInline(valueSub);
+
+valueSub();
+
index e1989bd..b166c2e 100644 (file)
@@ -1,3 +1,54 @@
+2018-10-19  Caio Lima  <ticaiolima@gmail.com>
+
+        [BigInt] Add ValueSub into DFG
+        https://bugs.webkit.org/show_bug.cgi?id=186176
+
+        Reviewed by Yusuke Suzuki.
+
+        We are introducing in this patch a new node called ValueSub. This node
+        is necessary due to introduction of BigInt, making subtraction
+        operations result in non-Number values in some cases. In such case, ValueSub is
+        responsible to handle Untyped and BigInt operations.
+        In addition, we are also creating a speculative path when both
+        operands are BigInt. According to a simple BigInt subtraction microbenchmark,
+        this represents a speedup of ~1.2x faster.
+
+        big-int-simple-sub    14.6427+-0.5652    ^    11.9559+-0.6485   ^   definitely 1.2247x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::addSpeculationMode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileValueSub):
+        (JSC::DFG::SpeculativeJIT::compileArithSub):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGValidate.cpp:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
+        (JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
+
 2018-10-18  Alexey Proskuryakov  <ap@apple.com>
 
         Switch from PLATFORM(IOS) to PLATFORM(IOS_FAMILY)
index 0659108..2fa280f 100644 (file)
@@ -589,11 +589,15 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         forNode(node).fixTypeForRepresentation(m_graph, node);
         break;
     }
-        
+
+    case ValueSub:
     case ValueAdd: {
-        ASSERT(node->binaryUseKind() == UntypedUse);
+        DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == BigIntUse);
         clobberWorld();
-        setTypeForNode(node, SpecString | SpecBytecodeNumber);
+        if (node->binaryUseKind() == BigIntUse)
+            setTypeForNode(node, SpecBigInt);
+        else
+            setTypeForNode(node, SpecString | SpecBytecodeNumber | SpecBigInt);
         break;
     }
 
index a819d83..568569e 100644 (file)
@@ -4933,7 +4933,10 @@ void ByteCodeParser::parseBlock(unsigned limit)
         case op_sub: {
             Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
             Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
-            set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithSub, op1, op2)));
+            if (op1->hasNumberResult() && op2->hasNumberResult())
+                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithSub, op1, op2)));
+            else
+                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ValueSub, op1, op2)));
             NEXT_OPCODE(op_sub);
         }
 
index c5ba734..4557d43 100644 (file)
@@ -639,6 +639,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case ValueBitOr:
     case ValueNegate:
     case ValueAdd:
+    case ValueSub:
     case SetFunctionName:
     case GetDynamicVar:
     case PutDynamicVar:
index 5ad8bdd..e9a72c8 100644 (file)
@@ -99,6 +99,7 @@ bool doesGC(Graph& graph, Node* node)
     case ValueBitAnd:
     case ValueBitOr:
     case ValueAdd:
+    case ValueSub:
     case ValueNegate:
     case TryGetById:
     case GetById:
index 7f36e78..91a26dd 100644 (file)
@@ -98,7 +98,38 @@ private:
             // This gets handled by fixupGetAndSetLocalsInBlock().
             return;
         }
+
+        case ValueSub: {
+            Edge& child1 = node->child1();
+            Edge& child2 = node->child2();
+
+            if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
+                fixEdge<BigIntUse>(child1);
+                fixEdge<BigIntUse>(child2);
+                break; 
+            }
             
+            if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
+                fixEdge<UntypedUse>(child1);
+                fixEdge<UntypedUse>(child2);
+                break;
+            }
+
+            if (attemptToMakeIntegerAdd(node)) {
+                // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
+                // https://bugs.webkit.org/show_bug.cgi?id=190607
+                node->setOp(ArithSub);
+                break;
+            }
+
+            fixDoubleOrBooleanEdge(node->child1());
+            fixDoubleOrBooleanEdge(node->child2());
+            node->setOp(ArithSub);
+            node->setResult(NodeResultDouble);
+
+            break;
+        }
+
         case ValueBitOr:
         case ValueBitAnd: {
             if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
@@ -293,13 +324,8 @@ private:
             
         case ArithAdd:
         case ArithSub: {
-            if (op == ArithSub
-                && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
-                fixEdge<UntypedUse>(node->child1());
-                fixEdge<UntypedUse>(node->child2());
-                node->setResult(NodeResultJS);
-                break;
-            }
+            // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
+            // https://bugs.webkit.org/show_bug.cgi?id=190607
             if (attemptToMakeIntegerAdd(node))
                 break;
             fixDoubleOrBooleanEdge(node->child1());
index 2a09c0f..e5b1e2a 100644 (file)
@@ -238,7 +238,7 @@ public:
 
     AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
     {
-        ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
+        ASSERT(add->op() == ValueAdd || add->op() == ValueSub || add->op() == ArithAdd || add->op() == ArithSub);
         
         RareCaseProfilingSource source = add->sourceFor(pass);
         
index a9689b2..954b1a1 100644 (file)
@@ -171,6 +171,8 @@ namespace JSC { namespace DFG {
     /* Add of values may either be arithmetic, or result in string concatenation. */\
     macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
     \
+    macro(ValueSub, NodeResultJS | NodeMustGenerate) \
+    \
     /* Add of values that always convers its inputs to strings. May have two or three kids. */\
     macro(StrCat, NodeResultJS | NodeMustGenerate) \
     \
index a24c30b..d30483b 100644 (file)
@@ -1286,6 +1286,17 @@ size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject*
     RELEASE_AND_RETURN(scope, regexp->test(exec, globalObject, input));
 }
 
+JSCell* JIT_OPERATION operationSubBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
+{
+    VM* vm = &exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    
+    JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
+    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
+    
+    return JSBigInt::sub(*vm, leftOperand, rightOperand);
+}
+
 JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
 {
     VM* vm = &exec->vm();
index da6d2ed..2a294a7 100644 (file)
@@ -163,6 +163,7 @@ size_t JIT_OPERATION operationRegExpTestString(ExecState*, JSGlobalObject*, RegE
 size_t JIT_OPERATION operationRegExpTest(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 size_t JIT_OPERATION operationSameValue(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
index aedf226..0d71293 100644 (file)
@@ -246,6 +246,33 @@ private:
             break;
         }
 
+        case ValueSub: {
+            SpeculatedType left = node->child1()->prediction();
+            SpeculatedType right = node->child2()->prediction();
+
+            if (left && right) {
+                if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
+                    && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
+                    if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
+                        changed |= mergePrediction(SpecInt32Only);
+                    else if (m_graph.addShouldSpeculateAnyInt(node))
+                        changed |= mergePrediction(SpecInt52Only);
+                    else
+                        changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
+                } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
+                    changed |= mergePrediction(SpecBigInt);
+                else {
+                    changed |= mergePrediction(SpecInt32Only);
+                    if (node->mayHaveDoubleResult())
+                        changed |= mergePrediction(SpecBytecodeDouble);
+                    if (node->mayHaveNonNumberResult())
+                        changed |= mergePrediction(SpecBigInt);
+                }
+            }
+
+            break;
+        }
+
         case ValueBitOr:
         case ValueBitAnd: {
             if (node->child1()->shouldSpeculateBigInt() && node->child2()->shouldSpeculateBigInt())
@@ -521,6 +548,7 @@ private:
         
         switch (node->op()) {
         case ValueAdd:
+        case ValueSub:
         case ArithAdd:
         case ArithSub: {
             SpeculatedType left = node->child1()->prediction();
@@ -1068,6 +1096,7 @@ private:
         case ValueBitAnd:
         case ValueNegate:
         case ValueAdd:
+        case ValueSub:
         case ArithAdd:
         case ArithSub:
         case ArithNegate:
index 91bbd59..bcd09e5 100644 (file)
@@ -230,6 +230,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case ValueBitOr:
     case ValueNegate:
     case ValueAdd:
+    case ValueSub:
     case TryGetById:
     case DeleteById:
     case DeleteByVal:
index 8286632..3b8c832 100644 (file)
@@ -3871,6 +3871,51 @@ void SpeculativeJIT::compileValueAdd(Node* node)
     compileMathIC(node, addIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
 }
 
+void SpeculativeJIT::compileValueSub(Node* node)
+{
+    Edge& leftChild = node->child1();
+    Edge& rightChild = node->child2();
+
+    if (node->binaryUseKind() == UntypedUse) {
+#if USE(JSVALUE64)
+        bool needsScratchGPRReg = true;
+        bool needsScratchFPRReg = false;
+#else
+        bool needsScratchGPRReg = true;
+        bool needsScratchFPRReg = true;
+#endif
+
+        CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
+        ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
+        Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex];
+        JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile, instruction);
+        auto repatchingFunction = operationValueSubOptimize;
+        auto nonRepatchingFunction = operationValueSub;
+
+        compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
+        return;
+    }
+
+    ASSERT(leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse);
+
+    SpeculateCellOperand left(this, node->child1());
+    SpeculateCellOperand right(this, node->child2());
+    GPRReg leftGPR = left.gpr();
+    GPRReg rightGPR = right.gpr();
+
+    speculateBigInt(leftChild, leftGPR);
+    speculateBigInt(rightChild, rightGPR);
+
+    flushRegisters();
+    GPRFlushedCallResult result(this);
+    GPRReg resultGPR = result.gpr();
+
+    callOperation(operationSubBigInt, resultGPR, leftGPR, rightGPR);
+
+    m_jit.exceptionCheck();
+    cellResult(resultGPR, node);
+}
+
 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
 void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
 {
@@ -4506,26 +4551,6 @@ void SpeculativeJIT::compileArithSub(Node* node)
         return;
     }
 
-    case UntypedUse: {
-#if USE(JSVALUE64)
-        bool needsScratchGPRReg = true;
-        bool needsScratchFPRReg = false;
-#else
-        bool needsScratchGPRReg = true;
-        bool needsScratchFPRReg = true;
-#endif
-
-        CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
-        ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
-        Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex];
-        JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile, instruction);
-        auto repatchingFunction = operationValueSubOptimize;
-        auto nonRepatchingFunction = operationValueSub;
-        
-        compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
-        return;
-    }
-
     default:
         RELEASE_ASSERT_NOT_REACHED();
         return;
index 0dfd314..f3753d3 100644 (file)
@@ -1344,6 +1344,7 @@ public:
 
     void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
     void compileValueAdd(Node*);
+    void compileValueSub(Node*);
     void compileArithAdd(Node*);
     void compileMakeRope(Node*);
     void compileArithAbs(Node*);
index 34ac1b1..f0f620d 100644 (file)
@@ -2029,6 +2029,10 @@ void SpeculativeJIT::compile(Node* node)
         compileValueAdd(node);
         break;
 
+    case ValueSub:
+        compileValueSub(node);
+        break;
+
     case StrCat: {
         compileStrCat(node);
         break;
index 2c7db12..de9728e 100644 (file)
@@ -2171,6 +2171,10 @@ void SpeculativeJIT::compile(Node* node)
         compileValueAdd(node);
         break;
 
+    case ValueSub:
+        compileValueSub(node);
+        break;
+
     case StrCat: {
         compileStrCat(node);
         break;
index 20cf75c..5382f8a 100644 (file)
@@ -254,6 +254,7 @@ public:
                     break;
                 case MakeRope:
                 case ValueAdd:
+                case ValueSub:
                 case ArithAdd:
                 case ArithSub:
                 case ArithMul:
index a644444..174e59a 100644 (file)
@@ -90,6 +90,7 @@ inline CapabilityLevel canCompile(Node* node)
     case ValueBitOr:
     case ValueNegate:
     case ValueAdd:
+    case ValueSub:
     case StrCat:
     case ArithAdd:
     case ArithClz32:
index 5f04663..09d7bef 100644 (file)
@@ -593,6 +593,9 @@ private:
         case ValueAdd:
             compileValueAdd();
             break;
+        case ValueSub:
+            compileValueSub();
+            break;
         case StrCat:
             compileStrCat();
             break;
@@ -1865,6 +1868,25 @@ private:
         compileBinaryMathIC<JITAddGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction);
     }
 
+    void compileValueSub()
+    {
+        if (m_node->isBinaryUseKind(BigIntUse)) {
+            LValue left = lowBigInt(m_node->child1());
+            LValue right = lowBigInt(m_node->child2());
+            
+            LValue result = vmCall(pointerType(), m_out.operation(operationSubBigInt), m_callFrame, left, right);
+            setJSValue(result);
+            return;
+        }
+
+        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
+        ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
+        Instruction* instruction = &baselineCodeBlock->instructions()[m_node->origin.semantic.bytecodeIndex];
+        auto repatchingFunction = operationValueSubOptimize;
+        auto nonRepatchingFunction = operationValueSub;
+        compileBinaryMathIC<JITSubGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction);
+    }
+
     template <typename Generator, typename Func1, typename Func2,
         typename = std::enable_if_t<std::is_function<typename std::remove_pointer<Func1>::type>::value && std::is_function<typename std::remove_pointer<Func2>::type>::value>>
     void compileUnaryMathIC(ArithProfile* arithProfile, Instruction* instruction, Func1 repatchingFunction, Func2 nonRepatchingFunction)