Title: [260660] trunk
Revision
260660
Author
[email protected]
Date
2020-04-24 12:19:23 -0700 (Fri, 24 Apr 2020)

Log Message

[JSC] DFG compare should speculate BigInt well
https://bugs.webkit.org/show_bug.cgi?id=210892

Reviewed by Saam Barati.

JSTests:

* stress/compare-bigint-with-number.js: Added.
(shouldBe):
(result):
(lessThan):
(lessThanEqual):
(greaterThan):
(greaterThanEqual):
(equal):
* stress/compare-bigint-with-string.js: Added.
(shouldBe):
(result):
(lessThan):
(lessThanEqual):
(greaterThan):
(greaterThanEqual):
(equal):
* stress/compare-bigint.js: Added.
(shouldBe):
(result):
(lessThan):
(lessThanEqual):
(greaterThan):
(greaterThanEqual):
(equal):
* stress/compare-bigint32.js: Added.
(shouldBe):
(result):
(lessThan):
(lessThanEqual):
(greaterThan):
(greaterThanEqual):
(equal):
* stress/compare-heap-bigint.js: Added.
(shouldBe):
(result):
(lessThan):
(lessThanEqual):
(greaterThan):
(greaterThanEqual):
(equal):
* stress/dfg-ai-fold-bigint.js: Added.
(shouldBe):
(allAreTrue):
(allAreFalse):
(lessThan):
(lessThanFalse):
(lessThanEqual):
(lessThanEqualFalse):
(greaterThan):
(greaterThanFalse):
(greaterThanEqual):
(greaterThanEqualFalse):
(equal):
(equalFalse):

Source/_javascript_Core:

Compare operations in DFG does not support BigInt related speculations. As a result, DFG fixup phase emits DoubleRep for operands, and
causes OSR exit. This patch adds BigInt32, HeapBigInt, and AnyBigIntUse support to DFG compare operations to avoid OSR exits.
We also introduce JSBigInt::compareToInt32 to avoid allocating JSBigInt only for comparison, and optimize C++ runtime for JSBigInt comparison.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileValueAdd):
(JSC::DFG::SpeculativeJIT::compileValueSub):
(JSC::DFG::SpeculativeJIT::compileValueMul):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::genericJSValueNonPeepholeCompare):
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compileBigInt32Compare):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareEq):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
(JSC::FTL::DFG::LowerDFGToB3::compare):
(JSC::FTL::DFG::LowerDFGToB3::genericJSValueCompare):
(JSC::FTL::DFG::LowerDFGToB3::nonSpeculativeCompare): Deleted.
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::unboxBigInt32):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::compareToInt32):
* runtime/JSBigInt.h:
(JSC::swapBigIntCompareResult):
* runtime/Operations.h:
(JSC::compareBigInt):
(JSC::compareBigInt32ToOtherPrimitive):
(JSC::bigIntCompare):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (260659 => 260660)


--- trunk/JSTests/ChangeLog	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/JSTests/ChangeLog	2020-04-24 19:19:23 UTC (rev 260660)
@@ -1,3 +1,65 @@
+2020-04-24  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG compare should speculate BigInt well
+        https://bugs.webkit.org/show_bug.cgi?id=210892
+
+        Reviewed by Saam Barati.
+
+        * stress/compare-bigint-with-number.js: Added.
+        (shouldBe):
+        (result):
+        (lessThan):
+        (lessThanEqual):
+        (greaterThan):
+        (greaterThanEqual):
+        (equal):
+        * stress/compare-bigint-with-string.js: Added.
+        (shouldBe):
+        (result):
+        (lessThan):
+        (lessThanEqual):
+        (greaterThan):
+        (greaterThanEqual):
+        (equal):
+        * stress/compare-bigint.js: Added.
+        (shouldBe):
+        (result):
+        (lessThan):
+        (lessThanEqual):
+        (greaterThan):
+        (greaterThanEqual):
+        (equal):
+        * stress/compare-bigint32.js: Added.
+        (shouldBe):
+        (result):
+        (lessThan):
+        (lessThanEqual):
+        (greaterThan):
+        (greaterThanEqual):
+        (equal):
+        * stress/compare-heap-bigint.js: Added.
+        (shouldBe):
+        (result):
+        (lessThan):
+        (lessThanEqual):
+        (greaterThan):
+        (greaterThanEqual):
+        (equal):
+        * stress/dfg-ai-fold-bigint.js: Added.
+        (shouldBe):
+        (allAreTrue):
+        (allAreFalse):
+        (lessThan):
+        (lessThanFalse):
+        (lessThanEqual):
+        (lessThanEqualFalse):
+        (greaterThan):
+        (greaterThanFalse):
+        (greaterThanEqual):
+        (greaterThanEqualFalse):
+        (equal):
+        (equalFalse):
+
 2020-04-24  Alexey Shvayka  <[email protected]>
 
         Proxy.revocable should not have [[Construct]] slot

Added: trunk/JSTests/stress/compare-bigint-with-number.js (0 => 260660)


--- trunk/JSTests/stress/compare-bigint-with-number.js	                        (rev 0)
+++ trunk/JSTests/stress/compare-bigint-with-number.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,280 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+const Greater = 0;
+const Less = 1;
+const Equal = 2;
+const Undefined = 3;
+
+function result(func, data)
+{
+    if (data ="" Undefined)
+        return false;
+    if (func === lessThan)
+        return data ="" Less;
+    if (func === lessThanEqual)
+        return data ="" Less || data ="" Equal;
+    if (func === greaterThan)
+        return data ="" Greater;
+    if (func === greaterThanEqual)
+        return data ="" Greater || data ="" Equal;
+    if (func === equal)
+        return data ="" Equal;
+    return false;
+}
+
+var list = [
+    [createHeapBigInt(1n), 2, Less],
+    [createHeapBigInt(1n), 1, Equal],
+    [createHeapBigInt(1n), 0, Greater],
+    [createHeapBigInt(1n), -1, Greater],
+    [createHeapBigInt(1n), -2, Greater],
+    [createHeapBigInt(0n), 2, Less],
+    [createHeapBigInt(0n), 1, Less],
+    [createHeapBigInt(0n), 0, Equal],
+    [createHeapBigInt(0n), -1, Greater],
+    [createHeapBigInt(0n), -2, Greater],
+    [createHeapBigInt(-1n), 2, Less],
+    [createHeapBigInt(-1n), 1, Less],
+    [createHeapBigInt(-1n), 0, Less],
+    [createHeapBigInt(-1n), -1, Equal],
+    [createHeapBigInt(-1n), -2, Greater],
+
+    [1, createHeapBigInt(2n), Less],
+    [1, createHeapBigInt(1n), Equal],
+    [1, createHeapBigInt(0n), Greater],
+    [1, createHeapBigInt(-1n), Greater],
+    [1, createHeapBigInt(-2n), Greater],
+    [0, createHeapBigInt(2n), Less],
+    [0, createHeapBigInt(1n), Less],
+    [0, createHeapBigInt(0n), Equal],
+    [0, createHeapBigInt(-1n), Greater],
+    [0, createHeapBigInt(-2n), Greater],
+    [-1, createHeapBigInt(2n), Less],
+    [-1, createHeapBigInt(1n), Less],
+    [-1, createHeapBigInt(0n), Less],
+    [-1, createHeapBigInt(-1n), Equal],
+    [-1, createHeapBigInt(-2n), Greater],
+
+    [1, 2n, Less],
+    [1, 1n, Equal],
+    [1, 0n, Greater],
+    [1, -1n, Greater],
+    [1, -2n, Greater],
+    [0, 2n, Less],
+    [0, 1n, Less],
+    [0, 0n, Equal],
+    [0, -1n, Greater],
+    [0, -2n, Greater],
+    [-1, 2n, Less],
+    [-1, 1n, Less],
+    [-1, 0n, Less],
+    [-1, -1n, Equal],
+    [-1, -2n, Greater],
+
+    [1n, 2, Less],
+    [1n, 1, Equal],
+    [1n, 0, Greater],
+    [1n, -1, Greater],
+    [1n, -2, Greater],
+    [0n, 2, Less],
+    [0n, 1, Less],
+    [0n, 0, Equal],
+    [0n, -1, Greater],
+    [0n, -2, Greater],
+    [-1n, 2, Less],
+    [-1n, 1, Less],
+    [-1n, 0, Less],
+    [-1n, -1, Equal],
+    [-1n, -2, Greater],
+
+    [createHeapBigInt(1000000000000000000000000n), 2, Greater],
+    [createHeapBigInt(1000000000000000000000000n), 1, Greater],
+    [createHeapBigInt(1000000000000000000000000n), 0, Greater],
+    [createHeapBigInt(1000000000000000000000000n), -1, Greater],
+    [createHeapBigInt(1000000000000000000000000n), -2, Greater],
+    [createHeapBigInt(-1000000000000000000000000n), 2, Less],
+    [createHeapBigInt(-1000000000000000000000000n), 1, Less],
+    [createHeapBigInt(-1000000000000000000000000n), 0, Less],
+    [createHeapBigInt(-1000000000000000000000000n), -1, Less],
+    [createHeapBigInt(-1000000000000000000000000n), -2, Less],
+
+    [2, createHeapBigInt(1000000000000000000000000n), Less],
+    [1, createHeapBigInt(1000000000000000000000000n), Less],
+    [0, createHeapBigInt(1000000000000000000000000n), Less],
+    [-1, createHeapBigInt(1000000000000000000000000n), Less],
+    [-2, createHeapBigInt(1000000000000000000000000n), Less],
+    [2, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [1, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [0, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [-1, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [-2, createHeapBigInt(-1000000000000000000000000n), Greater],
+
+    [1.5, 2n, Less],
+    [1.0, 1n, Equal],
+    [1.5, 0n, Greater],
+    [1.5, -1n, Greater],
+    [1.5, -2n, Greater],
+    [0.5, 2n, Less],
+    [0.5, 1n, Less],
+    [-0.0, 0n, Equal],
+    [0.0, 0n, Equal],
+    [0.5, -1n, Greater],
+    [0.5, -2n, Greater],
+    [-1.5, 2n, Less],
+    [-1.5, 1n, Less],
+    [-1.5, 0n, Less],
+    [-1.0, -1n, Equal],
+    [-1.5, -2n, Greater],
+
+    [1n, 2.5, Less],
+    [1n, 1.0, Equal],
+    [1n, 0.5, Greater],
+    [1n, -1.5, Greater],
+    [1n, -2.5, Greater],
+    [0n, 2.5, Less],
+    [0n, 1.0, Less],
+    [0n, 0.0, Equal],
+    [0n, -0.0, Equal],
+    [0n, -1.5, Greater],
+    [0n, -2.5, Greater],
+    [-1n, 2.5, Less],
+    [-1n, 1.0, Less],
+    [-1n, 0.5, Less],
+    [-1n, -1.0, Equal],
+    [-1n, -2.5, Greater],
+
+    [createHeapBigInt(1n), 2.5, Less],
+    [createHeapBigInt(1n), 1.0, Equal],
+    [createHeapBigInt(1n), 0.5, Greater],
+    [createHeapBigInt(1n), -1.5, Greater],
+    [createHeapBigInt(1n), -2.5, Greater],
+    [createHeapBigInt(0n), 2.5, Less],
+    [createHeapBigInt(0n), 1.5, Less],
+    [createHeapBigInt(0n), 0.0, Equal],
+    [createHeapBigInt(0n), -0.0, Equal],
+    [createHeapBigInt(0n), -1.5, Greater],
+    [createHeapBigInt(0n), -2.5, Greater],
+    [createHeapBigInt(-1n), 2.5, Less],
+    [createHeapBigInt(-1n), 1.5, Less],
+    [createHeapBigInt(-1n), 0.5, Less],
+    [createHeapBigInt(-1n), -1.0, Equal],
+    [createHeapBigInt(-1n), -2.5, Greater],
+
+    [1.5, createHeapBigInt(2n), Less],
+    [1.0, createHeapBigInt(1n), Equal],
+    [1.5, createHeapBigInt(0n), Greater],
+    [1.5, createHeapBigInt(-1n), Greater],
+    [1.5, createHeapBigInt(-2n), Greater],
+    [0.5, createHeapBigInt(2n), Less],
+    [0.5, createHeapBigInt(1n), Less],
+    [0.0, createHeapBigInt(0n), Equal],
+    [-0.0, createHeapBigInt(0n), Equal],
+    [0.5, createHeapBigInt(-1n), Greater],
+    [0.5, createHeapBigInt(-2n), Greater],
+    [-1.5, createHeapBigInt(2n), Less],
+    [-1.5, createHeapBigInt(1n), Less],
+    [-1.5, createHeapBigInt(0n), Less],
+    [-1.0, createHeapBigInt(-1n), Equal],
+    [-1.5, createHeapBigInt(-2n), Greater],
+
+    [1n, NaN, Undefined],
+    [0n, NaN, Undefined],
+    [-1n, NaN, Undefined],
+
+    [NaN, 1n, Undefined],
+    [NaN, 0n, Undefined],
+    [NaN, -1n, Undefined],
+
+    [createHeapBigInt(1n), NaN, Undefined],
+    [createHeapBigInt(0n), NaN, Undefined],
+    [createHeapBigInt(-1n), NaN, Undefined],
+
+    [NaN, createHeapBigInt(1n), Undefined],
+    [NaN, createHeapBigInt(0n), Undefined],
+    [NaN, createHeapBigInt(-1n), Undefined],
+
+    [1n, Infinity, Less],
+    [0n, Infinity, Less],
+    [-1n, Infinity, Less],
+
+    [Infinity, 1n, Greater],
+    [Infinity, 0n, Greater],
+    [Infinity, -1n, Greater],
+
+    [createHeapBigInt(1n), Infinity, Less],
+    [createHeapBigInt(0n), Infinity, Less],
+    [createHeapBigInt(-1n), Infinity, Less],
+
+    [Infinity, createHeapBigInt(1n), Greater],
+    [Infinity, createHeapBigInt(0n), Greater],
+    [Infinity, createHeapBigInt(-1n), Greater],
+
+    [1n, -Infinity, Greater],
+    [0n, -Infinity, Greater],
+    [-1n, -Infinity, Greater],
+
+    [-Infinity, 1n, Less],
+    [-Infinity, 0n, Less],
+    [-Infinity, -1n, Less],
+
+    [createHeapBigInt(1n), -Infinity, Greater],
+    [createHeapBigInt(0n), -Infinity, Greater],
+    [createHeapBigInt(-1n), -Infinity, Greater],
+
+    [-Infinity, createHeapBigInt(1n), Less],
+    [-Infinity, createHeapBigInt(0n), Less],
+    [-Infinity, createHeapBigInt(-1n), Less],
+
+    [createHeapBigInt(1000000000000000000000000n), Infinity, Less],
+    [Infinity, createHeapBigInt(1000000000000000000000000n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), -Infinity, Greater],
+    [-Infinity, createHeapBigInt(1000000000000000000000000n), Less],
+
+    [createHeapBigInt(-1000000000000000000000000n), Infinity, Less],
+    [Infinity, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [createHeapBigInt(-1000000000000000000000000n), -Infinity, Greater],
+    [-Infinity, createHeapBigInt(-1000000000000000000000000n), Less],
+];
+
+function lessThan(a, b)
+{
+    return a < b;
+}
+noInline(lessThan);
+
+function lessThanEqual(a, b)
+{
+    return a <= b;
+}
+noInline(lessThanEqual);
+
+function greaterThan(a, b)
+{
+    return a > b;
+}
+noInline(greaterThan);
+
+function greaterThanEqual(a, b)
+{
+    return a >= b;
+}
+noInline(greaterThanEqual);
+
+function equal(a, b)
+{
+    return a == b;
+}
+noInline(equal);
+
+for (var i = 0; i < 1e3; ++i) {
+    for (let [a, b, res] of list) {
+        shouldBe(lessThan(a, b), result(lessThan, res));
+        shouldBe(lessThanEqual(a, b), result(lessThanEqual, res));
+        shouldBe(greaterThan(a, b), result(greaterThan, res));
+        shouldBe(greaterThanEqual(a, b), result(greaterThanEqual, res));
+        shouldBe(equal(a, b), result(equal, res));
+    }
+}

Added: trunk/JSTests/stress/compare-bigint-with-string.js (0 => 260660)


--- trunk/JSTests/stress/compare-bigint-with-string.js	                        (rev 0)
+++ trunk/JSTests/stress/compare-bigint-with-string.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,236 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+const Greater = 0;
+const Less = 1;
+const Equal = 2;
+const Undefined = 3;
+
+function result(func, data)
+{
+    if (data ="" Undefined)
+        return false;
+    if (func === lessThan)
+        return data ="" Less;
+    if (func === lessThanEqual)
+        return data ="" Less || data ="" Equal;
+    if (func === greaterThan)
+        return data ="" Greater;
+    if (func === greaterThanEqual)
+        return data ="" Greater || data ="" Equal;
+    if (func === equal)
+        return data ="" Equal;
+    return false;
+}
+
+var list = [
+    [createHeapBigInt(1n), "2", Less],
+    [createHeapBigInt(1n), "1", Equal],
+    [createHeapBigInt(1n), "0", Greater],
+    [createHeapBigInt(1n), "-1", Greater],
+    [createHeapBigInt(1n), "-2", Greater],
+    [createHeapBigInt(0n), "2", Less],
+    [createHeapBigInt(0n), "1", Less],
+    [createHeapBigInt(0n), "0", Equal],
+    [createHeapBigInt(0n), "-1", Greater],
+    [createHeapBigInt(0n), "-2", Greater],
+    [createHeapBigInt(-1n), "2", Less],
+    [createHeapBigInt(-1n), "1", Less],
+    [createHeapBigInt(-1n), "0", Less],
+    [createHeapBigInt(-1n), "-1", Equal],
+    [createHeapBigInt(-1n), "-2", Greater],
+
+    ["1", createHeapBigInt(2n), Less],
+    ["1", createHeapBigInt(1n), Equal],
+    ["1", createHeapBigInt(0n), Greater],
+    ["1", createHeapBigInt(-1n), Greater],
+    ["1", createHeapBigInt(-2n), Greater],
+    ["0", createHeapBigInt(2n), Less],
+    ["0", createHeapBigInt(1n), Less],
+    ["0", createHeapBigInt(0n), Equal],
+    ["0", createHeapBigInt(-1n), Greater],
+    ["0", createHeapBigInt(-2n), Greater],
+    ["-1", createHeapBigInt(2n), Less],
+    ["-1", createHeapBigInt(1n), Less],
+    ["-1", createHeapBigInt(0n), Less],
+    ["-1", createHeapBigInt(-1n), Equal],
+    ["-1", createHeapBigInt(-2n), Greater],
+
+    ["1", 2n, Less],
+    ["1", 1n, Equal],
+    ["1", 0n, Greater],
+    ["1", -1n, Greater],
+    ["1", -2n, Greater],
+    ["0", 2n, Less],
+    ["0", 1n, Less],
+    ["0", 0n, Equal],
+    ["0", -1n, Greater],
+    ["0", -2n, Greater],
+    ["-1", 2n, Less],
+    ["-1", 1n, Less],
+    ["-1", 0n, Less],
+    ["-1", -1n, Equal],
+    ["-1", -2n, Greater],
+
+    [1n, "2", Less],
+    [1n, "1", Equal],
+    [1n, "0", Greater],
+    [1n, "-1", Greater],
+    [1n, "-2", Greater],
+    [0n, "2", Less],
+    [0n, "1", Less],
+    [0n, "0", Equal],
+    [0n, "-1", Greater],
+    [0n, "-2", Greater],
+    [-1n, "2", Less],
+    [-1n, "1", Less],
+    [-1n, "0", Less],
+    [-1n, "-1", Equal],
+    [-1n, "-2", Greater],
+
+    [createHeapBigInt(1000000000000000000000000n), "2", Greater],
+    [createHeapBigInt(1000000000000000000000000n), "1", Greater],
+    [createHeapBigInt(1000000000000000000000000n), "0", Greater],
+    [createHeapBigInt(1000000000000000000000000n), "-1", Greater],
+    [createHeapBigInt(1000000000000000000000000n), "-2", Greater],
+    [createHeapBigInt(-1000000000000000000000000n), "2", Less],
+    [createHeapBigInt(-1000000000000000000000000n), "1", Less],
+    [createHeapBigInt(-1000000000000000000000000n), "0", Less],
+    [createHeapBigInt(-1000000000000000000000000n), "-1", Less],
+    [createHeapBigInt(-1000000000000000000000000n), "-2", Less],
+
+    ["2", createHeapBigInt(1000000000000000000000000n), Less],
+    ["1", createHeapBigInt(1000000000000000000000000n), Less],
+    ["0", createHeapBigInt(1000000000000000000000000n), Less],
+    ["-1", createHeapBigInt(1000000000000000000000000n), Less],
+    ["-2", createHeapBigInt(1000000000000000000000000n), Less],
+    ["2", createHeapBigInt(-1000000000000000000000000n), Greater],
+    ["1", createHeapBigInt(-1000000000000000000000000n), Greater],
+    ["0", createHeapBigInt(-1000000000000000000000000n), Greater],
+    ["-1", createHeapBigInt(-1000000000000000000000000n), Greater],
+    ["-2", createHeapBigInt(-1000000000000000000000000n), Greater],
+
+    ["1.5", 2n, Undefined],
+    ["1.0", 1n, Undefined],
+    ["1.5", 0n, Undefined],
+    ["1.5", -1n, Undefined],
+    ["1.5", -2n, Undefined],
+    ["0.5", 2n, Undefined],
+    ["0.5", 1n, Undefined],
+    ["-0.0", 0n, Undefined],
+    ["0.0", 0n, Undefined],
+    ["0.5", -1n, Undefined],
+    ["0.5", -2n, Undefined],
+    ["-1.5", 2n, Undefined],
+    ["-1.5", 1n, Undefined],
+    ["-1.5", 0n, Undefined],
+    ["-1.0", -1n, Undefined],
+    ["-1.5", -2n, Undefined],
+
+    [1n, "2.5", Undefined],
+    [1n, "1.0", Undefined],
+    [1n, "0.5", Undefined],
+    [1n, "-1.5", Undefined],
+    [1n, "-2.5", Undefined],
+    [0n, "2.5", Undefined],
+    [0n, "1.0", Undefined],
+    [0n, "0.0", Undefined],
+    [0n, "-0.0", Undefined],
+    [0n, "-1.5", Undefined],
+    [0n, "-2.5", Undefined],
+    [-1n, "2.5", Undefined],
+    [-1n, "1.0", Undefined],
+    [-1n, "0.5", Undefined],
+    [-1n, "-1.0", Undefined],
+    [-1n, "-2.5", Undefined],
+
+    [createHeapBigInt(1n), "2.5", Undefined],
+    [createHeapBigInt(1n), "1.0", Undefined],
+    [createHeapBigInt(1n), "0.5", Undefined],
+    [createHeapBigInt(1n), "-1.5", Undefined],
+    [createHeapBigInt(1n), "-2.5", Undefined],
+    [createHeapBigInt(0n), "2.5", Undefined],
+    [createHeapBigInt(0n), "1.5", Undefined],
+    [createHeapBigInt(0n), "0.0", Undefined],
+    [createHeapBigInt(0n), "-0.0", Undefined],
+    [createHeapBigInt(0n), "-1.5", Undefined],
+    [createHeapBigInt(0n), "-2.5", Undefined],
+    [createHeapBigInt(-1n), "2.5", Undefined],
+    [createHeapBigInt(-1n), "1.5", Undefined],
+    [createHeapBigInt(-1n), "0.5", Undefined],
+    [createHeapBigInt(-1n), "-1.0", Undefined],
+    [createHeapBigInt(-1n), "-2.5", Undefined],
+
+    ["1.5", createHeapBigInt(2n), Undefined],
+    ["1.0", createHeapBigInt(1n), Undefined],
+    ["1.5", createHeapBigInt(0n), Undefined],
+    ["1.5", createHeapBigInt(-1n), Undefined],
+    ["1.5", createHeapBigInt(-2n), Undefined],
+    ["0.5", createHeapBigInt(2n), Undefined],
+    ["0.5", createHeapBigInt(1n), Undefined],
+    ["0.0", createHeapBigInt(0n), Undefined],
+    ["-0.0", createHeapBigInt(0n), Undefined],
+    ["0.5", createHeapBigInt(-1n), Undefined],
+    ["0.5", createHeapBigInt(-2n), Undefined],
+    ["-1.5", createHeapBigInt(2n), Undefined],
+    ["-1.5", createHeapBigInt(1n), Undefined],
+    ["-1.5", createHeapBigInt(0n), Undefined],
+    ["-1.0", createHeapBigInt(-1n), Undefined],
+    ["-1.5", createHeapBigInt(-2n), Undefined],
+
+    [createHeapBigInt(1000000000000000000000000n), "100000000000000000000000000000000000", Less],
+    ["100000000000000000000000000000000000", createHeapBigInt(1000000000000000000000000n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), "-100000000000000000000000000000000000", Greater],
+    ["-100000000000000000000000000000000000", createHeapBigInt(1000000000000000000000000n), Less],
+    [createHeapBigInt(1000000000000000000000000n), "1000000000000000000000000", Equal],
+    ["1000000000000000000000000", createHeapBigInt(1000000000000000000000000n), Equal],
+    [createHeapBigInt(-1000000000000000000000000n), "-1000000000000000000000000", Equal],
+    ["-1000000000000000000000000", createHeapBigInt(-1000000000000000000000000n), Equal],
+
+    [20n, "100000000000000000000000000000000000", Less],
+    ["100000000000000000000000000000000000", 20n, Greater],
+    [20n, "-100000000000000000000000000000000000", Greater],
+    ["-100000000000000000000000000000000000", 20n, Less],
+];
+
+function lessThan(a, b)
+{
+    return a < b;
+}
+noInline(lessThan);
+
+function lessThanEqual(a, b)
+{
+    return a <= b;
+}
+noInline(lessThanEqual);
+
+function greaterThan(a, b)
+{
+    return a > b;
+}
+noInline(greaterThan);
+
+function greaterThanEqual(a, b)
+{
+    return a >= b;
+}
+noInline(greaterThanEqual);
+
+function equal(a, b)
+{
+    return a == b;
+}
+noInline(equal);
+
+for (var i = 0; i < 1e3; ++i) {
+    for (let [a, b, res] of list) {
+        shouldBe(lessThan(a, b), result(lessThan, res));
+        shouldBe(lessThanEqual(a, b), result(lessThanEqual, res));
+        shouldBe(greaterThan(a, b), result(greaterThan, res));
+        shouldBe(greaterThanEqual(a, b), result(greaterThanEqual, res));
+        shouldBe(equal(a, b), result(equal, res));
+    }
+}

Added: trunk/JSTests/stress/compare-bigint.js (0 => 260660)


--- trunk/JSTests/stress/compare-bigint.js	                        (rev 0)
+++ trunk/JSTests/stress/compare-bigint.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,151 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+const Greater = 0;
+const Less = 1;
+const Equal = 2;
+
+function result(func, data)
+{
+    if (func === lessThan)
+        return data ="" Less;
+    if (func === lessThanEqual)
+        return data ="" Less || data ="" Equal;
+    if (func === greaterThan)
+        return data ="" Greater;
+    if (func === greaterThanEqual)
+        return data ="" Greater || data ="" Equal;
+    if (func === equal)
+        return data ="" Equal;
+    return false;
+}
+
+var list = [
+    [createHeapBigInt(1n), 2n, Less],
+    [createHeapBigInt(1n), 1n, Equal],
+    [createHeapBigInt(1n), 0n, Greater],
+    [createHeapBigInt(1n), -1n, Greater],
+    [createHeapBigInt(1n), -2n, Greater],
+    [createHeapBigInt(0n), 2n, Less],
+    [createHeapBigInt(0n), 1n, Less],
+    [createHeapBigInt(0n), 0n, Equal],
+    [createHeapBigInt(0n), -1n, Greater],
+    [createHeapBigInt(0n), -2n, Greater],
+    [createHeapBigInt(-1n), 2n, Less],
+    [createHeapBigInt(-1n), 1n, Less],
+    [createHeapBigInt(-1n), 0n, Less],
+    [createHeapBigInt(-1n), -1n, Equal],
+    [createHeapBigInt(-1n), -2n, Greater],
+
+    [1n, createHeapBigInt(2n), Less],
+    [1n, createHeapBigInt(1n), Equal],
+    [1n, createHeapBigInt(0n), Greater],
+    [1n, createHeapBigInt(-1n), Greater],
+    [1n, createHeapBigInt(-2n), Greater],
+    [0n, createHeapBigInt(2n), Less],
+    [0n, createHeapBigInt(1n), Less],
+    [0n, createHeapBigInt(0n), Equal],
+    [0n, createHeapBigInt(-1n), Greater],
+    [0n, createHeapBigInt(-2n), Greater],
+    [-1n, createHeapBigInt(2n), Less],
+    [-1n, createHeapBigInt(1n), Less],
+    [-1n, createHeapBigInt(0n), Less],
+    [-1n, createHeapBigInt(-1n), Equal],
+    [-1n, createHeapBigInt(-2n), Greater],
+
+    [1n, 2n, Less],
+    [1n, 1n, Equal],
+    [1n, 0n, Greater],
+    [1n, -1n, Greater],
+    [1n, -2n, Greater],
+    [0n, 2n, Less],
+    [0n, 1n, Less],
+    [0n, 0n, Equal],
+    [0n, -1n, Greater],
+    [0n, -2n, Greater],
+    [-1n, 2n, Less],
+    [-1n, 1n, Less],
+    [-1n, 0n, Less],
+    [-1n, -1n, Equal],
+    [-1n, -2n, Greater],
+
+    [createHeapBigInt(1n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(1n), createHeapBigInt(1n), Equal],
+    [createHeapBigInt(1n), createHeapBigInt(0n), Greater],
+    [createHeapBigInt(1n), createHeapBigInt(-1n), Greater],
+    [createHeapBigInt(1n), createHeapBigInt(-2n), Greater],
+    [createHeapBigInt(0n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(0n), createHeapBigInt(1n), Less],
+    [createHeapBigInt(0n), createHeapBigInt(0n), Equal],
+    [createHeapBigInt(0n), createHeapBigInt(-1n), Greater],
+    [createHeapBigInt(0n), createHeapBigInt(-2n), Greater],
+    [createHeapBigInt(-1n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(1n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(0n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(-1n), Equal],
+    [createHeapBigInt(-1n), createHeapBigInt(-2n), Greater],
+
+    [createHeapBigInt(1000000000000000000000000n), 2n, Greater],
+    [createHeapBigInt(1000000000000000000000000n), 1n, Greater],
+    [createHeapBigInt(1000000000000000000000000n), 0n, Greater],
+    [createHeapBigInt(1000000000000000000000000n), -1n, Greater],
+    [createHeapBigInt(1000000000000000000000000n), -2n, Greater],
+    [createHeapBigInt(-1000000000000000000000000n), 2n, Less],
+    [createHeapBigInt(-1000000000000000000000000n), 1n, Less],
+    [createHeapBigInt(-1000000000000000000000000n), 0n, Less],
+    [createHeapBigInt(-1000000000000000000000000n), -1n, Less],
+    [createHeapBigInt(-1000000000000000000000000n), -2n, Less],
+
+    [2n, createHeapBigInt(1000000000000000000000000n), Less],
+    [1n, createHeapBigInt(1000000000000000000000000n), Less],
+    [0n, createHeapBigInt(1000000000000000000000000n), Less],
+    [-1n, createHeapBigInt(1000000000000000000000000n), Less],
+    [-2n, createHeapBigInt(1000000000000000000000000n), Less],
+    [2n, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [1n, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [0n, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [-1n, createHeapBigInt(-1000000000000000000000000n), Greater],
+    [-2n, createHeapBigInt(-1000000000000000000000000n), Greater],
+];
+
+function lessThan(a, b)
+{
+    return a < b;
+}
+noInline(lessThan);
+
+function lessThanEqual(a, b)
+{
+    return a <= b;
+}
+noInline(lessThanEqual);
+
+function greaterThan(a, b)
+{
+    return a > b;
+}
+noInline(greaterThan);
+
+function greaterThanEqual(a, b)
+{
+    return a >= b;
+}
+noInline(greaterThanEqual);
+
+function equal(a, b)
+{
+    return a == b;
+}
+noInline(equal);
+
+for (var i = 0; i < 1e3; ++i) {
+    for (let [a, b, res] of list) {
+        shouldBe(lessThan(a, b), result(lessThan, res));
+        shouldBe(lessThanEqual(a, b), result(lessThanEqual, res));
+        shouldBe(greaterThan(a, b), result(greaterThan, res));
+        shouldBe(greaterThanEqual(a, b), result(greaterThanEqual, res));
+        shouldBe(equal(a, b), result(equal, res));
+    }
+}

Added: trunk/JSTests/stress/compare-bigint32.js (0 => 260660)


--- trunk/JSTests/stress/compare-bigint32.js	                        (rev 0)
+++ trunk/JSTests/stress/compare-bigint32.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,81 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+const Greater = 0;
+const Less = 1;
+const Equal = 2;
+
+function result(func, data)
+{
+    if (func === lessThan)
+        return data ="" Less;
+    if (func === lessThanEqual)
+        return data ="" Less || data ="" Equal;
+    if (func === greaterThan)
+        return data ="" Greater;
+    if (func === greaterThanEqual)
+        return data ="" Greater || data ="" Equal;
+    if (func === equal)
+        return data ="" Equal;
+    return false;
+}
+
+var list = [
+    [1n, 2n, Less],
+    [1n, 1n, Equal],
+    [1n, 0n, Greater],
+    [1n, -1n, Greater],
+    [1n, -2n, Greater],
+    [0n, 2n, Less],
+    [0n, 1n, Less],
+    [0n, 0n, Equal],
+    [0n, -1n, Greater],
+    [0n, -2n, Greater],
+    [-1n, 2n, Less],
+    [-1n, 1n, Less],
+    [-1n, 0n, Less],
+    [-1n, -1n, Equal],
+    [-1n, -2n, Greater],
+];
+
+function lessThan(a, b)
+{
+    return a < b;
+}
+noInline(lessThan);
+
+function lessThanEqual(a, b)
+{
+    return a <= b;
+}
+noInline(lessThanEqual);
+
+function greaterThan(a, b)
+{
+    return a > b;
+}
+noInline(greaterThan);
+
+function greaterThanEqual(a, b)
+{
+    return a >= b;
+}
+noInline(greaterThanEqual);
+
+function equal(a, b)
+{
+    return a == b;
+}
+noInline(equal);
+
+for (var i = 0; i < 1e3; ++i) {
+    for (let [a, b, res] of list) {
+        shouldBe(lessThan(a, b), result(lessThan, res));
+        shouldBe(lessThanEqual(a, b), result(lessThanEqual, res));
+        shouldBe(greaterThan(a, b), result(greaterThan, res));
+        shouldBe(greaterThanEqual(a, b), result(greaterThanEqual, res));
+        shouldBe(equal(a, b), result(equal, res));
+    }
+}

Added: trunk/JSTests/stress/compare-heap-bigint.js (0 => 260660)


--- trunk/JSTests/stress/compare-heap-bigint.js	                        (rev 0)
+++ trunk/JSTests/stress/compare-heap-bigint.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,103 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+const Greater = 0;
+const Less = 1;
+const Equal = 2;
+
+function result(func, data)
+{
+    if (func === lessThan)
+        return data ="" Less;
+    if (func === lessThanEqual)
+        return data ="" Less || data ="" Equal;
+    if (func === greaterThan)
+        return data ="" Greater;
+    if (func === greaterThanEqual)
+        return data ="" Greater || data ="" Equal;
+    if (func === equal)
+        return data ="" Equal;
+    return false;
+}
+
+var list = [
+    [createHeapBigInt(1n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(1n), createHeapBigInt(1n), Equal],
+    [createHeapBigInt(1n), createHeapBigInt(0n), Greater],
+    [createHeapBigInt(1n), createHeapBigInt(-1n), Greater],
+    [createHeapBigInt(1n), createHeapBigInt(-2n), Greater],
+    [createHeapBigInt(0n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(0n), createHeapBigInt(1n), Less],
+    [createHeapBigInt(0n), createHeapBigInt(0n), Equal],
+    [createHeapBigInt(0n), createHeapBigInt(-1n), Greater],
+    [createHeapBigInt(0n), createHeapBigInt(-2n), Greater],
+    [createHeapBigInt(-1n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(1n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(0n), Less],
+    [createHeapBigInt(-1n), createHeapBigInt(-1n), Equal],
+    [createHeapBigInt(-1n), createHeapBigInt(-2n), Greater],
+
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(2n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(1n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(0n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(-1n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(-2n), Greater],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(2n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(1n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(0n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(-1n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(-2n), Less],
+
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(1000000000000000000000002n), Less],
+    [createHeapBigInt(1000000000000000000000001n), createHeapBigInt(1000000000000000000000000n), Greater],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(1000000000000000000000000n), Equal],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(-1000000000000000000000000n), Equal],
+    [createHeapBigInt(1000000000000000000000000n), createHeapBigInt(-1000000000000000000000001n), Greater],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(1000000000000000000000002n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(1000000000000000000000001n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(1000000000000000000000000n), Less],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(-1000000000000000000000001n), Greater],
+    [createHeapBigInt(-1000000000000000000000000n), createHeapBigInt(-1000000000000000000000002n), Greater],
+];
+
+function lessThan(a, b)
+{
+    return a < b;
+}
+noInline(lessThan);
+
+function lessThanEqual(a, b)
+{
+    return a <= b;
+}
+noInline(lessThanEqual);
+
+function greaterThan(a, b)
+{
+    return a > b;
+}
+noInline(greaterThan);
+
+function greaterThanEqual(a, b)
+{
+    return a >= b;
+}
+noInline(greaterThanEqual);
+
+function equal(a, b)
+{
+    return a == b;
+}
+noInline(equal);
+
+for (var i = 0; i < 1e3; ++i) {
+    for (let [a, b, res] of list) {
+        shouldBe(lessThan(a, b), result(lessThan, res));
+        shouldBe(lessThanEqual(a, b), result(lessThanEqual, res));
+        shouldBe(greaterThan(a, b), result(greaterThan, res));
+        shouldBe(greaterThanEqual(a, b), result(greaterThanEqual, res));
+        shouldBe(equal(a, b), result(equal, res));
+    }
+}

Added: trunk/JSTests/stress/dfg-ai-fold-bigint.js (0 => 260660)


--- trunk/JSTests/stress/dfg-ai-fold-bigint.js	                        (rev 0)
+++ trunk/JSTests/stress/dfg-ai-fold-bigint.js	2020-04-24 19:19:23 UTC (rev 260660)
@@ -0,0 +1,90 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function allAreTrue(list)
+{
+    for (let item of list)
+        shouldBe(item, true);
+}
+
+function allAreFalse(list)
+{
+    for (let item of list)
+        shouldBe(item, false);
+}
+
+function lessThan()
+{
+    return [0n < 2n, -10n < 20n, -10n < -2n, -100000000000000n < 0n, -100000000000000n < 10000n, -100000000000000n < -10000n, -1000000000000000000000n < -100000000000n, 1000000000000000000000n < 1000000000000000000000000n];
+}
+noInline(lessThan);
+
+function lessThanFalse()
+{
+    return [100000000000000000000n < 100000000000000000000n, 0n < 0n, 2n < 0n, 2n < 2n, -10n < -10n, 20n < -20n, -2n < -10n, 0n < -100000000000000n, -10000n < -100000000000000n, -100000000000n < -1000000000000000000000n, 1000000000000000000000000n < 1000000000000000000000n ];
+}
+noInline(lessThanFalse);
+
+function lessThanEqual()
+{
+    return [100000000000000000000n <= 100000000000000000000n, 0n <= 0n, 0n <= 2n, 2n <= 2n, -10n <= -10n, -20n <= 20n, -10n <= -2n, -100000000000000n <= 0n, -100000000000000n <= -10000n, -1000000000000000000000n <= -100000000000n, 1000000000000000000000n <= 1000000000000000000000000n ];
+}
+noInline(lessThanEqual);
+
+function lessThanEqualFalse()
+{
+    return [100000000000000000001n <= 100000000000000000000n, 1n <= 0n, 2n <= 0n, 3n <= 2n, -10n <= -11n, 20n <= -20n, -2n <= -10n, 0n <= -100000000000000n, -10000n <= -100000000000000n, -100000000000n <= -1000000000000000000000n, 1000000000000000000000000n <= 1000000000000000000000n ];
+}
+noInline(lessThanEqualFalse);
+
+function greaterThan()
+{
+    return [2n > 0n, 20n > -10n, -2n > -10n, 0n > -100000000000000n, 10000n > -100000000000000n, -10000n > -100000000000000n, -100000000000n > -1000000000000000000000n, 1000000000000000000000000n > 1000000000000000000000n ];
+}
+noInline(greaterThan);
+
+function greaterThanFalse()
+{
+    return [100000000000000000000n > 100000000000000000000n, 0n > 0n, 0n > 2n, 2n > 2n, -10n > -10n, -20n > 20n, -10n > -2n, -100000000000000n > 0n, -100000000000000n > -10000n, -1000000000000000000000n > -100000000000n, 1000000000000000000000n > 1000000000000000000000000n ];
+}
+noInline(greaterThanFalse);
+
+function greaterThanEqual()
+{
+    return [100000000000000000000n >= 100000000000000000000n, 0n >= 0n, 2n >= 0n, 2n >= 2n, -10n >= -10n, 20n >= -20n, -2n >= -10n, 0n >= -100000000000000n, -10000n >= -100000000000000n, -100000000000n >= -1000000000000000000000n, 1000000000000000000000000n >= 1000000000000000000000n ];
+}
+noInline(greaterThanEqual);
+
+function greaterThanEqualFalse()
+{
+    return [100000000000000000000n >= 100000000000000000001n, 0n >= 1n, 0n >= 2n, 2n >= 3n, -11n >= -10n, -20n >= 20n, -10n >= -2n, -100000000000000n >= 0n, -100000000000000n >= -10000n, -1000000000000000000000n >= -100000000000n, 1000000000000000000000n >= 1000000000000000000000000n ];
+}
+noInline(greaterThanEqualFalse);
+
+function equal()
+{
+    return [100000000000000000000n == 100000000000000000000n, 0n == 0n, 2n == 2n, -2n == -2n, -20n == -20n, -100000000000000n == -100000000000000n];
+}
+noInline(equal);
+
+function equalFalse()
+{
+    return [100000000000000000001n == 100000000000000000000n, 1n == 0n, -2n == 2n, 2n == -2n, -20n == 20n, -100000000000000n == 100000000000000n, 100000000000000n == -100000000000000n, -100000000000001n == -100000000000000n, 100000000000001n == 100000000000000n, -100000000000000n == 1n, 100000000000000n == 1n, -1n == 100000000000000n, 1n == -100000000000000n, -1n == -100000000000000n];
+}
+noInline(equalFalse);
+
+for (var i = 0; i < 1e4; ++i) {
+    allAreTrue(lessThan());
+    allAreTrue(lessThanEqual());
+    allAreTrue(greaterThan());
+    allAreTrue(greaterThanEqual());
+    allAreTrue(equal());
+
+    allAreFalse(lessThanFalse());
+    allAreFalse(lessThanEqualFalse());
+    allAreFalse(greaterThanFalse());
+    allAreFalse(greaterThanEqualFalse());
+    allAreFalse(equalFalse());
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (260659 => 260660)


--- trunk/Source/_javascript_Core/ChangeLog	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-04-24 19:19:23 UTC (rev 260660)
@@ -1,3 +1,47 @@
+2020-04-24  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG compare should speculate BigInt well
+        https://bugs.webkit.org/show_bug.cgi?id=210892
+
+        Reviewed by Saam Barati.
+
+        Compare operations in DFG does not support BigInt related speculations. As a result, DFG fixup phase emits DoubleRep for operands, and
+        causes OSR exit. This patch adds BigInt32, HeapBigInt, and AnyBigIntUse support to DFG compare operations to avoid OSR exits.
+        We also introduce JSBigInt::compareToInt32 to avoid allocating JSBigInt only for comparison, and optimize C++ runtime for JSBigInt comparison.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileValueAdd):
+        (JSC::DFG::SpeculativeJIT::compileValueSub):
+        (JSC::DFG::SpeculativeJIT::compileValueMul):
+        (JSC::DFG::SpeculativeJIT::compare):
+        (JSC::DFG::SpeculativeJIT::genericJSValueNonPeepholeCompare):
+        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompare): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileBigInt32Compare):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareEq):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        (JSC::FTL::DFG::LowerDFGToB3::compare):
+        (JSC::FTL::DFG::LowerDFGToB3::genericJSValueCompare):
+        (JSC::FTL::DFG::LowerDFGToB3::nonSpeculativeCompare): Deleted.
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::unboxBigInt32):
+        * runtime/JSBigInt.cpp:
+        (JSC::JSBigInt::compareToInt32):
+        * runtime/JSBigInt.h:
+        (JSC::swapBigIntCompareResult):
+        * runtime/Operations.h:
+        (JSC::compareBigInt):
+        (JSC::compareBigInt32ToOtherPrimitive):
+        (JSC::bigIntCompare):
+
 2020-04-24  Alexey Shvayka  <[email protected]>
 
         Proxy.revocable should not have [[Construct]] slot

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-04-24 19:19:23 UTC (rev 260660)
@@ -1855,23 +1855,45 @@
         JSValue rightConst = forNode(node->child2()).value();
         if (leftConst && rightConst) {
             if (leftConst.isNumber() && rightConst.isNumber()) {
+                auto compareNumber = [&](double a, double b) {
+                    switch (node->op()) {
+                    case CompareLess:
+                        return jsBoolean(a < b);
+                    case CompareLessEq:
+                        return jsBoolean(a <= b);
+                    case CompareGreater:
+                        return jsBoolean(a > b);
+                    case CompareGreaterEq:
+                        return jsBoolean(a >= b);
+                    case CompareEq:
+                        return jsBoolean(a == b);
+                    default:
+                        RELEASE_ASSERT_NOT_REACHED();
+                        break;
+                    }
+                };
                 double a = leftConst.asNumber();
                 double b = rightConst.asNumber();
+                setConstant(node, compareNumber(a, b));
+                break;
+            }
+
+            if (leftConst.isBigInt() && rightConst.isBigInt()) {
                 switch (node->op()) {
                 case CompareLess:
-                    setConstant(node, jsBoolean(a < b));
+                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(leftConst, rightConst), JSBigInt::ComparisonMode::LessThan)));
                     break;
                 case CompareLessEq:
-                    setConstant(node, jsBoolean(a <= b));
+                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(leftConst, rightConst), JSBigInt::ComparisonMode::LessThanOrEqual)));
                     break;
                 case CompareGreater:
-                    setConstant(node, jsBoolean(a > b));
+                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(rightConst, leftConst), JSBigInt::ComparisonMode::LessThan)));
                     break;
                 case CompareGreaterEq:
-                    setConstant(node, jsBoolean(a >= b));
+                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(rightConst, leftConst), JSBigInt::ComparisonMode::LessThanOrEqual)));
                     break;
                 case CompareEq:
-                    setConstant(node, jsBoolean(a == b));
+                    setConstant(node, jsBoolean(compareBigInt(leftConst, rightConst) == JSBigInt::ComparisonResult::Equal));
                     break;
                 default:
                     RELEASE_ASSERT_NOT_REACHED();
@@ -1947,6 +1969,9 @@
         if (node->child1() == node->child2()) {
             if (node->isBinaryUseKind(Int32Use) ||
                 node->isBinaryUseKind(Int52RepUse) ||
+                node->isBinaryUseKind(BigInt32Use) ||
+                node->isBinaryUseKind(HeapBigIntUse) ||
+                node->isBinaryUseKind(AnyBigIntUse) ||
                 node->isBinaryUseKind(StringUse) ||
                 node->isBinaryUseKind(BooleanUse) ||
                 node->isBinaryUseKind(SymbolUse) ||

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -434,11 +434,14 @@
     case CompareLessEq:
     case CompareGreater:
     case CompareGreaterEq:
+        // FIXME: Add AnyBigIntUse and HeapBigIntUse specific optimizations in DFG / FTL code generation and ensure it does not perform GC.
+        // https://bugs.webkit.org/show_bug.cgi?id=210923
         if (node->isBinaryUseKind(Int32Use)
 #if USE(JSVALUE64)
             || node->isBinaryUseKind(Int52RepUse)
 #endif
             || node->isBinaryUseKind(DoubleRepUse)
+            || node->isBinaryUseKind(BigInt32Use)
             || node->isBinaryUseKind(StringIdentUse)
             )
             return false;

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -872,6 +872,26 @@
                 node->clearFlags(NodeMustGenerate);
                 break;
             }
+            if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child2().node())) {
+                fixEdge<HeapBigIntUse>(node->child1());
+                fixEdge<HeapBigIntUse>(node->child2());
+                node->clearFlags(NodeMustGenerate);
+                return;
+            }
+#if USE(BIGINT32)
+            if (Node::shouldSpeculateBigInt32(node->child1().node(), node->child2().node())) {
+                fixEdge<BigInt32Use>(node->child1());
+                fixEdge<BigInt32Use>(node->child2());
+                node->clearFlags(NodeMustGenerate);
+                return;
+            }
+            if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
+                fixEdge<AnyBigIntUse>(node->child1());
+                fixEdge<AnyBigIntUse>(node->child2());
+                node->clearFlags(NodeMustGenerate);
+                return;
+            }
+#endif
             if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
                 fixDoubleOrBooleanEdge(node->child1());
                 fixDoubleOrBooleanEdge(node->child2());

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -4028,18 +4028,16 @@
     if (node->isBinaryUseKind(BigInt32Use)) {
         SpeculateBigInt32Operand left(this, leftChild);
         SpeculateBigInt32Operand right(this, rightChild);
+        GPRTemporary result(this);
+        GPRTemporary temp(this);
 
-        // FIXME: do we really need this extra register, or can we mutate left/right ?
-        // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
-        GPRTemporary result(this);
+        GPRReg leftGPR = left.gpr();
+        GPRReg rightGPR = right.gpr();
         GPRReg resultGPR = result.gpr();
-        GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
 
-        m_jit.move(left.gpr(), resultGPR);
-        m_jit.unboxBigInt32(resultGPR);
-        m_jit.move(right.gpr(), tempGPR);
-        m_jit.unboxBigInt32(tempGPR);
+        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);
@@ -4134,18 +4132,16 @@
     if (node->binaryUseKind() == BigInt32Use) {
         SpeculateBigInt32Operand left(this, node->child1());
         SpeculateBigInt32Operand right(this, node->child2());
+        GPRTemporary result(this);
+        GPRTemporary temp(this);
 
-        // FIXME: do we really need this extra register, or can we mutate left/right ?
-        // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
-        GPRTemporary result(this);
+        GPRReg leftGPR = left.gpr();
+        GPRReg rightGPR = right.gpr();
         GPRReg resultGPR = result.gpr();
-        GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
 
-        m_jit.move(left.gpr(), resultGPR);
-        m_jit.unboxBigInt32(resultGPR);
-        m_jit.move(right.gpr(), tempGPR);
-        m_jit.unboxBigInt32(tempGPR);
+        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);
@@ -4984,18 +4980,16 @@
         // 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());
         SpeculateBigInt32Operand right(this, node->child2());
+        GPRTemporary result(this);
+        GPRTemporary temp(this);
 
-        // FIXME: do we really need this extra register, or can we mutate left/right ?
-        // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
-        GPRTemporary result(this);
+        GPRReg leftGPR = left.gpr();
+        GPRReg rightGPR = right.gpr();
         GPRReg resultGPR = result.gpr();
-        GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
 
-        m_jit.move(left.gpr(), resultGPR);
-        m_jit.unboxBigInt32(resultGPR);
-        m_jit.move(right.gpr(), tempGPR);
-        m_jit.unboxBigInt32(tempGPR);
+        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);
@@ -6252,6 +6246,7 @@
         return false;
     }
 #endif
+
 #if USE(JSVALUE64)
     if (node->isBinaryUseKind(Int52RepUse)) {
         compileInt52Compare(node, condition);
@@ -6320,7 +6315,7 @@
         }
     }
 
-    nonSpeculativeNonPeepholeCompare(node, condition, operation);
+    genericJSValueNonPeepholeCompare(node, condition, operation);
     return false;
 }
 
@@ -14115,11 +14110,13 @@
     addSlowPathGenerator(WTFMove(slowPath));
 }
 
-void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_GJJ helperFunction)
+void SpeculativeJIT::genericJSValueNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_GJJ helperFunction)
 {
-    ASSERT(node->isBinaryUseKind(UntypedUse));
-    JSValueOperand arg1(this, node->child1());
-    JSValueOperand arg2(this, node->child2());
+    ASSERT(node->isBinaryUseKind(UntypedUse) || node->isBinaryUseKind(AnyBigIntUse) || node->isBinaryUseKind(HeapBigIntUse));
+    JSValueOperand arg1(this, node->child1(), ManualOperandSpeculation);
+    JSValueOperand arg2(this, node->child2(), ManualOperandSpeculation);
+    speculate(node, node->child1());
+    speculate(node, node->child2());
 
     JSValueRegs arg1Regs = arg1.jsValueRegs();
     JSValueRegs arg2Regs = arg2.jsValueRegs();

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2020-04-24 19:19:23 UTC (rev 260660)
@@ -743,7 +743,7 @@
     void nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode);
     
     void nonSpeculativePeepholeBranch(Node*, Node* branchNode, MacroAssembler::RelationalCondition, S_JITOperation_GJJ helperFunction);
-    void nonSpeculativeNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_GJJ helperFunction);
+    void genericJSValueNonPeepholeCompare(Node*, MacroAssembler::RelationalCondition, S_JITOperation_GJJ helperFunction);
     
     void nonSpeculativePeepholeStrictEq(Node*, Node* branchNode, bool invert = false);
     void genericJSValueNonPeepholeStrictEq(Node*, bool invert = false);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -1753,21 +1753,16 @@
 
     if (condition == MacroAssembler::Equal || condition == MacroAssembler::NotEqual) {
         // No need to unbox the operands, since the tag bits are identical
-        m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
+        m_jit.compare64(condition, op1GPR, op2GPR, resultGPR);
     } else {
         GPRTemporary temp(this);
         GPRReg tempGPR = temp.gpr();
 
-        m_jit.move(op1GPR, tempGPR);
-        m_jit.unboxBigInt32(tempGPR);
-        m_jit.move(op2GPR, resultGPR);
-        m_jit.unboxBigInt32(resultGPR);
-        m_jit.compare64(condition, tempGPR, resultGPR, resultGPR);
+        m_jit.unboxBigInt32(op1GPR, tempGPR);
+        m_jit.unboxBigInt32(op2GPR, resultGPR);
+        m_jit.compare32(condition, tempGPR, resultGPR, resultGPR);
     }
-
-    // If we add a DataFormatBool, we should use it here.
-    m_jit.or32(TrustedImm32(JSValue::ValueFalse), result.gpr());
-    jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
+    unblessedBooleanResult(resultGPR, node);
 }
 
 void SpeculativeJIT::compilePeepHoleBigInt32Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -8661,7 +8661,7 @@
         }
 
         DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse), m_node->child1().useKind(), m_node->child2().useKind());
-        nonSpeculativeCompare(
+        genericJSValueCompare(
             [&] (LValue left, LValue right) {
                 return m_out.equal(left, right);
             },
@@ -8949,7 +8949,7 @@
 
         // FIXME: we can do something much smarter here, see the DFGSpeculativeJIT approach in e.g. SpeculativeJIT::nonSpeculativePeepholeStrictEq
         DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse), m_node->child1().useKind(), m_node->child2().useKind());
-        nonSpeculativeCompare(
+        genericJSValueCompare(
             [&] (LValue left, LValue right) {
                 return m_out.equal(left, right);
             },
@@ -13556,6 +13556,13 @@
             return;
         }
 
+        if (m_node->isBinaryUseKind(BigInt32Use)) {
+            LValue left = lowBigInt32(m_node->child1());
+            LValue right = lowBigInt32(m_node->child2());
+            setBoolean(intFunctor(unboxBigInt32(left), unboxBigInt32(right)));
+            return;
+        }
+
         if (m_node->isBinaryUseKind(StringIdentUse)) {
             LValue left = lowStringIdent(m_node->child1());
             LValue right = lowStringIdent(m_node->child2());
@@ -13576,8 +13583,8 @@
             return;
         }
 
-        DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse), m_node->child1().useKind(), m_node->child2().useKind());
-        nonSpeculativeCompare(intFunctor, fallbackFunction);
+        DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse) || m_node->isBinaryUseKind(HeapBigIntUse) || m_node->isBinaryUseKind(AnyBigIntUse), m_node->child1().useKind(), m_node->child2().useKind());
+        genericJSValueCompare(intFunctor, fallbackFunction);
     }
 
     void compileStringSlice()
@@ -14547,11 +14554,13 @@
     }
 
     template<typename IntFunctor>
-    void nonSpeculativeCompare(const IntFunctor& intFunctor, S_JITOperation_GJJ helperFunction)
+    void genericJSValueCompare(const IntFunctor& intFunctor, S_JITOperation_GJJ helperFunction)
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-        LValue left = lowJSValue(m_node->child1());
-        LValue right = lowJSValue(m_node->child2());
+        LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
+        LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
+        speculate(m_node->child1());
+        speculate(m_node->child2());
         
         LBasicBlock leftIsInt = m_out.newBlock();
         LBasicBlock fastPath = m_out.newBlock();

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (260659 => 260660)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2020-04-24 19:19:23 UTC (rev 260660)
@@ -1398,9 +1398,14 @@
 #endif // USE(JSVALUE64)
 
 #if USE(BIGINT32)
-    void unboxBigInt32(GPRReg gpr)
+    void unboxBigInt32(GPRReg src, GPRReg dest)
     {
-        urshift64(trustedImm32ForShift(Imm32(16)), gpr);
+#if CPU(ARM64)
+        urshift64(src, trustedImm32ForShift(Imm32(16)), dest);
+#else
+        move(src, dest);
+        urshift64(trustedImm32ForShift(Imm32(16)), dest);
+#endif
     }
 
     void boxBigInt32(GPRReg gpr)

Modified: trunk/Source/_javascript_Core/runtime/JSBigInt.cpp (260659 => 260660)


--- trunk/Source/_javascript_Core/runtime/JSBigInt.cpp	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/runtime/JSBigInt.cpp	2020-04-24 19:19:23 UTC (rev 260660)
@@ -2020,6 +2020,36 @@
     return (this->length() == 1) && (this->sign() == (value < 0)) && (this->digit(0) == static_cast<Digit>(std::abs(static_cast<int64_t>(value))));
 }
 
+JSBigInt::ComparisonResult JSBigInt::compareToInt32(int32_t value)
+{
+    bool xSign = sign();
+    bool ySign = value < 0;
+
+    if (xSign != ySign)
+        return xSign ? ComparisonResult::LessThan : ComparisonResult::GreaterThan;
+    if (isZero()) {
+        ASSERT(!xSign);
+        ASSERT(!ySign);
+        if (value == 0)
+            return ComparisonResult::Equal;
+        return ComparisonResult::LessThan;
+    }
+
+    if (length() != 1)
+        return xSign ? ComparisonResult::LessThan : ComparisonResult::GreaterThan;
+
+    uint64_t value64 = 0;
+    if (xSign)
+        value64 = static_cast<uint64_t>(-static_cast<int64_t>(value));
+    else
+        value64 = value;
+    if (digit(0) == value64)
+        return ComparisonResult::Equal;
+    if (digit(0) < value64)
+        return xSign ? ComparisonResult::GreaterThan : ComparisonResult::LessThan;
+    return xSign ? ComparisonResult::LessThan : ComparisonResult::GreaterThan;
+}
+
 JSBigInt::ComparisonResult JSBigInt::compareToDouble(JSBigInt* x, double y)
 {
     // This algorithm expect that the double format is IEEE 754

Modified: trunk/Source/_javascript_Core/runtime/JSBigInt.h (260659 => 260660)


--- trunk/Source/_javascript_Core/runtime/JSBigInt.h	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/runtime/JSBigInt.h	2020-04-24 19:19:23 UTC (rev 260660)
@@ -124,6 +124,9 @@
     JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*);
     bool equalsToNumber(JSValue);
     JS_EXPORT_PRIVATE bool equalsToInt32(int32_t);
+    JS_EXPORT_PRIVATE ComparisonResult compareToInt32(int32_t);
+    JS_EXPORT_PRIVATE bool lessThanInt32(int32_t);
+    JS_EXPORT_PRIVATE bool lessThanEqualInt32(int32_t);
     static ComparisonResult compare(JSBigInt* x, JSBigInt* y);
 
     bool getPrimitiveNumber(JSGlobalObject*, double& number, JSValue& result) const;
@@ -287,4 +290,24 @@
     dataStorage()[n] = value;
 }
 
+#if !ASSERT_ENABLED
+IGNORE_RETURN_TYPE_WARNINGS_BEGIN
+#endif
+ALWAYS_INLINE JSBigInt::ComparisonResult invertBigIntCompareResult(JSBigInt::ComparisonResult comparisonResult)
+{
+    switch (comparisonResult) {
+    case JSBigInt::ComparisonResult::GreaterThan:
+        return JSBigInt::ComparisonResult::LessThan;
+    case JSBigInt::ComparisonResult::LessThan:
+        return JSBigInt::ComparisonResult::GreaterThan;
+    case JSBigInt::ComparisonResult::Equal:
+    case JSBigInt::ComparisonResult::Undefined:
+        return comparisonResult;
+    }
+    ASSERT_NOT_REACHED();
+}
+#if !ASSERT_ENABLED
+IGNORE_RETURN_TYPE_WARNINGS_END
+#endif
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (260659 => 260660)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2020-04-24 18:42:53 UTC (rev 260659)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2020-04-24 19:19:23 UTC (rev 260660)
@@ -238,6 +238,32 @@
     return ropeBuilder.release();
 }
 
+ALWAYS_INLINE JSBigInt::ComparisonResult compareBigInt(JSValue left, JSValue right)
+{
+    ASSERT(left.isBigInt());
+    ASSERT(right.isBigInt());
+#if USE(BIGINT32)
+    if (left.isBigInt32()) {
+        if (right.isBigInt32()) {
+            int32_t leftInt32 = left.bigInt32AsInt32();
+            int32_t rightInt32 = right.bigInt32AsInt32();
+            if (leftInt32 == rightInt32)
+                return JSBigInt::ComparisonResult::Equal;
+            if (leftInt32 < rightInt32)
+                return JSBigInt::ComparisonResult::LessThan;
+            return JSBigInt::ComparisonResult::GreaterThan;
+        }
+        ASSERT(right.isHeapBigInt());
+        return invertBigIntCompareResult(right.asHeapBigInt()->compareToInt32(left.bigInt32AsInt32()));
+    }
+    if (right.isBigInt32()) {
+        ASSERT(left.isHeapBigInt());
+        return left.asHeapBigInt()->compareToInt32(right.bigInt32AsInt32());
+    }
+#endif
+    return JSBigInt::compare(left.asHeapBigInt(), right.asHeapBigInt());
+}
+
 ALWAYS_INLINE JSBigInt::ComparisonResult compareBigIntToOtherPrimitive(JSGlobalObject* globalObject, JSBigInt* v1, JSValue primValue)
 {
     VM& vm = globalObject->vm();
@@ -267,6 +293,46 @@
     return JSBigInt::compareToDouble(v1, numberValue);
 }
 
+ALWAYS_INLINE JSBigInt::ComparisonResult compareBigInt32ToOtherPrimitive(JSGlobalObject* globalObject, int32_t v1, JSValue primValue)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    ASSERT(primValue.isPrimitive());
+    ASSERT(!primValue.isBigInt());
+
+    auto compare = [&] (auto v1, auto v2) {
+        static_assert(std::is_same_v<decltype(v1), decltype(v2)>);
+        if (v1 == v2)
+            return JSBigInt::ComparisonResult::Equal;
+        if (v1 < v2)
+            return JSBigInt::ComparisonResult::LessThan;
+        return JSBigInt::ComparisonResult::GreaterThan;
+    };
+
+    if (primValue.isString()) {
+        JSValue bigIntValue = JSBigInt::stringToBigInt(globalObject, asString(primValue)->value(globalObject));
+        RETURN_IF_EXCEPTION(scope, JSBigInt::ComparisonResult::Undefined);
+        if (!bigIntValue)
+            return JSBigInt::ComparisonResult::Undefined;
+
+        if (bigIntValue.isHeapBigInt())
+            return invertBigIntCompareResult(bigIntValue.asHeapBigInt()->compareToInt32(v1));
+
+        ASSERT(bigIntValue.isBigInt32());
+#if USE(BIGINT32)
+        return compare(v1, bigIntValue.bigInt32AsInt32());
+#endif
+    }
+
+    // Note that 0n <=> -0.0 is handling -0.0 as +0.
+    double numberValue = primValue.toNumber(globalObject);
+    RETURN_IF_EXCEPTION(scope, JSBigInt::ComparisonResult::Undefined);
+    if (std::isnan(numberValue))
+        return JSBigInt::ComparisonResult::Undefined;
+    return compare(static_cast<double>(v1), numberValue);
+}
+
 ALWAYS_INLINE bool bigIntCompareResult(JSBigInt::ComparisonResult comparisonResult, JSBigInt::ComparisonMode comparisonMode)
 {
     if (comparisonMode == JSBigInt::ComparisonMode::LessThan)
@@ -284,47 +350,38 @@
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
+    if (v1.isBigInt() && v2.isBigInt())
+        return bigIntCompareResult(compareBigInt(v1, v2), comparisonMode);
+
 #if USE(BIGINT32)
-    if (v1.isBigInt32() && v2.isBigInt32()) {
-        if (comparisonMode == JSBigInt::ComparisonMode::LessThan)
-            return v1.bigInt32AsInt32() < v2.bigInt32AsInt32();
-        ASSERT(comparisonMode == JSBigInt::ComparisonMode::LessThanOrEqual);
-        return v1.bigInt32AsInt32() <= v2.bigInt32AsInt32();
+    if (v1.isBigInt32()) {
+        ASSERT(!v2.isBigInt());
+        auto comparisonResult = compareBigInt32ToOtherPrimitive(globalObject, v1.bigInt32AsInt32(), v2);
+        RETURN_IF_EXCEPTION(scope, false);
+        return bigIntCompareResult(comparisonResult, comparisonMode);
     }
+    if (v2.isBigInt32()) {
+        ASSERT(!v1.isBigInt());
+        auto comparisonResult = compareBigInt32ToOtherPrimitive(globalObject, v2.bigInt32AsInt32(), v1);
+        RETURN_IF_EXCEPTION(scope, false);
+        return bigIntCompareResult(invertBigIntCompareResult(comparisonResult), comparisonMode);
+    }
+    ASSERT(!v1.isBigInt32() && !v2.isBigInt32());
 #endif
 
-    JSBigInt* v1HeapBigInt = nullptr;
-    JSBigInt* v2HeapBigInt = nullptr;
-    // FIXME: have some fast-ish path for a comparison between a small and a large big-int
-    if (v1.isHeapBigInt())
-        v1HeapBigInt = v1.asHeapBigInt();
-#if USE(BIGINT32)
-    else if (v1.isBigInt32())
-        v1HeapBigInt = JSBigInt::createFrom(vm, v1.bigInt32AsInt32());
-#endif
-
-    if (v2.isHeapBigInt())
-        v2HeapBigInt = v2.asHeapBigInt();
-#if USE(BIGINT32)
-    else if (v2.isBigInt32())
-        v2HeapBigInt = JSBigInt::createFrom(vm, v2.bigInt32AsInt32());
-#endif
-
-    if (v1HeapBigInt && v2HeapBigInt)
-        return bigIntCompareResult(JSBigInt::compare(v1HeapBigInt, v2HeapBigInt), comparisonMode);
-
-    if (v1HeapBigInt) {
-        auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v1HeapBigInt, v2);
+    if (v1.isHeapBigInt()) {
+        ASSERT(!v2.isBigInt());
+        auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v1.asHeapBigInt(), v2);
         RETURN_IF_EXCEPTION(scope, false);
         return bigIntCompareResult(comparisonResult, comparisonMode);
     }
 
-    auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v2HeapBigInt, v1);
+    // Here we check inverted because BigInt is the v2
+    ASSERT(!v1.isBigInt());
+    ASSERT(v2.isHeapBigInt());
+    auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v2.asHeapBigInt(), v1);
     RETURN_IF_EXCEPTION(scope, false);
-    // Here we check inverted because BigInt is the v2
-    if (comparisonMode == JSBigInt::ComparisonMode::LessThan)
-        return comparisonResult == JSBigInt::ComparisonResult::GreaterThan;
-    return comparisonResult == JSBigInt::ComparisonResult::GreaterThan || comparisonResult == JSBigInt::ComparisonResult::Equal;
+    return bigIntCompareResult(invertBigIntCompareResult(comparisonResult), comparisonMode);
 }
 
 ALWAYS_INLINE bool toPrimitiveNumeric(JSGlobalObject* globalObject, JSValue v, JSValue& p, double& n)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to