Title: [260730] trunk
Revision
260730
Author
ysuz...@apple.com
Date
2020-04-26 14:11:50 -0700 (Sun, 26 Apr 2020)

Log 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/_javascript_Core:

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

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (260729 => 260730)


--- trunk/JSTests/ChangeLog	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/JSTests/ChangeLog	2020-04-26 21:11:50 UTC (rev 260730)
@@ -1,3 +1,31 @@
+2020-04-26  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [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.
+
+        * 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):
+
 2020-04-25  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Handle BigInt32 INT32_MIN shift amount

Added: trunk/JSTests/stress/bigint32-add-overflow.js (0 => 260730)


--- trunk/JSTests/stress/bigint32-add-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/bigint32-add-overflow.js	2020-04-26 21:11:50 UTC (rev 260730)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function add(a, b) {
+    return a + b;
+}
+noInline(add);
+
+{
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(add(BigInt(i), 2n), BigInt(i + 2));
+}
+{
+    let max = 0x7fffffffn;
+    let result = 0x80000001n;
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(add(max, 2n), result);
+}

Added: trunk/JSTests/stress/bigint32-dec-overflow.js (0 => 260730)


--- trunk/JSTests/stress/bigint32-dec-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/bigint32-dec-overflow.js	2020-04-26 21:11:50 UTC (rev 260730)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function dec(a) {
+    return --a;
+}
+noInline(dec);
+
+{
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(dec(BigInt(i)), BigInt(i - 1));
+}
+{
+    let min = -0x7fffffffn - 1n;
+    let result = -0x80000001n;
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(dec(min), result);
+}

Added: trunk/JSTests/stress/bigint32-inc-overflow.js (0 => 260730)


--- trunk/JSTests/stress/bigint32-inc-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/bigint32-inc-overflow.js	2020-04-26 21:11:50 UTC (rev 260730)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function inc(a) {
+    return ++a;
+}
+noInline(inc);
+
+{
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(inc(BigInt(i)), BigInt(i + 1));
+}
+{
+    let max = 0x7fffffffn;
+    let result = 0x80000000n;
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(inc(max), result);
+}

Added: trunk/JSTests/stress/bigint32-mul-overflow.js (0 => 260730)


--- trunk/JSTests/stress/bigint32-mul-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/bigint32-mul-overflow.js	2020-04-26 21:11:50 UTC (rev 260730)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function mul(a, b) {
+    return a * b;
+}
+noInline(mul);
+
+{
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(mul(BigInt(i), 2n), BigInt(i * 2));
+}
+{
+    let max = 0x7fffffffn;
+    let result = 0xfffffffen;
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(mul(max, 2n), result);
+}

Added: trunk/JSTests/stress/bigint32-sub-overflow.js (0 => 260730)


--- trunk/JSTests/stress/bigint32-sub-overflow.js	                        (rev 0)
+++ trunk/JSTests/stress/bigint32-sub-overflow.js	2020-04-26 21:11:50 UTC (rev 260730)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function sub(a, b) {
+    return a - b;
+}
+noInline(sub);
+
+{
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(sub(BigInt(i), 2n), BigInt(i - 2));
+}
+{
+    let min = -0x7fffffffn - 1n;
+    let result = -0x80000002n;
+    for (var i = 0; i < 100000; ++i)
+        shouldBe(sub(min, 2n), result);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (260729 => 260730)


--- trunk/Source/_javascript_Core/ChangeLog	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-04-26 21:11:50 UTC (rev 260730)
@@ -1,3 +1,77 @@
+2020-04-26  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [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.
+
+        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):
+
 2020-04-25  Ross Kirsling  <ross.kirsl...@sony.com>
 
         [JSC] isCallable is redundant with isFunction

Modified: trunk/Source/_javascript_Core/bytecode/ExitKind.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/bytecode/ExitKind.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/bytecode/ExitKind.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -88,6 +88,8 @@
         return "ExceptionCheck";
     case GenericUnwind:
         return "GenericUnwind";
+    case BigInt32Overflow:
+        return "BigInt32Overflow";
     }
     RELEASE_ASSERT_NOT_REACHED();
     return "Unknown";

Modified: trunk/Source/_javascript_Core/bytecode/ExitKind.h (260729 => 260730)


--- trunk/Source/_javascript_Core/bytecode/ExitKind.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/bytecode/ExitKind.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -55,6 +55,7 @@
     DebuggerEvent, // We exited because we need to service the debugger.
     ExceptionCheck, // We exited because a direct exception check showed that we threw an exception from a C call.
     GenericUnwind, // We exited because we arrived at this OSR exit from genericUnwind.
+    BigInt32Overflow, // We exited because of an BigInt32 overflow.
 };
 
 const char* exitKindToString(ExitKind);

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (260729 => 260730)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -100,7 +100,12 @@
 static constexpr SpeculatedType SpecEmpty                             = 1ull << 40; // It's definitely an empty value marker.
 static constexpr SpeculatedType SpecHeapBigInt                        = 1ull << 41; // It's definitely a BigInt that is allocated on the heap
 static constexpr SpeculatedType SpecBigInt32                          = 1ull << 42; // It's definitely a small BigInt that is inline the JSValue
+#if USE(BIGINT32)
 static constexpr SpeculatedType SpecBigInt                            = SpecBigInt32 | SpecHeapBigInt;
+#else
+// 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.
+static constexpr SpeculatedType SpecBigInt                            = SpecHeapBigInt;
+#endif
 static constexpr SpeculatedType SpecDataViewObject                    = 1ull << 43; // It's definitely a JSDataView.
 static constexpr SpeculatedType SpecPrimitive                         = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
 static constexpr SpeculatedType SpecObject                            = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecDateObject | SpecPromiseObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther | SpecDataViewObject; // Bitmask used for testing for any kind of object prediction.

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -766,8 +766,10 @@
             // the format of our result:
             // https://bugs.webkit.org/show_bug.cgi?id=210982
             setTypeForNode(node, SpecBigInt);
-        } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
+        } else if (node->isBinaryUseKind(AnyBigIntUse))
             setTypeForNode(node, SpecBigInt);
+        else if (node->isBinaryUseKind(BigInt32Use))
+            setTypeForNode(node, SpecBigInt32);
         else {
             DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse);
             clobberWorld();
@@ -1056,8 +1058,10 @@
             // the format of our result:
             // https://bugs.webkit.org/show_bug.cgi?id=210982
             setTypeForNode(node, SpecBigInt);
-        } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
+        } else if (node->isBinaryUseKind(AnyBigIntUse))
             setTypeForNode(node, SpecBigInt);
+        else if (node->isBinaryUseKind(BigInt32Use))
+            setTypeForNode(node, SpecBigInt32);
         else {
             clobberWorld();
             setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -1011,8 +1011,10 @@
                 node->mergeFlags(NodeMayHaveDoubleResult);
             if (observed.didObserveNonNumeric())
                 node->mergeFlags(NodeMayHaveNonNumericResult);
-            if (observed.didObserveBigInt())
-                node->mergeFlags(NodeMayHaveBigIntResult);
+            if (observed.didObserveBigInt32())
+                node->mergeFlags(NodeMayHaveBigInt32Result);
+            if (observed.didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
+                node->mergeFlags(NodeMayHaveHeapBigIntResult);
             break;
         }
         case ValueMul:
@@ -1030,8 +1032,10 @@
                 node->mergeFlags(NodeMayHaveDoubleResult);
             if (arithProfile->didObserveNonNumeric())
                 node->mergeFlags(NodeMayHaveNonNumericResult);
-            if (arithProfile->didObserveBigInt())
-                node->mergeFlags(NodeMayHaveBigIntResult);
+            if (arithProfile->didObserveBigInt32())
+                node->mergeFlags(NodeMayHaveBigInt32Result);
+            if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
+                node->mergeFlags(NodeMayHaveHeapBigIntResult);
             break;
         }
         case ValueNegate:
@@ -1049,8 +1053,10 @@
                 node->mergeFlags(NodeMayOverflowInt32InBaseline);
             if (arithProfile->didObserveNonNumeric())
                 node->mergeFlags(NodeMayHaveNonNumericResult);
-            if (arithProfile->didObserveBigInt())
-                node->mergeFlags(NodeMayHaveBigIntResult);
+            if (arithProfile->didObserveBigInt32())
+                node->mergeFlags(NodeMayHaveBigInt32Result);
+            if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
+                node->mergeFlags(NodeMayHaveHeapBigIntResult);
             break;
         }
 
@@ -1099,9 +1105,12 @@
         node->mergeFlags(NodeMayOverflowInt32InBaseline | NodeMayNegZeroInBaseline);
 
         BinaryArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->binaryArithProfileForBytecodeIndex(m_currentIndex);
-        if (arithProfile->didObserveBigInt())
-            node->mergeFlags(NodeMayHaveBigIntResult);
 
+        if (arithProfile->didObserveBigInt32())
+            node->mergeFlags(NodeMayHaveBigInt32Result);
+        if (arithProfile->didObserveHeapBigInt() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BigInt32Overflow))
+            node->mergeFlags(NodeMayHaveHeapBigIntResult);
+
         return node;
     }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -188,6 +188,42 @@
 
         case Inc:
         case Dec: {
+            if (node->child1()->shouldSpeculateBigInt()) {
+                if (node->child1()->shouldSpeculateHeapBigInt()) {
+                    // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
+                    // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
+                    node->setOp(op == Inc ? ValueAdd : ValueSub);
+                    Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecHeapBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().heapBigIntConstantOne.get())));
+                    node->children.setChild2(Edge(nodeConstantOne));
+                    fixEdge<HeapBigIntUse>(node->child1());
+                    fixEdge<HeapBigIntUse>(node->child2());
+                    // HeapBigInts are cells, so the default of NodeResultJS is good here
+                    break;
+                }
+#if USE(BIGINT32)
+                if (m_graph.unaryArithShouldSpeculateBigInt32(node, FixupPass)) {
+                    node->setOp(op == Inc ? ValueAdd : ValueSub);
+                    Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
+                    node->children.setChild2(Edge(nodeConstantOne));
+                    fixEdge<BigInt32Use>(node->child1());
+                    fixEdge<BigInt32Use>(node->child2());
+                    // The default of NodeResultJS is good enough for now.
+                    // FIXME: consider having a special representation for small BigInts instead.
+                    break;
+                }
+
+                // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
+                // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
+                node->setOp(op == Inc ? ValueAdd : ValueSub);
+                Node* nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
+                node->children.setChild2(Edge(nodeConstantOne));
+                fixEdge<AnyBigIntUse>(node->child1());
+                fixEdge<AnyBigIntUse>(node->child2());
+                // The default of NodeResultJS is good here
+#endif // USE(BIGINT32)
+                break;
+            }
+
             if (node->child1()->shouldSpeculateUntypedForArithmetic()) {
                 fixEdge<UntypedUse>(node->child1());
                 break;
@@ -202,34 +238,6 @@
                 fixEdge<Int32Use>(node->child1());
                 fixEdge<Int32Use>(node->child2());
                 node->setResult(NodeResultInt32);
-            } else if (node->child1()->shouldSpeculateHeapBigInt()) {
-                // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
-                // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
-                node->setOp(op == Inc ? ValueAdd : ValueSub);
-                nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecHeapBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().heapBigIntConstantOne.get())));
-                node->children.setChild2(Edge(nodeConstantOne));
-                fixEdge<HeapBigIntUse>(node->child1());
-                fixEdge<HeapBigIntUse>(node->child2());
-                // HeapBigInts are cells, so the default of NodeResultJS is good here
-#if USE(BIGINT32)
-            } else if (node->child1()->shouldSpeculateBigInt32()) {
-                node->setOp(op == Inc ? ValueAdd : ValueSub);
-                nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
-                node->children.setChild2(Edge(nodeConstantOne));
-                fixEdge<BigInt32Use>(node->child1());
-                fixEdge<BigInt32Use>(node->child2());
-                // The default of NodeResultJS is good enough for now.
-                // FIXME: consider having a special representation for small BigInts instead.
-            } else if (node->child1()->shouldSpeculateBigInt()) {
-                // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
-                // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
-                node->setOp(op == Inc ? ValueAdd : ValueSub);
-                nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(jsBigInt32(1))));
-                node->children.setChild2(Edge(nodeConstantOne));
-                fixEdge<AnyBigIntUse>(node->child1());
-                fixEdge<AnyBigIntUse>(node->child2());
-                // The default of NodeResultJS is good here
-#endif // USE(BIGINT32)
             } else if (node->child1()->shouldSpeculateInt52()) {
                 node->setOp(op == Inc ? ArithAdd : ArithSub);
                 node->setArithMode(Arith::CheckOverflow);
@@ -262,10 +270,16 @@
             }
 
 #if USE(BIGINT32)
+            if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
+                fixEdge<BigInt32Use>(child1);
+                fixEdge<BigInt32Use>(child2);
+                break;
+            }
+
             if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
                 fixEdge<AnyBigIntUse>(child1);
                 fixEdge<AnyBigIntUse>(child2);
-                break; 
+                break;
             }
 #endif
 
@@ -311,7 +325,16 @@
                 fixEdge<HeapBigIntUse>(node->child1());
                 fixEdge<HeapBigIntUse>(node->child2());
 #endif
-                node->clearFlags(NodeMustGenerate);
+                // Shift can throw RangeError.
+                switch (node->op()) {
+                case ValueBitXor:
+                case ValueBitOr:
+                case ValueBitAnd:
+                    node->clearFlags(NodeMustGenerate);
+                    break;
+                default:
+                    break;
+                }
                 break;
             }
 
@@ -513,7 +536,7 @@
                 fixEdge<HeapBigIntUse>(child1);
                 fixEdge<HeapBigIntUse>(child2);
 #if USE(BIGINT32)
-            } else if (Node::shouldSpeculateBigInt32(child1.node(), child2.node())) {
+            } else if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
                 fixEdge<BigInt32Use>(child1);
                 fixEdge<BigInt32Use>(child2);
             } else if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
@@ -606,7 +629,7 @@
 
             if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
 #if USE(BIGINT32)
-                if (Node::shouldSpeculateBigInt32(leftChild.node(), rightChild.node())) {
+                if (m_graph.binaryArithShouldSpeculateBigInt32(node, FixupPass)) {
                     fixEdge<BigInt32Use>(node->child1());
                     fixEdge<BigInt32Use>(node->child2());
                 } else if (Node::shouldSpeculateHeapBigInt(leftChild.node(), rightChild.node())) {
@@ -737,7 +760,7 @@
         }
 
         case ValuePow: {
-            if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child1().node())) {
+            if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child2().node())) {
                 fixEdge<HeapBigIntUse>(node->child1());
                 fixEdge<HeapBigIntUse>(node->child2());
                 node->clearFlags(NodeMustGenerate);

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -410,6 +410,26 @@
             && !hasExitSite(node, Int52Overflow);
     }
 
+#if USE(BIGINT32)
+    bool binaryArithShouldSpeculateBigInt32(Node* node, PredictionPass pass)
+    {
+        if (!node->canSpeculateBigInt32(pass))
+            return false;
+        if (hasExitSite(node, BigInt32Overflow))
+            return false;
+        return Node::shouldSpeculateBigInt32(node->child1().node(), node->child2().node());
+    }
+
+    bool unaryArithShouldSpeculateBigInt32(Node* node, PredictionPass pass)
+    {
+        if (!node->canSpeculateBigInt32(pass))
+            return false;
+        if (hasExitSite(node, BigInt32Overflow))
+            return false;
+        return node->child1()->shouldSpeculateBigInt32();
+    }
+#endif
+
     bool canOptimizeStringObjectAccess(const CodeOrigin&);
 
     bool getRegExpPrototypeProperty(JSObject* regExpPrototype, Structure* regExpPrototypeStructure, UniquedStringImpl* uid, JSValue& returnJSValue);

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -1202,9 +1202,19 @@
         return m_flags & NodeMayHaveNonNumericResult;
     }
 
+    bool mayHaveBigInt32Result()
+    {
+        return m_flags & NodeMayHaveBigInt32Result;
+    }
+
+    bool mayHaveHeapBigIntResult()
+    {
+        return m_flags & NodeMayHaveHeapBigIntResult;
+    }
+
     bool mayHaveBigIntResult()
     {
-        return m_flags & NodeMayHaveBigIntResult;
+        return mayHaveBigInt32Result() || mayHaveHeapBigIntResult();
     }
 
     bool hasNewArrayBufferData()
@@ -2866,6 +2876,11 @@
     {
         return nodeCanSpeculateInt52(arithNodeFlags(), source);
     }
+
+    bool canSpeculateBigInt32(RareCaseProfilingSource source)
+    {
+        return nodeCanSpeculateBigInt32(arithNodeFlags(), source);
+    }
     
     RareCaseProfilingSource sourceFor(PredictionPass pass)
     {
@@ -2884,6 +2899,11 @@
         return canSpeculateInt52(sourceFor(pass));
     }
 
+    bool canSpeculateBigInt32(PredictionPass pass)
+    {
+        return canSpeculateBigInt32(sourceFor(pass));
+    }
+
     bool hasTypeLocation()
     {
         return op() == ProfileType;

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeFlags.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGNodeFlags.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeFlags.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -88,9 +88,12 @@
     if (flags & NodeMayHaveDoubleResult)
         out.print(comma, "MayHaveDoubleResult");
 
-    if (flags & NodeMayHaveBigIntResult)
-        out.print(comma, "MayHaveBigIntResult");
+    if (flags & NodeMayHaveBigInt32Result)
+        out.print(comma, "MayHaveBigInt32Result");
 
+    if (flags & NodeMayHaveHeapBigIntResult)
+        out.print(comma, "MayHaveHeapBigIntResult");
+
     if (flags & NodeMayHaveNonNumericResult)
         out.print(comma, "MayHaveNonNumericResult");
 

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeFlags.h (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGNodeFlags.h	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeFlags.h	2020-04-26 21:11:50 UTC (rev 260730)
@@ -42,11 +42,10 @@
 #define NodeResultInt52                  0x0005
 #define NodeResultBoolean                0x0006
 #define NodeResultStorage                0x0007
-                                
+
 #define NodeMustGenerate                 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE.
 #define NodeHasVarArgs                   0x0010
-    
-#define NodeBehaviorMask                 0x007e0
+
 #define NodeMayHaveDoubleResult          0x00020
 #define NodeMayOverflowInt52             0x00040
 #define NodeMayOverflowInt32InBaseline   0x00080
@@ -53,26 +52,27 @@
 #define NodeMayOverflowInt32InDFG        0x00100
 #define NodeMayNegZeroInBaseline         0x00200
 #define NodeMayNegZeroInDFG              0x00400
-#define NodeMayHaveNonNumericResult      0x00800
-// FIXME: we should have separate flags for HeapBigInt and BigInt32, currently prediction propagation will pessimize things.
-#define NodeMayHaveBigIntResult          0x01000
-#define NodeMayHaveNonIntResult          (NodeMayHaveDoubleResult | NodeMayHaveNonNumericResult | NodeMayHaveBigIntResult)
-                                
-#define NodeBytecodeBackPropMask        0x3e000
-#define NodeBytecodeUseBottom           0x00000
-#define NodeBytecodeUsesAsNumber        0x02000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
-#define NodeBytecodeNeedsNegZero        0x04000 // The result of this computation may be used in a context that observes -0.
-#define NodeBytecodeUsesAsOther         0x08000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
-#define NodeBytecodeUsesAsValue         (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
-#define NodeBytecodeUsesAsInt           0x10000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
-#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.
+#define NodeMayHaveBigInt32Result        0x00800
+#define NodeMayHaveHeapBigIntResult      0x01000
+#define NodeMayHaveNonNumericResult      0x02000
+#define NodeBehaviorMask                 (NodeMayHaveDoubleResult | NodeMayOverflowInt52 | NodeMayOverflowInt32InBaseline | NodeMayOverflowInt32InDFG | NodeMayNegZeroInBaseline | NodeMayNegZeroInDFG | NodeMayHaveBigInt32Result | NodeMayHaveHeapBigIntResult | NodeMayHaveNonNumericResult)
+#define NodeMayHaveNonIntResult          (NodeMayHaveDoubleResult | NodeMayHaveNonNumericResult | NodeMayHaveBigInt32Result | NodeMayHaveHeapBigIntResult)
 
+#define NodeBytecodeUseBottom            0x00000
+#define NodeBytecodeUsesAsNumber         0x04000 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
+#define NodeBytecodeNeedsNegZero         0x08000 // The result of this computation may be used in a context that observes -0.
+#define NodeBytecodeUsesAsOther          0x10000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
+#define NodeBytecodeUsesAsInt            0x20000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
+#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.
+#define NodeBytecodeUsesAsValue          (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
+#define NodeBytecodeBackPropMask         (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther | NodeBytecodeUsesAsInt | NodeBytecodeUsesAsArrayIndex)
+
 #define NodeArithFlagsMask               (NodeBehaviorMask | NodeBytecodeBackPropMask)
 
-#define NodeIsFlushed                   0x40000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush.
+#define NodeIsFlushed                    0x80000 // Computed by CPSRethreadingPhase, will tell you which local nodes are backwards-reachable from a Flush.
 
-#define NodeMiscFlag1                   0x80000
-#define NodeMiscFlag2                   0x100000
+#define NodeMiscFlag1                   0x100000
+#define NodeMiscFlag2                   0x200000
 
 typedef uint32_t NodeFlags;
 
@@ -158,6 +158,19 @@
     return true;
 }
 
+static inline bool nodeMayHaveHeapBigInt(NodeFlags flags, RareCaseProfilingSource)
+{
+    return !!(flags & NodeMayHaveHeapBigIntResult);
+}
+
+static inline bool nodeCanSpeculateBigInt32(NodeFlags flags, RareCaseProfilingSource source)
+{
+    // We always attempt to produce BigInt32 as much as possible. If we see HeapBigInt, we observed overflow.
+    // FIXME: Extend this information by tiered profiling (from Baseline, DFG etc.).
+    // https://bugs.webkit.org/show_bug.cgi?id=211039
+    return !nodeMayHaveHeapBigInt(flags, source);
+}
+
 // FIXME: Get rid of this.
 // https://bugs.webkit.org/show_bug.cgi?id=131689
 static inline NodeFlags canonicalResultRepresentation(NodeFlags flags)

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -210,7 +210,12 @@
                 } else if (isStringOrStringObjectSpeculation(left) || isStringOrStringObjectSpeculation(right)) {
                     // left or right is definitely something other than a number.
                     changed |= mergePrediction(SpecString);
-                } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
+                }
+#if USE(BIGINT32)
+                else if (m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
+                    changed |= mergePrediction(SpecBigInt32);
+#endif
+                else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
                     changed |= mergePrediction(SpecBigInt);
                 else {
                     changed |= mergePrediction(SpecInt32Only);
@@ -278,7 +283,12 @@
                         changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
-                } else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
+                }
+#if USE(BIGINT32)
+                else if (m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
+                    changed |= mergePrediction(SpecBigInt32);
+#endif
+                else if (isBigIntSpeculation(left) && isBigIntSpeculation(right))
                     changed |= mergePrediction(SpecBigInt);
                 else {
                     changed |= mergePrediction(SpecInt32Only);
@@ -304,7 +314,12 @@
                         changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPrediction(prediction));
-                } else if (isBigIntSpeculation(prediction))
+                }
+#if USE(BIGINT32)
+                else if (m_graph.unaryArithShouldSpeculateBigInt32(node, m_pass))
+                    changed |= mergePrediction(SpecBigInt32);
+#endif
+                else if (isBigIntSpeculation(prediction))
                     changed |= mergePrediction(SpecBigInt);
                 else {
                     changed |= mergePrediction(SpecInt32Only);
@@ -386,7 +401,12 @@
                         changed |= mergePrediction(SpecInt52Any);
                     else
                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
-                } else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right))
+                }
+#if USE(BIGINT32)
+                else if (op == ValueMul && m_graph.binaryArithShouldSpeculateBigInt32(node, m_pass))
+                    changed |= mergePrediction(SpecBigInt32);
+#endif
+                else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right))
                     changed |= mergePrediction(SpecBigInt);
                 else {
                     changed |= mergePrediction(SpecInt32Only);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -4026,6 +4026,10 @@
     Edge& rightChild = node->child2();
 
 #if USE(BIGINT32)
+    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+    // https://bugs.webkit.org/show_bug.cgi?id=210957
+    // https://bugs.webkit.org/show_bug.cgi?id=211040
     if (node->isBinaryUseKind(BigInt32Use)) {
         SpeculateBigInt32Operand left(this, leftChild);
         SpeculateBigInt32Operand right(this, rightChild);
@@ -4040,10 +4044,9 @@
         m_jit.unboxBigInt32(leftGPR, resultGPR);
         m_jit.unboxBigInt32(rightGPR, tempGPR);
 
-        // FIXME: add some way to eliminate the overflow check
         MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
 
-        speculationCheck(Overflow, JSValueRegs(), 0, check);
+        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
 
         m_jit.boxBigInt32(resultGPR);
         jsValueResult(resultGPR, node);
@@ -4130,6 +4133,10 @@
     Edge& rightChild = node->child2();
 
 #if USE(BIGINT32)
+    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+    // https://bugs.webkit.org/show_bug.cgi?id=210957
+    // https://bugs.webkit.org/show_bug.cgi?id=211040
     if (node->binaryUseKind() == BigInt32Use) {
         SpeculateBigInt32Operand left(this, node->child1());
         SpeculateBigInt32Operand right(this, node->child2());
@@ -4144,10 +4151,9 @@
         m_jit.unboxBigInt32(leftGPR, resultGPR);
         m_jit.unboxBigInt32(rightGPR, tempGPR);
 
-        // FIXME: add some way to eliminate the overflow check
         MacroAssembler::Jump check = m_jit.branchSub32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
 
-        speculationCheck(Overflow, JSValueRegs(), 0, check);
+        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
 
         m_jit.boxBigInt32(resultGPR);
         jsValueResult(resultGPR, node);
@@ -4977,6 +4983,10 @@
     Edge& rightChild = node->child2();
 
 #if USE(BIGINT32)
+    // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+    // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+    // https://bugs.webkit.org/show_bug.cgi?id=210957
+    // https://bugs.webkit.org/show_bug.cgi?id=211040
     if (node->binaryUseKind() == BigInt32Use) {
         // FIXME: the code between compileValueAdd, compileValueSub and compileValueMul for BigInt32 is nearly identical, so try to get rid of the duplication.
         SpeculateBigInt32Operand left(this, node->child1());
@@ -4992,10 +5002,9 @@
         m_jit.unboxBigInt32(leftGPR, resultGPR);
         m_jit.unboxBigInt32(rightGPR, tempGPR);
 
-        // FIXME: add some way to eliminate the overflow check
         MacroAssembler::Jump check = m_jit.branchMul32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
 
-        speculationCheck(Overflow, JSValueRegs(), 0, check);
+        speculationCheck(BigInt32Overflow, JSValueRegs(), 0, check);
 
         m_jit.boxBigInt32(resultGPR);
         jsValueResult(resultGPR, node);
@@ -5209,6 +5218,7 @@
     Edge& rightChild = node->child2();
 
     // FIXME: add a fast path for BigInt32. Currently we go through the slow path, because of how ugly the code for Div gets.
+    // https://bugs.webkit.org/show_bug.cgi?id=211041
 
     if (node->isBinaryUseKind(HeapBigIntUse)) {
         SpeculateCellOperand left(this, leftChild);
@@ -10802,7 +10812,7 @@
 
 void SpeculativeJIT::speculateHeapBigInt(Edge edge)
 {
-    if (!needsTypeCheck(edge, SpecBigInt))
+    if (!needsTypeCheck(edge, SpecHeapBigInt))
         return;
 
     SpeculateCellOperand operand(this, edge);

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (260729 => 260730)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-04-26 20:02:18 UTC (rev 260729)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-04-26 21:11:50 UTC (rev 260730)
@@ -2143,6 +2143,10 @@
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
 
 #if USE(BIGINT32)
+        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+        // https://bugs.webkit.org/show_bug.cgi?id=210957
+        // https://bugs.webkit.org/show_bug.cgi?id=211040
         if (m_node->isBinaryUseKind(BigInt32Use)) {
             LValue left = lowBigInt32(m_node->child1());
             LValue right = lowBigInt32(m_node->child2());
@@ -2151,7 +2155,7 @@
             LValue unboxedRight = unboxBigInt32(right);
 
             CheckValue* result = m_out.speculateAdd(unboxedLeft, unboxedRight);
-            blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
+            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
 
             LValue boxedResult = boxBigInt32(result);
             setJSValue(boxedResult);
@@ -2181,6 +2185,10 @@
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
 
 #if USE(BIGINT32)
+        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+        // https://bugs.webkit.org/show_bug.cgi?id=210957
+        // https://bugs.webkit.org/show_bug.cgi?id=211040
         if (m_node->isBinaryUseKind(BigInt32Use)) {
             LValue left = lowBigInt32(m_node->child1());
             LValue right = lowBigInt32(m_node->child2());
@@ -2189,7 +2197,7 @@
             LValue unboxedRight = unboxBigInt32(right);
 
             CheckValue* result = m_out.speculateSub(unboxedLeft, unboxedRight);
-            blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
+            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
 
             LValue boxedResult = boxBigInt32(result);
             setJSValue(boxedResult);
@@ -2219,6 +2227,10 @@
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
 
 #if USE(BIGINT32)
+        // FIXME: Introduce another BigInt32 code generation: binary use kinds are BigIntUse32, but result is SpecAnyInt and accepting overflow.
+        // Let's distinguish these modes based on result type information by introducing NodeResultBigInt32.
+        // https://bugs.webkit.org/show_bug.cgi?id=210957
+        // https://bugs.webkit.org/show_bug.cgi?id=211040
         if (m_node->isBinaryUseKind(BigInt32Use)) {
             LValue left = lowBigInt32(m_node->child1());
             LValue right = lowBigInt32(m_node->child2());
@@ -2227,7 +2239,7 @@
             LValue unboxedRight = unboxBigInt32(right);
 
             CheckValue* result = m_out.speculateMul(unboxedLeft, unboxedRight);
-            blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
+            blessSpeculation(result, BigInt32Overflow, noValue(), nullptr, m_origin);
 
             LValue boxedResult = boxBigInt32(result);
             setJSValue(boxedResult);
@@ -2627,6 +2639,7 @@
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
         // FIXME: add a fast path for BigInt32 here
+        // https://bugs.webkit.org/show_bug.cgi?id=211041
         if (m_node->isBinaryUseKind(HeapBigIntUse)) {
             LValue left = lowHeapBigInt(m_node->child1());
             LValue right = lowHeapBigInt(m_node->child2());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to