Changeset 260730 in webkit


Ignore:
Timestamp:
Apr 26, 2020 2:11:50 PM (4 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] ValueAdd, VaueSub, ValueMul, Inc, Dec should say SpecBigInt32 prediction based on ArithProfile
https://bugs.webkit.org/show_bug.cgi?id=211038

Reviewed by Filip Pizlo.

JSTests:

  • stress/bigint32-add-overflow.js: Added.

(shouldBe):
(add):
(noInline):

  • stress/bigint32-dec-overflow.js: Added.

(shouldBe):
(dec):
(noInline):

  • stress/bigint32-inc-overflow.js: Added.

(shouldBe):
(inc):
(noInline):

  • stress/bigint32-mul-overflow.js: Added.

(shouldBe):
(mul):
(noInline):

  • stress/bigint32-sub-overflow.js: Added.

(shouldBe):
(sub):
(noInline):

Source/JavaScriptCore:

This patch adds profile feedback to ValueAdd, ValueSub, ValueMul, Inc, Dec to say SpecBigInt32 prediction.

Our HeapBigInt v.s. BigInt32 strategy is simpler than Double v.s. Int32 strategy: we always
prefer BigInt32 over HeapBigInt. This is because HeapBigInt calculation and conversion require
much higher cost than BigInt32. This tradeoff is largely different from Double v.s. Int32.
So keeping HeapBigInt is simply inefficient when we can use BigInt32.

This means that ArithProfile's feedback is also very simple. If we see HeapBigInt, this means
overflow happens. In DFG, we propagate this information to ValueAdd, ValueSub, and ValueMul nodes
and record it in DFGNodeFlags. And based on this information, we change the prediction and
speculation in prediction propagation and fixup phase.

We change exit reason from Overflow to BigInt32Overflow since Overflow is solely used for Int32 case,
and we have Int52Overflow for Int52 case. We should have BigInt32Overflow for BigInt32 to precisely
record and tell about what happens in DFG as a feedback for the next compilation.

We add BigInt32 speculation for ValueSub. Previously, we missed that in fixup phase and we always
speculate ValueSub with AnyBigIntUse or HeapBigIntUse. Now it can use BigInt32Use.

We also fix Inc / Dec's fixup phase to use BigInt path. Previously, it was always using UntypedUse since
node->child1()->shouldSpeculateUntypedForArithmetic() returns true for BigInt. We fix the ordering of
speculation attempts as it is done in the other places in fixup phase.

This patch offers 7.9% performance improvement in sunspider-sha1-big-int.

ToT Patched

sunspider-sha1-big-int 134.5668+-2.8695 124.6743+-0.7541 definitely 1.0793x faster

  • bytecode/ExitKind.cpp:

(JSC::exitKindToString):

  • bytecode/ExitKind.h:
  • bytecode/SpeculatedType.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::makeDivSafe):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::binaryArithShouldSpeculateBigInt32):
(JSC::DFG::Graph::unaryArithShouldSpeculateBigInt32):

  • dfg/DFGNode.h:

(JSC::DFG::Node::mayHaveBigInt32Result):
(JSC::DFG::Node::mayHaveHeapBigIntResult):
(JSC::DFG::Node::mayHaveBigIntResult):
(JSC::DFG::Node::canSpeculateBigInt32):
(JSC::DFG::Node::canSpeculateInt52):

  • dfg/DFGNodeFlags.cpp:

(JSC::DFG::dumpNodeFlags):

  • dfg/DFGNodeFlags.h:

(JSC::DFG::nodeMayHaveHeapBigInt):
(JSC::DFG::nodeCanSpeculateBigInt32):

  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileValueAdd):
(JSC::DFG::SpeculativeJIT::compileValueSub):
(JSC::DFG::SpeculativeJIT::compileValueMul):
(JSC::DFG::SpeculativeJIT::compileValueDiv):
(JSC::DFG::SpeculativeJIT::speculateHeapBigInt):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
(JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
(JSC::FTL::DFG::LowerDFGToB3::compileValueDiv):

Location:
trunk
Files:
5 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r260720 r260730  
     12020-04-26  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] ValueAdd, VaueSub, ValueMul, Inc, Dec should say SpecBigInt32 prediction based on ArithProfile
     4        https://bugs.webkit.org/show_bug.cgi?id=211038
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * stress/bigint32-add-overflow.js: Added.
     9        (shouldBe):
     10        (add):
     11        (noInline):
     12        * stress/bigint32-dec-overflow.js: Added.
     13        (shouldBe):
     14        (dec):
     15        (noInline):
     16        * stress/bigint32-inc-overflow.js: Added.
     17        (shouldBe):
     18        (inc):
     19        (noInline):
     20        * stress/bigint32-mul-overflow.js: Added.
     21        (shouldBe):
     22        (mul):
     23        (noInline):
     24        * stress/bigint32-sub-overflow.js: Added.
     25        (shouldBe):
     26        (sub):
     27        (noInline):
     28
    1292020-04-25  Yusuke Suzuki  <ysuzuki@apple.com>
    230
  • trunk/Source/JavaScriptCore/ChangeLog

    r260722 r260730  
     12020-04-26  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] ValueAdd, VaueSub, ValueMul, Inc, Dec should say SpecBigInt32 prediction based on ArithProfile
     4        https://bugs.webkit.org/show_bug.cgi?id=211038
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch adds profile feedback to ValueAdd, ValueSub, ValueMul, Inc, Dec to say SpecBigInt32 prediction.
     9
     10        Our HeapBigInt v.s. BigInt32 strategy is simpler than Double v.s. Int32 strategy: we always
     11        prefer BigInt32 over HeapBigInt. This is because HeapBigInt calculation and conversion require
     12        much higher cost than BigInt32. This tradeoff is largely different from Double v.s. Int32.
     13        So keeping HeapBigInt is simply inefficient when we can use BigInt32.
     14
     15        This means that ArithProfile's feedback is also very simple. If we see HeapBigInt, this means
     16        overflow happens. In DFG, we propagate this information to ValueAdd, ValueSub, and ValueMul nodes
     17        and record it in DFGNodeFlags. And based on this information, we change the prediction and
     18        speculation in prediction propagation and fixup phase.
     19
     20        We change exit reason from Overflow to BigInt32Overflow since Overflow is solely used for Int32 case,
     21        and we have Int52Overflow for Int52 case. We should have BigInt32Overflow for BigInt32 to precisely
     22        record and tell about what happens in DFG as a feedback for the next compilation.
     23
     24        We add BigInt32 speculation for ValueSub. Previously, we missed that in fixup phase and we always
     25        speculate ValueSub with AnyBigIntUse or HeapBigIntUse. Now it can use BigInt32Use.
     26
     27        We also fix Inc / Dec's fixup phase to use BigInt path. Previously, it was always using UntypedUse since
     28        `node->child1()->shouldSpeculateUntypedForArithmetic()` returns true for BigInt. We fix the ordering of
     29        speculation attempts as it is done in the other places in fixup phase.
     30
     31        This patch offers 7.9% performance improvement in sunspider-sha1-big-int.
     32
     33                                               ToT                     Patched
     34
     35            sunspider-sha1-big-int      134.5668+-2.8695     ^    124.6743+-0.7541        ^ definitely 1.0793x faster
     36
     37        * bytecode/ExitKind.cpp:
     38        (JSC::exitKindToString):
     39        * bytecode/ExitKind.h:
     40        * bytecode/SpeculatedType.h:
     41        * dfg/DFGAbstractInterpreterInlines.h:
     42        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     43        * dfg/DFGByteCodeParser.cpp:
     44        (JSC::DFG::ByteCodeParser::makeSafe):
     45        (JSC::DFG::ByteCodeParser::makeDivSafe):
     46        * dfg/DFGFixupPhase.cpp:
     47        (JSC::DFG::FixupPhase::fixupNode):
     48        * dfg/DFGGraph.h:
     49        (JSC::DFG::Graph::binaryArithShouldSpeculateBigInt32):
     50        (JSC::DFG::Graph::unaryArithShouldSpeculateBigInt32):
     51        * dfg/DFGNode.h:
     52        (JSC::DFG::Node::mayHaveBigInt32Result):
     53        (JSC::DFG::Node::mayHaveHeapBigIntResult):
     54        (JSC::DFG::Node::mayHaveBigIntResult):
     55        (JSC::DFG::Node::canSpeculateBigInt32):
     56        (JSC::DFG::Node::canSpeculateInt52):
     57        * dfg/DFGNodeFlags.cpp:
     58        (JSC::DFG::dumpNodeFlags):
     59        * dfg/DFGNodeFlags.h:
     60        (JSC::DFG::nodeMayHaveHeapBigInt):
     61        (JSC::DFG::nodeCanSpeculateBigInt32):
     62        * dfg/DFGPredictionPropagationPhase.cpp:
     63        * dfg/DFGSpeculativeJIT.cpp:
     64        (JSC::DFG::SpeculativeJIT::compileValueAdd):
     65        (JSC::DFG::SpeculativeJIT::compileValueSub):
     66        (JSC::DFG::SpeculativeJIT::compileValueMul):
     67        (JSC::DFG::SpeculativeJIT::compileValueDiv):
     68        (JSC::DFG::SpeculativeJIT::speculateHeapBigInt):
     69        * ftl/FTLLowerDFGToB3.cpp:
     70        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
     71        (JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
     72        (JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
     73        (JSC::FTL::DFG::LowerDFGToB3::compileValueDiv):
     74
    1752020-04-25  Ross Kirsling  <ross.kirsling@sony.com>
    276
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r240114 r260730  
    8989    case GenericUnwind:
    9090        return "GenericUnwind";
     91    case BigInt32Overflow:
     92        return "BigInt32Overflow";
    9193    }
    9294    RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r252680 r260730  
    5656    ExceptionCheck, // We exited because a direct exception check showed that we threw an exception from a C call.
    5757    GenericUnwind, // We exited because we arrived at this OSR exit from genericUnwind.
     58    BigInt32Overflow, // We exited because of an BigInt32 overflow.
    5859};
    5960
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r260331 r260730  
    101101static constexpr SpeculatedType SpecHeapBigInt                        = 1ull << 41; // It's definitely a BigInt that is allocated on the heap
    102102static constexpr SpeculatedType SpecBigInt32                          = 1ull << 42; // It's definitely a small BigInt that is inline the JSValue
     103#if USE(BIGINT32)
    103104static constexpr SpeculatedType SpecBigInt                            = SpecBigInt32 | SpecHeapBigInt;
     105#else
     106// We should not include SpecBigInt32. We are using SpecBigInt in various places like prediction. If this includes SpecBigInt32, fixup phase is confused if !USE(BIGINT32) since it is not using AnyBigIntUse.
     107static constexpr SpeculatedType SpecBigInt                            = SpecHeapBigInt;
     108#endif
    104109static constexpr SpeculatedType SpecDataViewObject                    = 1ull << 43; // It's definitely a JSDataView.
    105110static constexpr SpeculatedType SpecPrimitive                         = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r260683 r260730  
    767767            // https://bugs.webkit.org/show_bug.cgi?id=210982
    768768            setTypeForNode(node, SpecBigInt);
    769         } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
     769        } else if (node->isBinaryUseKind(AnyBigIntUse))
    770770            setTypeForNode(node, SpecBigInt);
     771        else if (node->isBinaryUseKind(BigInt32Use))
     772            setTypeForNode(node, SpecBigInt32);
    771773        else {
    772774            DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse);
     
    10571059            // https://bugs.webkit.org/show_bug.cgi?id=210982
    10581060            setTypeForNode(node, SpecBigInt);
    1059         } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
     1061        } else if (node->isBinaryUseKind(AnyBigIntUse))
    10601062            setTypeForNode(node, SpecBigInt);
     1063        else if (node->isBinaryUseKind(BigInt32Use))
     1064            setTypeForNode(node, SpecBigInt32);
    10611065        else {
    10621066            clobberWorld();
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r260585 r260730  
    10121012            if (observed.didObserveNonNumeric())
    10131013                node->mergeFlags(NodeMayHaveNonNumericResult);
    1014             if (observed.didObserveBigInt())
    1015                 node->mergeFlags(NodeMayHaveBigIntResult);
     1014            if (observed.didObserveBigInt32())
     1015                node->mergeFlags(NodeMayHaveBigInt32Result);
     1016            if (observed.didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
     1017                node->mergeFlags(NodeMayHaveHeapBigIntResult);
    10161018            break;
    10171019        }
     
    10311033            if (arithProfile->didObserveNonNumeric())
    10321034                node->mergeFlags(NodeMayHaveNonNumericResult);
    1033             if (arithProfile->didObserveBigInt())
    1034                 node->mergeFlags(NodeMayHaveBigIntResult);
     1035            if (arithProfile->didObserveBigInt32())
     1036                node->mergeFlags(NodeMayHaveBigInt32Result);
     1037            if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
     1038                node->mergeFlags(NodeMayHaveHeapBigIntResult);
    10351039            break;
    10361040        }
     
    10501054            if (arithProfile->didObserveNonNumeric())
    10511055                node->mergeFlags(NodeMayHaveNonNumericResult);
    1052             if (arithProfile->didObserveBigInt())
    1053                 node->mergeFlags(NodeMayHaveBigIntResult);
     1056            if (arithProfile->didObserveBigInt32())
     1057                node->mergeFlags(NodeMayHaveBigInt32Result);
     1058            if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
     1059                node->mergeFlags(NodeMayHaveHeapBigIntResult);
    10541060            break;
    10551061        }
     
    11001106
    11011107        BinaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->binaryArithProfileForBytecodeIndex(m_currentIndex);
    1102         if (arithProfile->didObserveBigInt())
    1103             node->mergeFlags(NodeMayHaveBigIntResult);
     1108
     1109        if (arithProfile->didObserveBigInt32())
     1110            node->mergeFlags(NodeMayHaveBigInt32Result);
     1111        if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
     1112            node->mergeFlags(NodeMayHaveHeapBigIntResult);
    11041113
    11051114        return node;
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r260683 r260730  
    189189        case Inc:
    190190        case Dec: {
     191            if (node->child1()->shouldSpeculateBigInt()) {
     192                if (node->child1()->shouldSpeculateHeapBigInt()) {
     193                    // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
     194                    // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
     195                    node->setOp(op == Inc ? ValueAdd : ValueSub);
     196                    Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecHeapBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().heapBigIntConstantOne.get())));
     197                    node->children.setChild2(Edge(nodeConstantOne));
     198                    fixEdge<HeapBigIntUse>(node->child1());
     199                    fixEdge<HeapBigIntUse>(node->child2());
     200                    // HeapBigInts are cells, so the default of NodeResultJS is good here
     201                    break;
     202                }
     203#if USE(BIGINT32)
     204                if (m_graph.unaryArithShouldSpeculateBigInt32(node, FixupPass)) {
     205                    node->setOp(op == Inc ? ValueAdd : ValueSub);
     206                    Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
     207                    node->children.setChild2(Edge(nodeConstantOne));
     208                    fixEdge<BigInt32Use>(node->child1());
     209                    fixEdge<BigInt32Use>(node->child2());
     210                    // The default of NodeResultJS is good enough for now.
     211                    // FIXME: consider having a special representation for small BigInts instead.
     212                    break;
     213                }
     214
     215                // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
     216                // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
     217                node->setOp(op == Inc ? ValueAdd : ValueSub);
     218                Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
     219                node->children.setChild2(Edge(nodeConstantOne));
     220                fixEdge<AnyBigIntUse>(node->child1());
     221                fixEdge<AnyBigIntUse>(node->child2());
     222                // The default of NodeResultJS is good here
     223#endif // USE(BIGINT32)
     224                break;
     225            }
     226
    191227            if (node->child1()->shouldSpeculateUntypedForArithmetic()) {
    192228                fixEdge<UntypedUse>(node->child1());
     
    203239                fixEdge<Int32Use>(node->child2());
    204240                node->setResult(NodeResultInt32);
    205             } else if (node->child1()->shouldSpeculateHeapBigInt()) {
    206                 // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
    207                 // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
    208                 node->setOp(op == Inc ? ValueAdd : ValueSub);
    209                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecHeapBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().heapBigIntConstantOne.get())));
    210                 node->children.setChild2(Edge(nodeConstantOne));
    211                 fixEdge<HeapBigIntUse>(node->child1());
    212                 fixEdge<HeapBigIntUse>(node->child2());
    213                 // HeapBigInts are cells, so the default of NodeResultJS is good here
    214 #if USE(BIGINT32)
    215             } else if (node->child1()->shouldSpeculateBigInt32()) {
    216                 node->setOp(op == Inc ? ValueAdd : ValueSub);
    217                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
    218                 node->children.setChild2(Edge(nodeConstantOne));
    219                 fixEdge<BigInt32Use>(node->child1());
    220                 fixEdge<BigInt32Use>(node->child2());
    221                 // The default of NodeResultJS is good enough for now.
    222                 // FIXME: consider having a special representation for small BigInts instead.
    223             } else if (node->child1()->shouldSpeculateBigInt()) {
    224                 // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
    225                 // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
    226                 node->setOp(op == Inc ? ValueAdd : ValueSub);
    227                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
    228                 node->children.setChild2(Edge(nodeConstantOne));
    229                 fixEdge<AnyBigIntUse>(node->child1());
    230                 fixEdge<AnyBigIntUse>(node->child2());
    231                 // The default of NodeResultJS is good here
    232 #endif // USE(BIGINT32)
    233241            } else if (node->child1()->shouldSpeculateInt52()) {
    234242                node->setOp(op == Inc ? ArithAdd : ArithSub);
     
    263271
    264272#if USE(BIGINT32)
     273            if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
     274                fixEdge<BigInt32Use>(child1);
     275                fixEdge<BigInt32Use>(child2);
     276                break;
     277            }
     278
    265279            if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
    266280                fixEdge<AnyBigIntUse>(child1);
    267281                fixEdge<AnyBigIntUse>(child2);
    268                 break; 
     282                break;
    269283            }
    270284#endif
     
    312326                fixEdge<HeapBigIntUse>(node->child2());
    313327#endif
    314                 node->clearFlags(NodeMustGenerate);
     328                // Shift can throw RangeError.
     329                switch (node->op()) {
     330                case ValueBitXor:
     331                case ValueBitOr:
     332                case ValueBitAnd:
     333                    node->clearFlags(NodeMustGenerate);
     334                    break;
     335                default:
     336                    break;
     337                }
    315338                break;
    316339            }
     
    514537                fixEdge<HeapBigIntUse>(child2);
    515538#if USE(BIGINT32)
    516             } else if (Node::shouldSpeculateBigInt32(child1.node(), child2.node())) {
     539            } else if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
    517540                fixEdge<BigInt32Use>(child1);
    518541                fixEdge<BigInt32Use>(child2);
     
    607630            if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
    608631#if USE(BIGINT32)
    609                 if (Node::shouldSpeculateBigInt32(leftChild.node(), rightChild.node())) {
     632                if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
    610633                    fixEdge<BigInt32Use>(node->child1());
    611634                    fixEdge<BigInt32Use>(node->child2());
     
    738761
    739762        case ValuePow: {
    740             if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child1().node())) {
     763            if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child2().node())) {
    741764                fixEdge<HeapBigIntUse>(node->child1());
    742765                fixEdge<HeapBigIntUse>(node->child2());
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r260323 r260730  
    410410            && !hasExitSite(node, Int52Overflow);
    411411    }
     412
     413#if USE(BIGINT32)
     414    bool binaryArithShouldSpeculateBigInt32(Node* node, PredictionPass pass)
     415    {
     416        if (!node->canSpeculateBigInt32(pass))
     417            return false;
     418        if (hasExitSite(node, BigInt32Overflow))
     419            return false;
     420        return Node::shouldSpeculateBigInt32(node->child1().node(), node->child2().node());
     421    }
     422
     423    bool unaryArithShouldSpeculateBigInt32(Node* node, PredictionPass pass)
     424    {
     425        if (!node->canSpeculateBigInt32(pass))
     426            return false;
     427        if (hasExitSite(node, BigInt32Overflow))
     428            return false;
     429        return node->child1()->shouldSpeculateBigInt32();
     430    }
     431#endif
    412432
    413433    bool canOptimizeStringObjectAccess(const CodeOrigin&);
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r260331 r260730  
    12031203    }
    12041204
     1205    bool mayHaveBigInt32Result()
     1206    {
     1207        return m_flags & NodeMayHaveBigInt32Result;
     1208    }
     1209
     1210    bool mayHaveHeapBigIntResult()
     1211    {
     1212        return m_flags & NodeMayHaveHeapBigIntResult;
     1213    }
     1214
    12051215    bool mayHaveBigIntResult()
    12061216    {
    1207         return m_flags & NodeMayHaveBigIntResult;
     1217        return mayHaveBigInt32Result() || mayHaveHeapBigIntResult();
    12081218    }
    12091219
     
    28672877        return nodeCanSpeculateInt52(arithNodeFlags(), source);
    28682878    }
     2879
     2880    bool canSpeculateBigInt32(RareCaseProfilingSource source)
     2881    {
     2882        return nodeCanSpeculateBigInt32(arithNodeFlags(), source);
     2883    }
    28692884   
    28702885    RareCaseProfilingSource sourceFor(PredictionPass pass)
     
    28832898    {
    28842899        return canSpeculateInt52(sourceFor(pass));
     2900    }
     2901
     2902    bool canSpeculateBigInt32(PredictionPass pass)
     2903    {
     2904        return canSpeculateBigInt32(sourceFor(pass));
    28852905    }
    28862906
  • trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp

    r237972 r260730  
    8989        out.print(comma, "MayHaveDoubleResult");
    9090
    91     if (flags & NodeMayHaveBigIntResult)
    92         out.print(comma, "MayHaveBigIntResult");
     91    if (flags & NodeMayHaveBigInt32Result)
     92        out.print(comma, "MayHaveBigInt32Result");
     93
     94    if (flags & NodeMayHaveHeapBigIntResult)
     95        out.print(comma, "MayHaveHeapBigIntResult");
    9396
    9497    if (flags & NodeMayHaveNonNumericResult)
  • trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h

    r260331 r260730  
    4343#define NodeResultBoolean                0x0006
    4444#define NodeResultStorage                0x0007
    45                                
     45
    4646#define NodeMustGenerate                 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
    4747#define NodeHasVarArgs                   0x0010
    48    
    49 #define NodeBehaviorMask                 0x007e0
     48
    5049#define NodeMayHaveDoubleResult          0x00020
    5150#define NodeMayOverflowInt52             0x00040
     
    5453#define NodeMayNegZeroInBaseline         0x00200
    5554#define NodeMayNegZeroInDFG              0x00400
    56 #define NodeMayHaveNonNumericResult      0x00800
    57 // FIXME: we should have separate flags for HeapBigInt and BigInt32, currently prediction propagation will pessimize things.
    58 #define NodeMayHaveBigIntResult          0x01000
    59 #define NodeMayHaveNonIntResult          (NodeMayHaveDoubleResult | NodeMayHaveNonNumericResult | NodeMayHaveBigIntResult)
    60                                
    61 #define NodeBytecodeBackPropMask        0x3e000
    62 #define NodeBytecodeUseBottom           0x00000
    63 #define NodeBytecodeUsesAsNumber        0x02000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
    64 #define NodeBytecodeNeedsNegZero        0x04000 // The result of this computation may be used in a context that observes -0.
    65 #define NodeBytecodeUsesAsOther         0x08000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
    66 #define NodeBytecodeUsesAsValue         (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
    67 #define NodeBytecodeUsesAsInt           0x10000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
    68 #define NodeBytecodeUsesAsArrayIndex    0x20000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.
     55#define NodeMayHaveBigInt32Result        0x00800
     56#define NodeMayHaveHeapBigIntResult      0x01000
     57#define NodeMayHaveNonNumericResult      0x02000
     58#define NodeBehaviorMask                 (NodeMayHaveDoubleResult | NodeMayOverflowInt52 | NodeMayOverflowInt32InBaseline | NodeMayOverflowInt32InDFG | NodeMayNegZeroInBaseline | NodeMayNegZeroInDFG | NodeMayHaveBigInt32Result | NodeMayHaveHeapBigIntResult | NodeMayHaveNonNumericResult)
     59#define NodeMayHaveNonIntResult          (NodeMayHaveDoubleResult | NodeMayHaveNonNumericResult | NodeMayHaveBigInt32Result | NodeMayHaveHeapBigIntResult)
     60
     61#define NodeBytecodeUseBottom            0x00000
     62#define NodeBytecodeUsesAsNumber         0x04000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
     63#define NodeBytecodeNeedsNegZero         0x08000 // The result of this computation may be used in a context that observes -0.
     64#define NodeBytecodeUsesAsOther          0x10000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
     65#define NodeBytecodeUsesAsInt            0x20000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
     66#define NodeBytecodeUsesAsArrayIndex     0x40000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.
     67#define NodeBytecodeUsesAsValue          (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
     68#define NodeBytecodeBackPropMask         (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex)
    6969
    7070#define NodeArithFlagsMask               (NodeBehaviorMask | NodeBytecodeBackPropMask)
    7171
    72 #define NodeIsFlushed                   0x40000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush.
     72#define NodeIsFlushed                    0x80000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush.
    7373
    74 #define NodeMiscFlag1                   0x80000
    75 #define NodeMiscFlag2                   0x100000
     74#define NodeMiscFlag1                   0x100000
     75#define NodeMiscFlag2                   0x200000
    7676
    7777typedef uint32_t NodeFlags;
     
    159159}
    160160
     161static inline bool nodeMayHaveHeapBigInt(NodeFlags flags, RareCaseProfilingSource)
     162{
     163    return !!(flags & NodeMayHaveHeapBigIntResult);
     164}
     165
     166static inline bool nodeCanSpeculateBigInt32(NodeFlags flags, RareCaseProfilingSource source)
     167{
     168    // We always attempt to produce BigInt32 as much as possible. If we see HeapBigInt, we observed overflow.
     169    // FIXME: Extend this information by tiered profiling (from Baseline, DFG etc.).
     170    // https://bugs.webkit.org/show_bug.cgi?id=211039
     171    return !nodeMayHaveHeapBigInt(flags, source);
     172}
     173
    161174// FIXME: Get rid of this.
    162175// https://bugs.webkit.org/show_bug.cgi?id=131689
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r260711 r260730  
    211211                    // left or right is definitely something other than a number.
    212212                    changed |= mergePrediction(SpecString);
    213                 } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
     213                }
     214#if USE(BIGINT32)
     215                else if (m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
     216                    changed |= mergePrediction(SpecBigInt32);
     217#endif
     218                else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
    214219                    changed |= mergePrediction(SpecBigInt);
    215220                else {
     
    279284                    else
    280285                        changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    281                 } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
     286                }
     287#if USE(BIGINT32)
     288                else if (m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
     289                    changed |= mergePrediction(SpecBigInt32);
     290#endif
     291                else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
    282292                    changed |= mergePrediction(SpecBigInt);
    283293                else {
     
    305315                    else
    306316                        changed |= mergePrediction(speculatedDoubleTypeForPrediction(prediction));
    307                 } else if (isBigIntSpeculation(prediction))
     317                }
     318#if USE(BIGINT32)
     319                else if (m_graph.unaryArithShouldSpeculateBigInt32(node, m_pass))
     320                    changed |= mergePrediction(SpecBigInt32);
     321#endif
     322                else if (isBigIntSpeculation(prediction))
    308323                    changed |= mergePrediction(SpecBigInt);
    309324                else {
     
    387402                    else
    388403                        changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    389                 } else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right))
     404                }
     405#if USE(BIGINT32)
     406                else if (op == ValueMul && m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
     407                    changed |= mergePrediction(SpecBigInt32);
     408#endif
     409                else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right))
    390410                    changed |= mergePrediction(SpecBigInt);
    391411                else {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r260683 r260730  
    40274027
    40284028#if USE(BIGINT32)
     4029    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     4030    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     4031    // https://bugs.webkit.org/show_bug.cgi?id=210957
     4032    // https://bugs.webkit.org/show_bug.cgi?id=211040
    40294033    if (node->isBinaryUseKind(BigInt32Use)) {
    40304034        SpeculateBigInt32Operand left(this, leftChild);
     
    40414045        m_jit.unboxBigInt32(rightGPR, tempGPR);
    40424046
    4043         // FIXME: add some way to eliminate the overflow check
    40444047        MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
    40454048
    4046         speculationCheck(Overflow, JSValueRegs(), 0, check);
     4049        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
    40474050
    40484051        m_jit.boxBigInt32(resultGPR);
     
    41314134
    41324135#if USE(BIGINT32)
     4136    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     4137    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     4138    // https://bugs.webkit.org/show_bug.cgi?id=210957
     4139    // https://bugs.webkit.org/show_bug.cgi?id=211040
    41334140    if (node->binaryUseKind() == BigInt32Use) {
    41344141        SpeculateBigInt32Operand left(this, node->child1());
     
    41454152        m_jit.unboxBigInt32(rightGPR, tempGPR);
    41464153
    4147         // FIXME: add some way to eliminate the overflow check
    41484154        MacroAssembler::Jump check = m_jit.branchSub32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
    41494155
    4150         speculationCheck(Overflow, JSValueRegs(), 0, check);
     4156        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
    41514157
    41524158        m_jit.boxBigInt32(resultGPR);
     
    49784984
    49794985#if USE(BIGINT32)
     4986    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     4987    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     4988    // https://bugs.webkit.org/show_bug.cgi?id=210957
     4989    // https://bugs.webkit.org/show_bug.cgi?id=211040
    49804990    if (node->binaryUseKind() == BigInt32Use) {
    49814991        // FIXME: the code between compileValueAdd, compileValueSub and compileValueMul for BigInt32 is nearly identical, so try to get rid of the duplication.
     
    49935003        m_jit.unboxBigInt32(rightGPR, tempGPR);
    49945004
    4995         // FIXME: add some way to eliminate the overflow check
    49965005        MacroAssembler::Jump check = m_jit.branchMul32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
    49975006
    4998         speculationCheck(Overflow, JSValueRegs(), 0, check);
     5007        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
    49995008
    50005009        m_jit.boxBigInt32(resultGPR);
     
    52105219
    52115220    // FIXME: add a fast path for BigInt32. Currently we go through the slow path, because of how ugly the code for Div gets.
     5221    // https://bugs.webkit.org/show_bug.cgi?id=211041
    52125222
    52135223    if (node->isBinaryUseKind(HeapBigIntUse)) {
     
    1080310813void SpeculativeJIT::speculateHeapBigInt(Edge edge)
    1080410814{
    10805     if (!needsTypeCheck(edge, SpecBigInt))
     10815    if (!needsTypeCheck(edge, SpecHeapBigInt))
    1080610816        return;
    1080710817
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r260660 r260730  
    21442144
    21452145#if USE(BIGINT32)
     2146        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     2147        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     2148        // https://bugs.webkit.org/show_bug.cgi?id=210957
     2149        // https://bugs.webkit.org/show_bug.cgi?id=211040
    21462150        if (m_node->isBinaryUseKind(BigInt32Use)) {
    21472151            LValue left = lowBigInt32(m_node->child1());
     
    21522156
    21532157            CheckValue* result = m_out.speculateAdd(unboxedLeft, unboxedRight);
    2154             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
     2158            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
    21552159
    21562160            LValue boxedResult = boxBigInt32(result);
     
    21822186
    21832187#if USE(BIGINT32)
     2188        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     2189        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     2190        // https://bugs.webkit.org/show_bug.cgi?id=210957
     2191        // https://bugs.webkit.org/show_bug.cgi?id=211040
    21842192        if (m_node->isBinaryUseKind(BigInt32Use)) {
    21852193            LValue left = lowBigInt32(m_node->child1());
     
    21902198
    21912199            CheckValue* result = m_out.speculateSub(unboxedLeft, unboxedRight);
    2192             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
     2200            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
    21932201
    21942202            LValue boxedResult = boxBigInt32(result);
     
    22202228
    22212229#if USE(BIGINT32)
     2230        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
     2231        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
     2232        // https://bugs.webkit.org/show_bug.cgi?id=210957
     2233        // https://bugs.webkit.org/show_bug.cgi?id=211040
    22222234        if (m_node->isBinaryUseKind(BigInt32Use)) {
    22232235            LValue left = lowBigInt32(m_node->child1());
     
    22282240
    22292241            CheckValue* result = m_out.speculateMul(unboxedLeft, unboxedRight);
    2230             blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
     2242            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
    22312243
    22322244            LValue boxedResult = boxBigInt32(result);
     
    26282640        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
    26292641        // FIXME: add a fast path for BigInt32 here
     2642        // https://bugs.webkit.org/show_bug.cgi?id=211041
    26302643        if (m_node->isBinaryUseKind(HeapBigIntUse)) {
    26312644            LValue left = lowHeapBigInt(m_node->child1());
Note: See TracChangeset for help on using the changeset viewer.