Changeset 237242 in webkit


Ignore:
Timestamp:
Oct 17, 2018 6:14:00 PM (5 years ago)
Author:
Caio Lima
Message:

[BigInt] Add ValueSub into DFG
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.

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

Location:
trunk
Files:
2 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r237200 r237242  
     12018-10-17  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [BigInt] Add ValueSub into DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=186176
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * stress/big-int-subtraction-jit.js:
     9        * stress/value-sub-big-int-prediction-propagation.js: Added.
     10        * stress/value-sub-big-int-untyped.js: Added.
     11
    1122018-10-16  Dominik Infuehr  <dinfuehr@igalia.com>
    213
  • trunk/JSTests/stress/big-int-subtraction-jit.js

    r232449 r237242  
    99
    1010function bigIntAddition(x, y) {
    11     return x - y;
     11    return x - y - 1n;
    1212}
    1313noInline(bigIntAddition);
     
    1515for (let i = 0; i < 10000; i++) {
    1616    let r = bigIntAddition(3n, 10n);
    17     assert.sameValue(r, -7n, 3n + " - " + 10n + " = " + r);
     17    assert.sameValue(r, -8n, 3n + " - " + 10n + " - 1 = " + r);
    1818}
    1919
  • trunk/Source/JavaScriptCore/ChangeLog

    r237241 r237242  
     12018-10-17  Caio Lima  <ticaiolima@gmail.com>
     2
     3        [BigInt] Add ValueSub into DFG
     4        https://bugs.webkit.org/show_bug.cgi?id=186176
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        We are introducing in this patch a new node called ValueSub. This node
     9        is necessary due to introduction of BigInt, making subtraction
     10        operations result in non-Number values in some cases. In such case, ValueSub is
     11        responsible to handle Untyped and BigInt operations.
     12        In addition, we are also creating a speculative path when both
     13        operands are BigInt. According to a simple BigInt subtraction microbenchmark,
     14        this represents a speedup of ~1.2x faster.
     15
     16        big-int-simple-sub    14.6427+-0.5652    ^    11.9559+-0.6485   ^   definitely 1.2247x faster
     17
     18        * dfg/DFGAbstractInterpreterInlines.h:
     19        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     20        * dfg/DFGByteCodeParser.cpp:
     21        (JSC::DFG::ByteCodeParser::parseBlock):
     22        * dfg/DFGClobberize.h:
     23        (JSC::DFG::clobberize):
     24        * dfg/DFGDoesGC.cpp:
     25        (JSC::DFG::doesGC):
     26        * dfg/DFGFixupPhase.cpp:
     27        (JSC::DFG::FixupPhase::fixupNode):
     28        * dfg/DFGGraph.h:
     29        (JSC::DFG::Graph::addSpeculationMode):
     30        * dfg/DFGNodeType.h:
     31        * dfg/DFGOperations.cpp:
     32        * dfg/DFGOperations.h:
     33        * dfg/DFGPredictionPropagationPhase.cpp:
     34        * dfg/DFGSafeToExecute.h:
     35        (JSC::DFG::safeToExecute):
     36        * dfg/DFGSpeculativeJIT.cpp:
     37        (JSC::DFG::SpeculativeJIT::compileValueSub):
     38        (JSC::DFG::SpeculativeJIT::compileArithSub):
     39        * dfg/DFGSpeculativeJIT.h:
     40        * dfg/DFGSpeculativeJIT32_64.cpp:
     41        (JSC::DFG::SpeculativeJIT::compile):
     42        * dfg/DFGSpeculativeJIT64.cpp:
     43        (JSC::DFG::SpeculativeJIT::compile):
     44        * dfg/DFGValidate.cpp:
     45        * ftl/FTLCapabilities.cpp:
     46        (JSC::FTL::canCompile):
     47        * ftl/FTLLowerDFGToB3.cpp:
     48        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     49        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
     50        (JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
     51
    1522018-10-17  Mark Lam  <mark.lam@apple.com>
    253
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r236901 r237242  
    590590        break;
    591591    }
    592        
     592
     593    case ValueSub:
    593594    case ValueAdd: {
    594         ASSERT(node->binaryUseKind() == UntypedUse);
     595        DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == BigIntUse);
    595596        clobberWorld();
    596         setTypeForNode(node, SpecString | SpecBytecodeNumber);
     597        if (node->binaryUseKind() == BigIntUse)
     598            setTypeForNode(node, SpecBigInt);
     599        else
     600            setTypeForNode(node, SpecString | SpecBytecodeNumber | SpecBigInt);
    597601        break;
    598602    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r236901 r237242  
    49344934            Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand));
    49354935            Node* op2 = get(VirtualRegister(currentInstruction[3].u.operand));
    4936             set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithSub, op1, op2)));
     4936            if (op1->hasNumberResult() && op2->hasNumberResult())
     4937                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithSub, op1, op2)));
     4938            else
     4939                set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ValueSub, op1, op2)));
    49374940            NEXT_OPCODE(op_sub);
    49384941        }
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r236901 r237242  
    640640    case ValueNegate:
    641641    case ValueAdd:
     642    case ValueSub:
    642643    case SetFunctionName:
    643644    case GetDynamicVar:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r237215 r237242  
    100100    case ValueBitOr:
    101101    case ValueAdd:
     102    case ValueSub:
    102103    case ValueNegate:
    103104    case TryGetById:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r236901 r237242  
    9999            return;
    100100        }
    101            
     101
     102        case ValueSub: {
     103            Edge& child1 = node->child1();
     104            Edge& child2 = node->child2();
     105
     106            if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
     107                fixEdge<BigIntUse>(child1);
     108                fixEdge<BigIntUse>(child2);
     109                break;
     110            }
     111           
     112            if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
     113                fixEdge<UntypedUse>(child1);
     114                fixEdge<UntypedUse>(child2);
     115                break;
     116            }
     117
     118            if (attemptToMakeIntegerAdd(node)) {
     119                // FIXME: [DFG] Clear ArithSub when ArithMode is Unchecked
     120                // https://bugs.webkit.org/show_bug.cgi?id=190607
     121                node->setOp(ArithSub);
     122                break;
     123            }
     124
     125            DFG_ASSERT(m_graph, node, Node::shouldSpeculateNumberOrBooleanExpectingDefined(child1.node(), child2.node()));
     126            fixDoubleOrBooleanEdge(node->child1());
     127            fixDoubleOrBooleanEdge(node->child2());
     128            node->setOp(ArithSub);
     129            node->setResult(NodeResultDouble);
     130
     131            break;
     132        }
     133
    102134        case ValueBitOr:
    103135        case ValueBitAnd: {
     
    294326        case ArithAdd:
    295327        case ArithSub: {
    296             if (op == ArithSub
    297                 && Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
    298                 fixEdge<UntypedUse>(node->child1());
    299                 fixEdge<UntypedUse>(node->child2());
    300                 node->setResult(NodeResultJS);
    301                 break;
    302             }
     328            // FIXME: [DFG] Clear ArithSub when ArithMode is Unchecked
     329            // https://bugs.webkit.org/show_bug.cgi?id=190607
    303330            if (attemptToMakeIntegerAdd(node))
    304331                break;
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r234178 r237242  
    239239    AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
    240240    {
    241         ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
     241        ASSERT(add->op() == ValueAdd || add->op() == ValueSub || add->op() == ArithAdd || add->op() == ArithSub);
    242242       
    243243        RareCaseProfilingSource source = add->sourceFor(pass);
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r236901 r237242  
    171171    /* Add of values may either be arithmetic, or result in string concatenation. */\
    172172    macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
     173    \
     174    macro(ValueSub, NodeResultJS | NodeMustGenerate) \
    173175    \
    174176    /* Add of values that always convers its inputs to strings. May have two or three kids. */\
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r236901 r237242  
    12871287}
    12881288
     1289JSCell* JIT_OPERATION operationSubBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
     1290{
     1291    VM* vm = &exec->vm();
     1292    NativeCallFrameTracer tracer(vm, exec);
     1293   
     1294    JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
     1295    JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
     1296   
     1297    return JSBigInt::sub(*vm, leftOperand, rightOperand);
     1298}
     1299
    12891300JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
    12901301{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r236901 r237242  
    164164size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
    165165size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
     166JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
    166167JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
    167168JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r236901 r237242  
    244244                    changed |= mergePrediction(SpecInt32Only);
    245245            }
     246            break;
     247        }
     248
     249        case ValueSub: {
     250            SpeculatedType left = node->child1()->prediction();
     251            SpeculatedType right = node->child2()->prediction();
     252
     253            if (left && right) {
     254                if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
     255                    && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
     256                    if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
     257                        changed |= mergePrediction(SpecInt32Only);
     258                    else if (m_graph.addShouldSpeculateAnyInt(node))
     259                        changed |= mergePrediction(SpecInt52Only);
     260                    else
     261                        changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
     262                } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
     263                    changed |= mergePrediction(SpecBigInt);
     264                else {
     265                    changed |= mergePrediction(SpecInt32Only);
     266                    if (node->mayHaveDoubleResult())
     267                        changed |= mergePrediction(SpecBytecodeDouble);
     268                    if (node->mayHaveNonNumberResult())
     269                        changed |= mergePrediction(SpecBigInt);
     270                }
     271            }
     272
    246273            break;
    247274        }
     
    522549        switch (node->op()) {
    523550        case ValueAdd:
     551        case ValueSub:
    524552        case ArithAdd:
    525553        case ArithSub: {
     
    10691097        case ValueNegate:
    10701098        case ValueAdd:
     1099        case ValueSub:
    10711100        case ArithAdd:
    10721101        case ArithSub:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r236901 r237242  
    231231    case ValueNegate:
    232232    case ValueAdd:
     233    case ValueSub:
    233234    case TryGetById:
    234235    case DeleteById:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r237136 r237242  
    38723872}
    38733873
     3874void SpeculativeJIT::compileValueSub(Node* node)
     3875{
     3876    Edge& leftChild = node->child1();
     3877    Edge& rightChild = node->child2();
     3878
     3879    if (node->binaryUseKind() == UntypedUse) {
     3880#if USE(JSVALUE64)
     3881        bool needsScratchGPRReg = true;
     3882        bool needsScratchFPRReg = false;
     3883#else
     3884        bool needsScratchGPRReg = true;
     3885        bool needsScratchFPRReg = true;
     3886#endif
     3887
     3888        CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
     3889        ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
     3890        Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex];
     3891        JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile, instruction);
     3892        auto repatchingFunction = operationValueSubOptimize;
     3893        auto nonRepatchingFunction = operationValueSub;
     3894
     3895        compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
     3896        return;
     3897    }
     3898
     3899    ASSERT(leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse);
     3900
     3901    SpeculateCellOperand left(this, node->child1());
     3902    SpeculateCellOperand right(this, node->child2());
     3903    GPRReg leftGPR = left.gpr();
     3904    GPRReg rightGPR = right.gpr();
     3905
     3906    speculateBigInt(leftChild, leftGPR);
     3907    speculateBigInt(rightChild, rightGPR);
     3908
     3909    flushRegisters();
     3910    GPRFlushedCallResult result(this);
     3911    GPRReg resultGPR = result.gpr();
     3912
     3913    callOperation(operationSubBigInt, resultGPR, leftGPR, rightGPR);
     3914
     3915    m_jit.exceptionCheck();
     3916    cellResult(resultGPR, node);
     3917}
     3918
    38743919template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
    38753920void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
     
    45044549
    45054550        doubleResult(result.fpr(), node);
    4506         return;
    4507     }
    4508 
    4509     case UntypedUse: {
    4510 #if USE(JSVALUE64)
    4511         bool needsScratchGPRReg = true;
    4512         bool needsScratchFPRReg = false;
    4513 #else
    4514         bool needsScratchGPRReg = true;
    4515         bool needsScratchFPRReg = true;
    4516 #endif
    4517 
    4518         CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
    4519         ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
    4520         Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex];
    4521         JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile, instruction);
    4522         auto repatchingFunction = operationValueSubOptimize;
    4523         auto nonRepatchingFunction = operationValueSub;
    4524        
    4525         compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
    45264551        return;
    45274552    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r236901 r237242  
    13451345    void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
    13461346    void compileValueAdd(Node*);
     1347    void compileValueSub(Node*);
    13471348    void compileArithAdd(Node*);
    13481349    void compileMakeRope(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r236901 r237242  
    20282028    case ValueAdd:
    20292029        compileValueAdd(node);
     2030        break;
     2031
     2032    case ValueSub:
     2033        compileValueSub(node);
    20302034        break;
    20312035
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r237173 r237242  
    21702170    case ValueAdd:
    21712171        compileValueAdd(node);
     2172        break;
     2173
     2174    case ValueSub:
     2175        compileValueSub(node);
    21722176        break;
    21732177
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r234082 r237242  
    255255                case MakeRope:
    256256                case ValueAdd:
     257                case ValueSub:
    257258                case ArithAdd:
    258259                case ArithSub:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r236901 r237242  
    9191    case ValueNegate:
    9292    case ValueAdd:
     93    case ValueSub:
    9394    case StrCat:
    9495    case ArithAdd:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r237173 r237242  
    594594            compileValueAdd();
    595595            break;
     596        case ValueSub:
     597            compileValueSub();
     598            break;
    596599        case StrCat:
    597600            compileStrCat();
     
    18641867        auto nonRepatchingFunction = operationValueAdd;
    18651868        compileBinaryMathIC<JITAddGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction);
     1869    }
     1870
     1871    void compileValueSub()
     1872    {
     1873        if (m_node->isBinaryUseKind(BigIntUse)) {
     1874            LValue left = lowBigInt(m_node->child1());
     1875            LValue right = lowBigInt(m_node->child2());
     1876           
     1877            LValue result = vmCall(pointerType(), m_out.operation(operationSubBigInt), m_callFrame, left, right);
     1878            setJSValue(result);
     1879            return;
     1880        }
     1881
     1882        CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic);
     1883        ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex);
     1884        Instruction* instruction = &baselineCodeBlock->instructions()[m_node->origin.semantic.bytecodeIndex];
     1885        auto repatchingFunction = operationValueSubOptimize;
     1886        auto nonRepatchingFunction = operationValueSub;
     1887        compileBinaryMathIC<JITSubGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction);
    18661888    }
    18671889
Note: See TracChangeset for help on using the changeset viewer.