JSTests/ChangeLog

 12020-04-06 Robin Morisset <rmorisset@apple.com>
 2
 3 Support an inlined representation in JSValue of small BigInts ("BigInt32")
 4 https://bugs.webkit.org/show_bug.cgi?id=206182
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 I improved various of the tests to give more informative error messages in the process of fixing them.
 9
 10 More interestingly I had to modify "missing-exception-check-in-string-compare" because it relied on "s1 == s1" resolving ropes, and we now just return true.
 11
 12 * stress/big-int-division.js:
 13 (testDiv):
 14 * stress/big-int-left-shift-wrapped-value.js:
 15 (assert.sameValue):
 16 * stress/big-int-logical-not.js:
 17 (assert):
 18 * stress/big-int-mod-jit.js:
 19 * stress/big-int-right-shift-general.js:
 20 (testRightShift):
 21 * stress/big-int-type-of-proven-type.js:
 22 (assert):
 23 * stress/compare-strict-eq-on-various-types.js:
 24 (testAllTypesCall):
 25 * stress/ftl-string-strict-equality.js:
 26 * stress/missing-exception-check-in-string-compare.js:
 27
1282020-04-16 Yusuke Suzuki <ysuzuki@apple.com>
229
330 Unreviewed, reduce # of iteration since this test is timed out in slow devices

JSTests/stress/big-int-division.js

11//@ runBigIntEnabled
 2//@ runBigIntEnabledNoJIT
23
34// Copyright (C) 2017 Robin Templeton. All rights reserved.
45// This code is governed by the BSD license found in the LICENSE file.

@@assert.sameValue = function (input, expected, message) {
1415}
1516
1617function testDiv(x, y, z) {
17  assert.sameValue(x / y, z, x + " / " + y + " = " + z);
 18 assert.sameValue(x / y, z, x + " / " + y + " = " + (x/y) + " but should be " + z);
1819}
1920
2021testDiv(0xFEDCBA9876543210n, 0xFEDCBA9876543210n, 0x1n);

JSTests/stress/big-int-left-shift-wrapped-value.js

33assert = {
44 sameValue: function (input, expected, message) {
55 if (input !== expected)
6  throw new Error(message);
 6 throw new Error(message + " input: " + input + " != expected: " + expected);
77 }
88};
99

JSTests/stress/big-int-logical-not.js

11//@ runBigIntEnabled
22
3 function assert(a, e) {
 3function assert(a, e, n) {
44 if (a !== e) {
5  throw new Error("Bad!");
 5 throw new Error("Bad logical negation for " + n);
66 }
77}
88

@@function logicalNot(a) {
1212noInline(logicalNot);
1313
1414for (let i = 0; i < 100000; i++) {
15  assert(logicalNot(10n), false);
16  assert(logicalNot(1n), false);
17  assert(logicalNot(0n), true);
18  assert(logicalNot(-1n), false);
 15 assert(logicalNot(10n), false, 10n);
 16 assert(logicalNot(1n), false, 1n);
 17 assert(logicalNot(0n), true, 0n);
 18 assert(logicalNot(-1n), false, -1n);
1919}
2020

JSTests/stress/big-int-mod-jit.js

@@noInline(bigIntModFolding);
2525
2626for (let i = 0; i < 10000; i++) {
2727 let r = bigIntModFolding(10, 30);
28  assert.sameValue(r, -10, "-(" + 10 + " % " + 30 + ") = " + r);
 28 assert.sameValue(r, -10, "[Number] -(" + 10 + " % " + 30 + ") = " + r);
2929}
3030
3131let r = bigIntModFolding(10n, 30n);
32 assert.sameValue(r, -10n, "-(" + 10n + " % " + 30n + ") = " + r);
 32assert.sameValue(r, -10n, "[BigInt] -(" + 10n + " % " + 30n + ") = " + r);
3333

JSTests/stress/big-int-multiplication.js

11//@ runBigIntEnabled
 2//@ runBigIntEnabledNoJIT
23
34// Copyright (C) 2017 Robin Templeton. All rights reserved.
45// This code is governed by the BSD license found in the LICENSE file.
56
6 assert = {
7  sameValue: function (input, expected, message) {
8  if (input !== expected)
9  throw new Error(message);
10  }
11 };
 7function testOneMul(x, y, z) {
 8 let result = x * y;
 9 if (result !== z)
 10 throw new Error("Computing " + x + " * " + y + " resulted in " + result + " instead of the expected " + z);
 11}
1212
1313function testMul(x, y, z) {
14  assert.sameValue(x * y, z, x + " * " + y + " = " + z);
15  assert.sameValue(y * x, z, y + " * " + x + " = " + z);
 14 testOneMul(x, y, z);
 15 testOneMul(y, x, z);
1616}
1717
1818testMul(0xFEDCBA9876543210n, 0xFEDCBA9876543210n, 0xFDBAC097C8DC5ACCDEEC6CD7A44A4100n);

JSTests/stress/big-int-right-shift-general.js

22
33// Copyright (C) 2017 Josh Wolfe. All rights reserved.
44// This code is governed by the BSD license found in the LICENSE file.
 5// Modified by Copyright (C) 2020 Apple.
56
6 function assert(a) {
7  if (!a)
8  throw new Error("Bad assertion");
 7function testRightShift(left, right, expected)
 8{
 9 var result = left >> right;
 10 if (result !== expected)
 11 throw new Error("" + left + ", " + right + " resulted in " + result + " but expected " + expected);
912}
1013
11 assert.sameValue = function (input, expected, message) {
12  if (input !== expected)
13  throw new Error(message);
 14for (var i = 0; i < 1000 ; ++i) {
 15 testRightShift(0n, 0n, 0n);
 16 testRightShift(0b101n, -1n, 0b1010n);
 17 testRightShift(0b101n, -2n, 0b10100n);
 18 testRightShift(0b101n, -3n, 0b101000n);
 19 testRightShift(0b101n, 1n, 0b10n);
 20 testRightShift(0b101n, 2n, 1n);
 21 testRightShift(0b101n, 3n, 0n);
 22 testRightShift(0n, -128n, 0n);
 23 testRightShift(0n, 128n, 0n);
 24 testRightShift(0x246n, 0n, 0x246n);
 25 testRightShift(0x246n, -127n, 0x12300000000000000000000000000000000n);
 26 testRightShift(0x246n, -128n, 0x24600000000000000000000000000000000n);
 27 testRightShift(0x246n, -129n, 0x48c00000000000000000000000000000000n);
 28 testRightShift(0x246n, 128n, 0n);
 29 testRightShift(0x123456789abcdef0fedcba9876543212345678n, -64n, 0x123456789abcdef0fedcba98765432123456780000000000000000n);
 30 testRightShift(0x123456789abcdef0fedcba9876543212345678n, -32n, 0x123456789abcdef0fedcba987654321234567800000000n);
 31 testRightShift(0x123456789abcdef0fedcba9876543212345678n, -16n, 0x123456789abcdef0fedcba98765432123456780000n);
 32 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 0n, 0x123456789abcdef0fedcba9876543212345678n);
 33 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 16n, 0x123456789abcdef0fedcba987654321234n);
 34 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 32n, 0x123456789abcdef0fedcba98765432n);
 35 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 64n, 0x123456789abcdef0fedcban);
 36 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 127n, 0x2468acn);
 37 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 128n, 0x123456n);
 38 testRightShift(0x123456789abcdef0fedcba9876543212345678n, 129n, 0x91a2bn);
 39 testRightShift(-5n, -1n, -0xan);
 40 testRightShift(-5n, -2n, -0x14n);
 41 testRightShift(-5n, -3n, -0x28n);
 42 testRightShift(-5n, 1n, -3n);
 43 testRightShift(-5n, 2n, -2n);
 44 testRightShift(-5n, 3n, -1n);
 45 testRightShift(-1n, -128n, -0x100000000000000000000000000000000n);
 46 testRightShift(-1n, 0n, -1n);
 47 testRightShift(-1n, 128n, -1n);
 48 testRightShift(-0x246n, 0n, -0x246n);
 49 testRightShift(-0x246n, -127n, -0x12300000000000000000000000000000000n);
 50 testRightShift(-0x246n, -128n, -0x24600000000000000000000000000000000n);
 51 testRightShift(-0x246n, -129n, -0x48c00000000000000000000000000000000n);
 52 testRightShift(-0x246n, 128n, -1n);
 53 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, -64n, -0x123456789abcdef0fedcba98765432123456780000000000000000n);
 54 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, -32n, -0x123456789abcdef0fedcba987654321234567800000000n);
 55 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, -16n, -0x123456789abcdef0fedcba98765432123456780000n);
 56 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 0n, -0x123456789abcdef0fedcba9876543212345678n);
 57 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 16n, -0x123456789abcdef0fedcba987654321235n);
 58 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 32n, -0x123456789abcdef0fedcba98765433n);
 59 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 64n, -0x123456789abcdef0fedcbbn);
 60 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 127n, -0x2468adn);
 61 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 128n, -0x123457n);
 62 testRightShift(-0x123456789abcdef0fedcba9876543212345678n, 129n, -0x91a2cn);
1463}
15 
16 assert.sameValue(0n >> 0n, 0n, "0n >> 0n === 0n");
17 assert.sameValue(0b101n >> -1n, 0b1010n, "0b101n >> -1n === 0b1010n");
18 assert.sameValue(0b101n >> -2n, 0b10100n, "0b101n >> -2n === 0b10100n");
19 assert.sameValue(0b101n >> -3n, 0b101000n, "0b101n >> -3n === 0b101000n");
20 assert.sameValue(0b101n >> 1n, 0b10n, "0b101n >> 1n === 0b10n");
21 assert.sameValue(0b101n >> 2n, 1n, "0b101n >> 2n === 1n");
22 assert.sameValue(0b101n >> 3n, 0n, "0b101n >> 3n === 0n");
23 assert.sameValue(0n >> -128n, 0n, "0n >> -128n === 0n");
24 assert.sameValue(0n >> 128n, 0n, "0n >> 128n === 0n");
25 assert.sameValue(0x246n >> 0n, 0x246n, "0x246n >> 0n === 0x246n");
26 assert.sameValue(0x246n >> -127n, 0x12300000000000000000000000000000000n, "0x246n >> -127n === 0x12300000000000000000000000000000000n");
27 assert.sameValue(0x246n >> -128n, 0x24600000000000000000000000000000000n, "0x246n >> -128n === 0x24600000000000000000000000000000000n");
28 assert.sameValue(0x246n >> -129n, 0x48c00000000000000000000000000000000n, "0x246n >> -129n === 0x48c00000000000000000000000000000000n");
29 assert.sameValue(0x246n >> 128n, 0n, "0x246n >> 128n === 0n");
30 assert.sameValue(
31  0x123456789abcdef0fedcba9876543212345678n >> -64n, 0x123456789abcdef0fedcba98765432123456780000000000000000n,
32  "0x123456789abcdef0fedcba9876543212345678n >> -64n === 0x123456789abcdef0fedcba98765432123456780000000000000000n");
33 assert.sameValue(
34  0x123456789abcdef0fedcba9876543212345678n >> -32n, 0x123456789abcdef0fedcba987654321234567800000000n,
35  "0x123456789abcdef0fedcba9876543212345678n >> -32n === 0x123456789abcdef0fedcba987654321234567800000000n");
36 assert.sameValue(
37  0x123456789abcdef0fedcba9876543212345678n >> -16n, 0x123456789abcdef0fedcba98765432123456780000n,
38  "0x123456789abcdef0fedcba9876543212345678n >> -16n === 0x123456789abcdef0fedcba98765432123456780000n");
39 assert.sameValue(
40  0x123456789abcdef0fedcba9876543212345678n >> 0n, 0x123456789abcdef0fedcba9876543212345678n,
41  "0x123456789abcdef0fedcba9876543212345678n >> 0n === 0x123456789abcdef0fedcba9876543212345678n");
42 assert.sameValue(
43  0x123456789abcdef0fedcba9876543212345678n >> 16n, 0x123456789abcdef0fedcba987654321234n,
44  "0x123456789abcdef0fedcba9876543212345678n >> 16n === 0x123456789abcdef0fedcba987654321234n");
45 assert.sameValue(
46  0x123456789abcdef0fedcba9876543212345678n >> 32n, 0x123456789abcdef0fedcba98765432n,
47  "0x123456789abcdef0fedcba9876543212345678n >> 32n === 0x123456789abcdef0fedcba98765432n");
48 assert.sameValue(
49  0x123456789abcdef0fedcba9876543212345678n >> 64n, 0x123456789abcdef0fedcban,
50  "0x123456789abcdef0fedcba9876543212345678n >> 64n === 0x123456789abcdef0fedcban");
51 assert.sameValue(
52  0x123456789abcdef0fedcba9876543212345678n >> 127n, 0x2468acn,
53  "0x123456789abcdef0fedcba9876543212345678n >> 127n === 0x2468acn");
54 assert.sameValue(
55  0x123456789abcdef0fedcba9876543212345678n >> 128n, 0x123456n,
56  "0x123456789abcdef0fedcba9876543212345678n >> 128n === 0x123456n");
57 assert.sameValue(
58  0x123456789abcdef0fedcba9876543212345678n >> 129n, 0x91a2bn,
59  "0x123456789abcdef0fedcba9876543212345678n >> 129n === 0x91a2bn");
60 assert.sameValue(-5n >> -1n, -0xan, "-5n >> -1n === -0xan");
61 assert.sameValue(-5n >> -2n, -0x14n, "-5n >> -2n === -0x14n");
62 assert.sameValue(-5n >> -3n, -0x28n, "-5n >> -3n === -0x28n");
63 assert.sameValue(-5n >> 1n, -3n, "-5n >> 1n === -3n");
64 assert.sameValue(-5n >> 2n, -2n, "-5n >> 2n === -2n");
65 assert.sameValue(-5n >> 3n, -1n, "-5n >> 3n === -1n");
66 assert.sameValue(-1n >> -128n, -0x100000000000000000000000000000000n, "-1n >> -128n === -0x100000000000000000000000000000000n");
67 assert.sameValue(-1n >> 0n, -1n, "-1n >> 0n === -1n");
68 assert.sameValue(-1n >> 128n, -1n, "-1n >> 128n === -1n");
69 assert.sameValue(-0x246n >> 0n, -0x246n, "-0x246n >> 0n === -0x246n");
70 assert.sameValue(-0x246n >> -127n, -0x12300000000000000000000000000000000n, "-0x246n >> -127n === -0x12300000000000000000000000000000000n");
71 assert.sameValue(-0x246n >> -128n, -0x24600000000000000000000000000000000n, "-0x246n >> -128n === -0x24600000000000000000000000000000000n");
72 assert.sameValue(-0x246n >> -129n, -0x48c00000000000000000000000000000000n, "-0x246n >> -129n === -0x48c00000000000000000000000000000000n");
73 assert.sameValue(-0x246n >> 128n, -1n, "-0x246n >> 128n === -1n");
74 assert.sameValue(
75  -0x123456789abcdef0fedcba9876543212345678n >> -64n, -0x123456789abcdef0fedcba98765432123456780000000000000000n,
76  "-0x123456789abcdef0fedcba9876543212345678n >> -64n === -0x123456789abcdef0fedcba98765432123456780000000000000000n");
77 assert.sameValue(
78  -0x123456789abcdef0fedcba9876543212345678n >> -32n, -0x123456789abcdef0fedcba987654321234567800000000n,
79  "-0x123456789abcdef0fedcba9876543212345678n >> -32n === -0x123456789abcdef0fedcba987654321234567800000000n");
80 assert.sameValue(
81  -0x123456789abcdef0fedcba9876543212345678n >> -16n, -0x123456789abcdef0fedcba98765432123456780000n,
82  "-0x123456789abcdef0fedcba9876543212345678n >> -16n === -0x123456789abcdef0fedcba98765432123456780000n");
83 assert.sameValue(
84  -0x123456789abcdef0fedcba9876543212345678n >> 0n, -0x123456789abcdef0fedcba9876543212345678n,
85  "-0x123456789abcdef0fedcba9876543212345678n >> 0n === -0x123456789abcdef0fedcba9876543212345678n");
86 assert.sameValue(
87  -0x123456789abcdef0fedcba9876543212345678n >> 16n, -0x123456789abcdef0fedcba987654321235n,
88  "-0x123456789abcdef0fedcba9876543212345678n >> 16n === -0x123456789abcdef0fedcba987654321235n");
89 assert.sameValue(
90  -0x123456789abcdef0fedcba9876543212345678n >> 32n, -0x123456789abcdef0fedcba98765433n,
91  "-0x123456789abcdef0fedcba9876543212345678n >> 32n === -0x123456789abcdef0fedcba98765433n");
92 assert.sameValue(
93  -0x123456789abcdef0fedcba9876543212345678n >> 64n, -0x123456789abcdef0fedcbbn,
94  "-0x123456789abcdef0fedcba9876543212345678n >> 64n === -0x123456789abcdef0fedcbbn");
95 assert.sameValue(
96  -0x123456789abcdef0fedcba9876543212345678n >> 127n, -0x2468adn,
97  "-0x123456789abcdef0fedcba9876543212345678n >> 127n === -0x2468adn");
98 assert.sameValue(
99  -0x123456789abcdef0fedcba9876543212345678n >> 128n, -0x123457n,
100  "-0x123456789abcdef0fedcba9876543212345678n >> 128n === -0x123457n");
101 assert.sameValue(
102  -0x123456789abcdef0fedcba9876543212345678n >> 129n, -0x91a2cn,
103  "-0x123456789abcdef0fedcba9876543212345678n >> 129n === -0x91a2cn");
104 

JSTests/stress/big-int-type-of-proven-type.js

11//@ runDefault("--useBigInt=true", "--useConcurrentJIT=false")
22
3 function assert(a) {
4  if (!a)
5  throw new Error("Bad assertion");
 3function assert(input, expected) {
 4 if (input !== expected)
 5 throw new Error("Bad result: " + input);
66}
77
88function foo(o) {

@@function foo(o) {
1313noInline(foo);
1414
1515for (let i = 0; i < 10000; i++) {
16  assert(foo(3n) === "3");
 16 assert(foo(3n), "3");
1717}
18 

JSTests/stress/compare-number-and-other.js

@@for (let operator of operators) {
5959 noInline(testMonomorphicRightConstant${testCaseIndex});
6060
6161 for (let i = 0; i < 500; ++i) {
62  if (testMonomorphic${testCaseIndex}(${left}, ${right}) != ${llintResult})
 62 if (testMonomorphic${testCaseIndex}(${left}, ${right}) !== ${llintResult})
6363 throw "Failed testMonomorphic${testCaseIndex}(${left}, ${right})";
64  if (testMonomorphicLeftConstant${testCaseIndex}(${right}) != ${llintResult})
 64 if (testMonomorphicLeftConstant${testCaseIndex}(${right}) !== ${llintResult})
6565 throw "Failed testMonomorphicLeftConstant${testCaseIndex}(${right})";
66  if (testMonomorphicRightConstant${testCaseIndex}(${left}) != ${llintResult})
 66 if (testMonomorphicRightConstant${testCaseIndex}(${left}) !== ${llintResult})
6767 throw "Failed testMonomorphicLeftConstant${testCaseIndex}(${left})";
6868 if (testPolymorphic(${left}, ${right}) !== ${llintResult})
69  throw "Failed polymorphicVersion(${left})";
 69 throw "Failed polymorphicVersion(${left}, ${operator}, ${right}, expected result: ${llintResult})";
7070 }
7171 `);
7272 ++testCaseIndex;
7373 }
7474 }
75 }
7675\ No newline at end of file
 76}

JSTests/stress/compare-strict-eq-on-various-types.js

@@function testAllTypesCall() {
8383 ", Right = " +
8484 rightCases[rightCaseIndex] +
8585 ", Result = " +
86  strictEqualOutput;
 86 strictEqualOutput +
 87 " (case: " + leftCaseIndex + ", " + rightCaseIndex + ")";
8788 }
8889
8990 let strictNotEqualOutput = opaqueStrictNotEqualAllTypes(leftCases[leftCaseIndex], rightCases[rightCaseIndex]);

@@function testAllTypesCall() {
9394 ", Right = " +
9495 rightCases[rightCaseIndex] +
9596 ", Result = " +
96  strictEqualOutput;
 97 strictEqualOutput +
 98 " (case: " + leftCaseIndex + ", " + rightCaseIndex + ")";
9799 }
98100 }
99101 }

JSTests/stress/ftl-string-strict-equality.js

@@for (var i = 0; i < 100000; ++i) {
3030 var result = foo(array, array2[index]);
3131 var expected = index >= array.length ? null : index
3232 if (result !== expected)
33  throw "Error: bad result: " + result;
 33 throw "Error: bad result: " + result + " but expected " + expected;
3434}
3535

JSTests/stress/missing-exception-check-in-string-compare.js

11const s1 = (-1).toLocaleString().padEnd(2**31-1, 'aa');
 2const s2 = (-1).toLocaleString().padEnd(2**31-1, 'aa');
23try {
3  s1 == s1;
 4 // Force evaluation of Rope
 5 s1 == s2;
46} catch (e) {
57 exception = e;
68}

Source/JavaScriptCore/CMakeLists.txt

@@set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
986986 runtime/SamplingProfiler.h
987987 runtime/ScopeOffset.h
988988 runtime/ScopedArgumentsTable.h
 989 runtime/Scribble.h
989990 runtime/ScriptExecutable.h
990991 runtime/ScriptFetchParameters.h
991992 runtime/ScriptFetcher.h

Source/JavaScriptCore/ChangeLog

 12020-04-06 Robin Morisset <rmorisset@apple.com>
 2
 3 Support an inlined representation in JSValue of small BigInts ("BigInt32")
 4 https://bugs.webkit.org/show_bug.cgi?id=206182
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 This patch attempts to optimize the performance of BigInts, when they are small (32 bit or less).
 9 It works by inlining them into JSValue on 64-bit platforms, avoiding the allocation of a JSBigInt.
 10 The bit pattern we use is 0000:XXXX:XXXX:0012
 11 This representation works because of the following things:
 12 - It cannot be confused with a Double or Integer thanks to the top bits
 13 - It cannot be confused with a pointer to a Cell, thanks to bit 1 which is set to true
 14 - It cannot be confused with a pointer to wasm thanks to bit 0 which is set to false
 15 - It cannot be confused with true/false because bit 2 is set to false
 16 - It cannot be confused for null/undefined because bit 4 is set to true
 17
 18 This entire change is gated by USE(BIGINT32), to make it easier to disable if it turns out to have bugs.
 19 It should also make it much easier to verify if a given bug comes from it or from something else.
 20
 21 Note that in this patch we create such small BigInts when parsing BigInt constants, and most operations (e.g. Add or BitOr) produce a BigInt32 if both of their operands are BigInt32,
 22 but we don't produce a BigInt32 from for example the substraction/division of two large heap-allocated JSBigInts, even if the result fits in 32-bits.
 23 As a result, small BigInts can now either be heap-allocated or inlined in the JSValue.
 24
 25 This patch includes a significant refactor of various slow paths, which are now grouped together in Operations.h
 26 Because this increased the size of Operations.h significantly, I split the parts of Operations.h which are only used by the GC into Scribble.h, to avoid bloating compile times.
 27
 28 In the DFG and FTL we now have 3 UseKinds for BigInts: HeapBigIntUse, BigInt32Use and AnyBigIntUse.
 29 The latter is useful when we know that we are receiving BigInts, but speculation indicates a mix of heap-allocated and small (inlined) big-ints.
 30
 31 Unfortunately, a naive implementation of this patch significantly regresses the performance of StrictEq (and its variants), as it is no longer true that a cell and a non-cell cannot be equal.
 32 Before this patch, the code was jumping to a slow path if either:
 33 - at least one operand is a double
 34 - or both operands are cells
 35 Now, it also needs to jump to the slow path if at least one is a cell.
 36 To recover this performance cost, I significantly rewrote this code, from
 37 if (left is Cell && right is Cell) {
 38 if (left == right)
 39 return true;
 40 goto slowPath;
 41 }
 42 if (! left is Int32) {
 43 if (left is Number)
 44 goto slowPath
 45 }
 46 if (! right is Int32) {
 47 if (right is Number)
 48 goto slowPath
 49 }
 50 return left == right
 51 To the following:
 52 if (left is Double || right is Double)
 53 goto slowPath
 54 if (left == right)
 55 return true;
 56 if (left is Cell || right is Cell)
 57 goto slowPath
 58 return false;
 59 I believe this to be faster than just replacing (left is Cell && right is Cell) by an ||, because I found a bit-trick to check (left is Double || right is Double) which should help reduce the pressure on the branch predictor.
 60 Early JetStream2 tests appear to confirm that this patch is roughly neutral while it was a 0.5% regression before I used this trick, but the numbers are still too noisy, I plan to do more measurements before landing this patch.
 61
 62 I don't yet have performance numbers for this patch on a BigInt benchmark, I will get such numbers before trying to land it, but I'd like some review in the meantime.
 63
 64 * JavaScriptCore.xcodeproj/project.pbxproj:
 65 * assembler/X86Assembler.h:
 66 (JSC::X86Assembler::X86InstructionFormatter::SingleInstructionBufferWriter::memoryModRM):
 67 * bytecode/ArithProfile.cpp:
 68 (JSC::ArithProfile<BitfieldType>::emitObserveResult):
 69 (JSC::ArithProfile<BitfieldType>::shouldEmitSetBigInt32 const):
 70 (JSC::ArithProfile<BitfieldType>::shouldEmitSetHeapBigInt const):
 71 (JSC::ArithProfile<BitfieldType>::emitSetHeapBigInt const):
 72 (JSC::ArithProfile<BitfieldType>::emitSetBigInt32 const):
 73 (WTF::printInternal):
 74 * bytecode/ArithProfile.h:
 75 (JSC::ObservedResults::didObserveNonInt32):
 76 (JSC::ObservedResults::didObserveBigInt):
 77 (JSC::ObservedResults::didObserveHeapBigInt):
 78 (JSC::ObservedResults::didObserveBigInt32):
 79 (JSC::ArithProfile::didObserveHeapBigInt const):
 80 (JSC::ArithProfile::didObserveBigInt32 const):
 81 (JSC::ArithProfile::setObservedHeapBigInt):
 82 (JSC::ArithProfile::setObservedBigInt32):
 83 (JSC::ArithProfile::observeResult):
 84 * bytecode/BytecodeList.rb:
 85 * bytecode/BytecodeLivenessAnalysisInlines.h:
 86 * bytecode/BytecodeUseDef.cpp:
 87 (JSC::computeUsesForBytecodeIndexImpl):
 88 (JSC::computeDefsForBytecodeIndexImpl):
 89 * bytecode/CodeBlock.cpp:
 90 * bytecode/DataFormat.h:
 91 * bytecode/MethodOfGettingAValueProfile.cpp:
 92 (JSC::MethodOfGettingAValueProfile::emitReportValue const):
 93 * bytecode/MethodOfGettingAValueProfile.h:
 94 * bytecode/SpeculatedType.cpp:
 95 (JSC::dumpSpeculation):
 96 (JSC::speculationFromClassInfo):
 97 (JSC::speculationFromStructure):
 98 (JSC::speculationFromValue):
 99 (JSC::speculationFromJSType):
 100 (JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
 101 * bytecode/SpeculatedType.h:
 102 (JSC::isBigInt32Speculation):
 103 (JSC::isHeapBigIntSpeculation):
 104 (JSC::isBigIntSpeculation):
 105 * bytecompiler/BytecodeGenerator.cpp:
 106 (JSC::BytecodeGenerator::emitEqualityOpImpl):
 107 (JSC::BytecodeGenerator::addBigIntConstant):
 108 * bytecompiler/BytecodeGenerator.h:
 109 * dfg/DFGAbstractInterpreterInlines.h:
 110 (JSC::DFG::isToThisAnIdentity):
 111 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
 112 * dfg/DFGByteCodeParser.cpp:
 113 (JSC::DFG::ByteCodeParser::parseBlock):
 114 * dfg/DFGCapabilities.cpp:
 115 (JSC::DFG::capabilityLevel):
 116 * dfg/DFGClobberize.h:
 117 (JSC::DFG::clobberize):
 118 * dfg/DFGConstantFoldingPhase.cpp:
 119 (JSC::DFG::ConstantFoldingPhase::foldConstants):
 120 * dfg/DFGDoesGC.cpp:
 121 (JSC::DFG::doesGC):
 122 * dfg/DFGFixupPhase.cpp:
 123 (JSC::DFG::FixupPhase::fixupNode):
 124 (JSC::DFG::FixupPhase::fixupToThis):
 125 (JSC::DFG::FixupPhase::fixupToNumeric):
 126 (JSC::DFG::FixupPhase::observeUseKindOnNode):
 127 (JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue):
 128 * dfg/DFGMayExit.cpp:
 129 * dfg/DFGNode.h:
 130 (JSC::DFG::Node::shouldSpeculateBigInt32):
 131 (JSC::DFG::Node::shouldSpeculateHeapBigInt):
 132 * dfg/DFGNodeType.h:
 133 * dfg/DFGOSRExit.cpp:
 134 (JSC::DFG::OSRExit::compileExit):
 135 * dfg/DFGOSRExit.h:
 136 * dfg/DFGOperations.cpp:
 137 * dfg/DFGOperations.h:
 138 * dfg/DFGPredictionPropagationPhase.cpp:
 139 * dfg/DFGSafeToExecute.h:
 140 (JSC::DFG::SafeToExecuteEdge::operator()):
 141 (JSC::DFG::safeToExecute):
 142 * dfg/DFGSpeculativeJIT.cpp:
 143 (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
 144 (JSC::DFG::SpeculativeJIT::compileValueBitNot):
 145 (JSC::DFG::SpeculativeJIT::emitUntypedOrAnyBigIntBitOp):
 146 (JSC::DFG::SpeculativeJIT::compileValueBitwiseOp):
 147 (JSC::DFG::SpeculativeJIT::emitUntypedOrBigIntRightShiftBitOp):
 148 (JSC::DFG::SpeculativeJIT::compileValueLShiftOp):
 149 (JSC::DFG::SpeculativeJIT::compileValueBitRShift):
 150 (JSC::DFG::SpeculativeJIT::compileShiftOp):
 151 (JSC::DFG::SpeculativeJIT::compileValueAdd):
 152 (JSC::DFG::SpeculativeJIT::compileValueSub):
 153 (JSC::DFG::SpeculativeJIT::compileIncOrDec):
 154 (JSC::DFG::SpeculativeJIT::compileValueNegate):
 155 (JSC::DFG::SpeculativeJIT::compileValueMul):
 156 (JSC::DFG::SpeculativeJIT::compileValueDiv):
 157 (JSC::DFG::SpeculativeJIT::compileValueMod):
 158 (JSC::DFG::SpeculativeJIT::compileValuePow):
 159 (JSC::DFG::SpeculativeJIT::compare):
 160 (JSC::DFG::SpeculativeJIT::compileStrictEq):
 161 (JSC::DFG::SpeculativeJIT::speculateHeapBigInt):
 162 (JSC::DFG::SpeculativeJIT::speculate):
 163 (JSC::DFG::SpeculativeJIT::compileToNumeric):
 164 (JSC::DFG::SpeculativeJIT::compileHeapBigIntEquality):
 165 * dfg/DFGSpeculativeJIT.h:
 166 (JSC::DFG::SpeculateBigInt32Operand::SpeculateBigInt32Operand):
 167 (JSC::DFG::SpeculateBigInt32Operand::~SpeculateBigInt32Operand):
 168 (JSC::DFG::SpeculateBigInt32Operand::edge const):
 169 (JSC::DFG::SpeculateBigInt32Operand::node const):
 170 (JSC::DFG::SpeculateBigInt32Operand::gpr):
 171 (JSC::DFG::SpeculateBigInt32Operand::use):
 172 * dfg/DFGSpeculativeJIT32_64.cpp:
 173 (JSC::DFG::SpeculativeJIT::compile):
 174 * dfg/DFGSpeculativeJIT64.cpp:
 175 (JSC::DFG::SpeculativeJIT::fillJSValue):
 176 (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeStrictEq):
 177 (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq):
 178 (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
 179 (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
 180 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
 181 (JSC::DFG::SpeculativeJIT::speculateBigInt32):
 182 (JSC::DFG::SpeculativeJIT::speculateAnyBigInt):
 183 (JSC::DFG::SpeculativeJIT::fillSpeculateBigInt32):
 184 (JSC::DFG::SpeculativeJIT::compileBigInt32Compare):
 185 (JSC::DFG::SpeculativeJIT::compilePeepHoleBigInt32Branch):
 186 (JSC::DFG::SpeculativeJIT::compile):
 187 * dfg/DFGStrengthReductionPhase.cpp:
 188 (JSC::DFG::StrengthReductionPhase::handleNode):
 189 * dfg/DFGUseKind.cpp:
 190 (WTF::printInternal):
 191 * dfg/DFGUseKind.h:
 192 (JSC::DFG::typeFilterFor):
 193 (JSC::DFG::isCell):
 194 * ftl/FTLCapabilities.cpp:
 195 (JSC::FTL::canCompile):
 196 * ftl/FTLCommonValues.cpp:
 197 (JSC::FTL::CommonValues::initializeConstants):
 198 * ftl/FTLCommonValues.h:
 199 * ftl/FTLLowerDFGToB3.cpp:
 200 (JSC::FTL::DFG::LowerDFGToB3::compileNode):
 201 (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
 202 (JSC::FTL::DFG::LowerDFGToB3::compileValueSub):
 203 (JSC::FTL::DFG::LowerDFGToB3::compileValueMul):
 204 (JSC::FTL::DFG::LowerDFGToB3::compileBinaryMathIC):
 205 (JSC::FTL::DFG::LowerDFGToB3::compileValueDiv):
 206 (JSC::FTL::DFG::LowerDFGToB3::compileValueMod):
 207 (JSC::FTL::DFG::LowerDFGToB3::compileValuePow):
 208 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitNot):
 209 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitAnd):
 210 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitOr):
 211 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitXor):
 212 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitRShift):
 213 (JSC::FTL::DFG::LowerDFGToB3::compileArithBitRShift):
 214 (JSC::FTL::DFG::LowerDFGToB3::compileArithBitLShift):
 215 (JSC::FTL::DFG::LowerDFGToB3::compileValueBitLShift):
 216 (JSC::FTL::DFG::LowerDFGToB3::compileBitURShift):
 217 (JSC::FTL::DFG::LowerDFGToB3::compileToNumeric):
 218 (JSC::FTL::DFG::LowerDFGToB3::compileCompareEq):
 219 (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
 220 (JSC::FTL::DFG::LowerDFGToB3::compileIsBigInt):
 221 (JSC::FTL::DFG::LowerDFGToB3::emitBinarySnippet):
 222 (JSC::FTL::DFG::LowerDFGToB3::emitBinaryBitOpSnippet):
 223 (JSC::FTL::DFG::LowerDFGToB3::boolify):
 224 (JSC::FTL::DFG::LowerDFGToB3::buildTypeOf):
 225 (JSC::FTL::DFG::LowerDFGToB3::lowHeapBigInt):
 226 (JSC::FTL::DFG::LowerDFGToB3::lowBigInt32):
 227 (JSC::FTL::DFG::LowerDFGToB3::isBigInt32):
 228 (JSC::FTL::DFG::LowerDFGToB3::isNotBigInt32):
 229 (JSC::FTL::DFG::LowerDFGToB3::unboxBigInt32):
 230 (JSC::FTL::DFG::LowerDFGToB3::boxBigInt32):
 231 (JSC::FTL::DFG::LowerDFGToB3::isNotAnyBigInt):
 232 (JSC::FTL::DFG::LowerDFGToB3::speculate):
 233 (JSC::FTL::DFG::LowerDFGToB3::isNotHeapBigIntUnknownWhetherCell):
 234 (JSC::FTL::DFG::LowerDFGToB3::isNotHeapBigInt):
 235 (JSC::FTL::DFG::LowerDFGToB3::isHeapBigInt):
 236 (JSC::FTL::DFG::LowerDFGToB3::speculateHeapBigInt):
 237 (JSC::FTL::DFG::LowerDFGToB3::speculateHeapBigIntUnknownWhetherCell):
 238 (JSC::FTL::DFG::LowerDFGToB3::speculateBigInt32):
 239 (JSC::FTL::DFG::LowerDFGToB3::speculateAnyBigInt):
 240 * ftl/FTLOSRExitCompiler.cpp:
 241 (JSC::FTL::compileStub):
 242 * heap/HeapSnapshotBuilder.cpp:
 243 (JSC::HeapSnapshotBuilder::json):
 244 * heap/MarkedBlockInlines.h:
 245 * heap/PreciseAllocation.cpp:
 246 * inspector/agents/InspectorHeapAgent.cpp:
 247 (Inspector::InspectorHeapAgent::getPreview):
 248 * interpreter/Interpreter.cpp:
 249 (JSC::sizeOfVarargs):
 250 * jit/AssemblyHelpers.cpp:
 251 (JSC::AssemblyHelpers::emitConvertValueToBoolean):
 252 (JSC::AssemblyHelpers::branchIfValue):
 253 * jit/AssemblyHelpers.h:
 254 (JSC::AssemblyHelpers::branchIfBigInt32):
 255 (JSC::AssemblyHelpers::branchIfBigInt32KnownNotNumber):
 256 (JSC::AssemblyHelpers::branchIfNotBigInt32KnownNotNumber):
 257 (JSC::AssemblyHelpers::branchIfHeapBigInt):
 258 (JSC::AssemblyHelpers::branchIfNotHeapBigInt):
 259 (JSC::AssemblyHelpers::unboxBigInt32):
 260 (JSC::AssemblyHelpers::boxBigInt32):
 261 (JSC::AssemblyHelpers::emitTypeOf):
 262 * jit/JIT.cpp:
 263 (JSC::JIT::privateCompileMainPass):
 264 * jit/JIT.h:
 265 * jit/JITArithmetic.cpp:
 266 (JSC::JIT::emit_op_negate):
 267 (JSC::JIT::emitSlow_op_negate):
 268 * jit/JITOpcodes.cpp:
 269 (JSC::JIT::emit_op_is_big_int):
 270 (JSC::JIT::compileOpStrictEq):
 271 (JSC::JIT::compileOpStrictEqJump):
 272 (JSC::JIT::emit_op_to_numeric):
 273 * jit/JITOpcodes32_64.cpp:
 274 (JSC::JIT::emit_op_is_big_int):
 275 (JSC::JIT::emit_op_to_numeric):
 276 * jit/JITOperations.cpp:
 277 * jit/JITOperations.h:
 278 * llint/LLIntOfflineAsmConfig.h:
 279 * llint/LowLevelInterpreter.asm:
 280 * llint/LowLevelInterpreter64.asm:
 281 * parser/ParserArena.cpp:
 282 (JSC::IdentifierArena::makeBigIntDecimalIdentifier):
 283 * runtime/ArrayPrototype.cpp:
 284 * runtime/BigIntConstructor.cpp:
 285 (JSC::toBigInt):
 286 (JSC::callBigIntConstructor):
 287 * runtime/BigIntObject.cpp:
 288 (JSC::BigIntObject::create):
 289 (JSC::BigIntObject::finishCreation):
 290 * runtime/BigIntObject.h:
 291 * runtime/BigIntPrototype.cpp:
 292 (JSC::toThisBigIntValue):
 293 (JSC::bigIntProtoFuncToStringImpl):
 294 * runtime/CommonSlowPaths.cpp:
 295 (JSC::SLOW_PATH_DECL):
 296 (JSC::updateArithProfileForUnaryArithOp):
 297 (JSC::updateArithProfileForBinaryArithOp):
 298 * runtime/JSBigInt.cpp:
 299 (JSC::JSBigInt::createStructure):
 300 (JSC::JSBigInt::parseInt):
 301 (JSC::JSBigInt::stringToBigInt):
 302 (JSC::JSBigInt::inc):
 303 (JSC::JSBigInt::dec):
 304 (JSC::JSBigInt::bitwiseAnd):
 305 (JSC::JSBigInt::toStringGeneric):
 306 (JSC::JSBigInt::equalsToNumber):
 307 (JSC::JSBigInt::equalsToInt32):
 308 * runtime/JSBigInt.h:
 309 (JSC::asHeapBigInt):
 310 * runtime/JSCJSValue.cpp:
 311 (JSC::JSValue::toNumberSlowCase const):
 312 (JSC::JSValue::toObjectSlowCase const):
 313 (JSC::JSValue::toThisSlowCase const):
 314 (JSC::JSValue::synthesizePrototype const):
 315 (JSC::JSValue::dumpInContextAssumingStructure const):
 316 (JSC::JSValue::dumpForBacktrace const):
 317 (JSC::JSValue::toStringSlowCase const):
 318 * runtime/JSCJSValue.h:
 319 * runtime/JSCJSValueInlines.h:
 320 (JSC::JSValue::JSValue):
 321 (JSC::JSValue::asHeapBigInt const):
 322 (JSC::JSValue::isBigInt const):
 323 (JSC::JSValue::isHeapBigInt const):
 324 (JSC::JSValue::isBigInt32 const):
 325 (JSC::JSValue::bigInt32AsInt32 const):
 326 (JSC::JSValue::isPrimitive const):
 327 (JSC::JSValue::getPrimitiveNumber):
 328 (JSC::JSValue::toNumeric const):
 329 (JSC::JSValue::toBigIntOrInt32 const):
 330 (JSC::JSValue::equalSlowCaseInline):
 331 (JSC::JSValue::strictEqualForCells):
 332 (JSC::JSValue::strictEqual):
 333 (JSC::JSValue::pureStrictEqual):
 334 (JSC::JSValue::pureToBoolean const):
 335 * runtime/JSCell.cpp:
 336 (JSC::JSCell::put):
 337 (JSC::JSCell::putByIndex):
 338 (JSC::JSCell::toPrimitive const):
 339 (JSC::JSCell::getPrimitiveNumber const):
 340 (JSC::JSCell::toNumber const):
 341 (JSC::JSCell::toObjectSlow const):
 342 * runtime/JSCell.h:
 343 * runtime/JSCellInlines.h:
 344 (JSC::JSCell::isHeapBigInt const):
 345 (JSC::JSCell::toBoolean const):
 346 (JSC::JSCell::pureToBoolean const):
 347 * runtime/JSString.h:
 348 (JSC::JSValue::toBoolean const):
 349 * runtime/JSType.cpp:
 350 (WTF::printInternal):
 351 * runtime/JSType.h:
 352 * runtime/JSTypeInfo.h:
 353 * runtime/ObjectInitializationScope.cpp:
 354 * runtime/Operations.cpp:
 355 (JSC::jsAddSlowCase):
 356 (JSC::jsIsObjectTypeOrNull):
 357 * runtime/Operations.h:
 358 (JSC::compareBigIntToOtherPrimitive):
 359 (JSC::bigIntCompare):
 360 (JSC::jsLess):
 361 (JSC::jsLessEq):
 362 (JSC::arithmeticBinaryOp):
 363 (JSC::jsSub):
 364 (JSC::jsMul):
 365 (JSC::jsDiv):
 366 (JSC::jsRemainder):
 367 (JSC::jsPow):
 368 (JSC::jsInc):
 369 (JSC::jsDec):
 370 (JSC::jsBitwiseNot):
 371 (JSC::shift):
 372 (JSC::jsLShift):
 373 (JSC::jsRShift):
 374 (JSC::bitwiseBinaryOp):
 375 (JSC::jsBitwiseAnd):
 376 (JSC::jsBitwiseOr):
 377 (JSC::jsBitwiseXor):
 378 * runtime/Scribble.h: Copied from Source/JavaScriptCore/runtime/BigIntObject.h.
 379 (JSC::scribbleFreeCells):
 380 (JSC::isScribbledValue):
 381 (JSC::scribble):
 382 * runtime/StructureInlines.h:
 383 (JSC::prototypeForLookupPrimitiveImpl):
 384
13852020-04-16 Sergio Villar Senin <svillar@igalia.com>
2386
3387 Unreviewed build fix for non unified builds.

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

867867 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
868868 2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
869869 2D342F36F7244096804ADB24 /* SourceOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 425BA1337E4344E1B269A671 /* SourceOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
 870 33111B8B2397256500AA34CE /* Scribble.h in Headers */ = {isa = PBXBuildFile; fileRef = 33111B8A2397256500AA34CE /* Scribble.h */; settings = {ATTRIBUTES = (Private, ); }; };
870871 3395C70722555F6D00BDBFAD /* B3EliminateDeadCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3395C70522555F6D00BDBFAD /* B3EliminateDeadCode.h */; };
871872 33A920BD23DA2C6D000EBAF0 /* CommonSlowPathsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 33A920BC23DA2C6D000EBAF0 /* CommonSlowPathsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
872873 33B2A54722653481005A0F79 /* B3ValueInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */; };

35143515 2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDTable.h; sourceTree = "<group>"; };
35153516 3032175DF1AD47D8998B34E1 /* JSSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSourceCode.h; sourceTree = "<group>"; };
35163517 30A5F403F11C4F599CD596D5 /* WasmSignatureInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSignatureInlines.h; sourceTree = "<group>"; };
 3518 33111B8A2397256500AA34CE /* Scribble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Scribble.h; sourceTree = "<group>"; };
35173519 33743649224D79EF00C8C227 /* B3OptimizeAssociativeExpressionTrees.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = B3OptimizeAssociativeExpressionTrees.cpp; path = b3/B3OptimizeAssociativeExpressionTrees.cpp; sourceTree = "<group>"; };
35183520 3374364A224D79EF00C8C227 /* B3OptimizeAssociativeExpressionTrees.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = B3OptimizeAssociativeExpressionTrees.h; path = b3/B3OptimizeAssociativeExpressionTrees.h; sourceTree = "<group>"; };
35193521 3395C70422555F6C00BDBFAD /* B3EliminateDeadCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3EliminateDeadCode.cpp; path = b3/B3EliminateDeadCode.cpp; sourceTree = "<group>"; };

75627564 0FE050201AA9095600D33B33 /* ScopedArgumentsTable.h */,
75637565 0FE050211AA9095600D33B33 /* ScopeOffset.cpp */,
75647566 0FE050221AA9095600D33B33 /* ScopeOffset.h */,
 7567 33111B8A2397256500AA34CE /* Scribble.h */,
75657568 147341E01DC2CE9600AA29BA /* ScriptExecutable.cpp */,
75667569 147341CD1DC02D7900AA29BA /* ScriptExecutable.h */,
75677570 8852151A9C3842389B3215B7 /* ScriptFetcher.h */,

89288931 0FEC85911BDACDC70080FF74 /* AirValidate.h in Headers */,
89298932 0FEC3C531F33A41600F59B6C /* AlignedMemoryAllocator.h in Headers */,
89308933 0FA7620B1DB959F900B7A2FD /* AllocatingScope.h in Headers */,
 8934 33111B8B2397256500AA34CE /* Scribble.h in Headers */,
89318935 0FDCE11C1FAE6209006F3901 /* AllocationFailureMode.h in Headers */,
89328936 0F75A063200D261F0038E2CF /* Allocator.h in Headers */,
89338937 0F30CB5E1FCE4E37004B5323 /* AllocatorForMode.h in Headers */,

Source/JavaScriptCore/assembler/X86Assembler.h

@@private:
46984698
46994699 // Immediates:
47004700 //
4701  // An immedaite should be appended where appropriate after an op has been emitted.
 4701 // An immediate should be appended where appropriate after an op has been emitted.
47024702 // The writes are unchecked since the opcode formatters above will have ensured space.
47034703
47044704 void immediate8(int imm)

Source/JavaScriptCore/bytecode/ArithProfile.cpp

11/*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@namespace JSC {
3333
3434#if ENABLE(JIT)
3535template<typename BitfieldType>
36 void ArithProfile<BitfieldType>::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, TagRegistersMode mode)
 36void ArithProfile<BitfieldType>::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode)
3737{
38  if (!shouldEmitSetDouble() && !shouldEmitSetNonNumeric() && !shouldEmitSetBigInt())
 38 if (!shouldEmitSetDouble() && !shouldEmitSetNonNumeric() && !shouldEmitSetHeapBigInt() && !shouldEmitSetBigInt32())
3939 return;
4040
4141 CCallHelpers::JumpList done;

@@void ArithProfile<BitfieldType>::emitObserveResult(CCallHelpers& jit, JSValueReg
4848
4949 notDouble.link(&jit);
5050
 51#if USE(BIGINT32)
 52 CCallHelpers::Jump notBigInt32 = jit.branchIfNotBigInt32KnownNotNumber(regs, tempGPR);
 53 emitSetBigInt32(jit);
 54 done.append(jit.jump());
 55 notBigInt32.link(&jit);
 56#else
 57 UNUSED_PARAM(tempGPR);
 58#endif
 59
5160 nonNumeric.append(jit.branchIfNotCell(regs, mode));
52  nonNumeric.append(jit.branchIfNotBigInt(regs.payloadGPR()));
53  emitSetBigInt(jit);
 61 nonNumeric.append(jit.branchIfNotHeapBigInt(regs.payloadGPR()));
 62 emitSetHeapBigInt(jit);
5463 done.append(jit.jump());
5564
5665 nonNumeric.link(&jit);

@@void ArithProfile<BitfieldType>::emitSetNonNumeric(CCallHelpers& jit) const
8897}
8998
9099template<typename BitfieldType>
91 bool ArithProfile<BitfieldType>::shouldEmitSetBigInt() const
 100bool ArithProfile<BitfieldType>::shouldEmitSetBigInt32() const
 101{
 102#if USE(BIGINT32)
 103 BitfieldType mask = ObservedResults::BigInt32;
 104 return (m_bits & mask) != mask;
 105#else
 106 return false;
 107#endif
 108}
 109
 110template<typename BitfieldType>
 111bool ArithProfile<BitfieldType>::shouldEmitSetHeapBigInt() const
92112{
93  BitfieldType mask = ObservedResults::BigInt;
 113 BitfieldType mask = ObservedResults::HeapBigInt;
94114 return (m_bits & mask) != mask;
95115}
96116
97117template<typename BitfieldType>
98 void ArithProfile<BitfieldType>::emitSetBigInt(CCallHelpers& jit) const
 118void ArithProfile<BitfieldType>::emitSetHeapBigInt(CCallHelpers& jit) const
99119{
100  if (shouldEmitSetBigInt())
101  emitUnconditionalSet(jit, ObservedResults::BigInt);
 120 if (shouldEmitSetHeapBigInt())
 121 emitUnconditionalSet(jit, ObservedResults::HeapBigInt);
102122}
103123
 124#if USE(BIGINT32)
 125template<typename BitfieldType>
 126void ArithProfile<BitfieldType>::emitSetBigInt32(CCallHelpers& jit) const
 127{
 128 if (shouldEmitSetBigInt32())
 129 emitUnconditionalSet(jit, ObservedResults::BigInt32);
 130}
 131#endif
 132
104133template<typename BitfieldType>
105134void ArithProfile<BitfieldType>::emitUnconditionalSet(CCallHelpers& jit, BitfieldType mask) const
106135{

@@void printInternal(PrintStream& out, const ArithProfile<T>& profile)
149178 out.print(separator, "Int52Overflow");
150179 separator = "|";
151180 }
152  if (profile.didObserveBigInt()) {
153  out.print(separator, "BigInt");
 181 if (profile.didObserveHeapBigInt()) {
 182 out.print(separator, "HeapBigInt");
 183 separator = "|";
 184 }
 185 if (profile.didObserveBigInt32()) {
 186 out.print(separator, "BigInt32");
154187 separator = "|";
155188 }
156189 }

Source/JavaScriptCore/bytecode/ArithProfile.h

11/*
2  * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2016-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@public:
7474 NonNumeric = 1 << 2,
7575 Int32Overflow = 1 << 3,
7676 Int52Overflow = 1 << 4,
77  BigInt = 1 << 5,
 77 HeapBigInt = 1 << 5,
 78 BigInt32 = 1 << 6,
7879 };
79  static constexpr uint32_t numBitsNeeded = 6;
 80 static constexpr uint32_t numBitsNeeded = 7;
8081
8182 ObservedResults() = default;
8283 explicit ObservedResults(uint8_t bits)
8384 : m_bits(bits)
8485 { }
8586
86  bool didObserveNonInt32() { return m_bits & (NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); }
 87 bool didObserveNonInt32() { return m_bits & (NonNegZeroDouble | NegZeroDouble | NonNumeric | HeapBigInt | BigInt32); }
8788 bool didObserveDouble() { return m_bits & (NonNegZeroDouble | NegZeroDouble); }
8889 bool didObserveNonNegZeroDouble() { return m_bits & NonNegZeroDouble; }
8990 bool didObserveNegZeroDouble() { return m_bits & NegZeroDouble; }
9091 bool didObserveNonNumeric() { return m_bits & NonNumeric; }
91  bool didObserveBigInt() { return m_bits & BigInt; }
 92 bool didObserveBigInt() { return m_bits & (HeapBigInt | BigInt32); }
 93 bool didObserveHeapBigInt() { return m_bits & HeapBigInt; }
 94 bool didObserveBigInt32() { return m_bits & BigInt32; }
9295 bool didObserveInt32Overflow() { return m_bits & Int32Overflow; }
9396 bool didObserveInt52Overflow() { return m_bits & Int52Overflow; }
9497

@@public:
109112 bool didObserveNegZeroDouble() const { return observedResults().didObserveNegZeroDouble(); }
110113 bool didObserveNonNumeric() const { return observedResults().didObserveNonNumeric(); }
111114 bool didObserveBigInt() const { return observedResults().didObserveBigInt(); }
 115 bool didObserveHeapBigInt() const { return observedResults().didObserveHeapBigInt(); }
 116 bool didObserveBigInt32() const { return observedResults().didObserveBigInt32(); }
112117 bool didObserveInt32Overflow() const { return observedResults().didObserveInt32Overflow(); }
113118 bool didObserveInt52Overflow() const { return observedResults().didObserveInt52Overflow(); }
114119
115120 void setObservedNonNegZeroDouble() { setBit(ObservedResults::NonNegZeroDouble); }
116121 void setObservedNegZeroDouble() { setBit(ObservedResults::NegZeroDouble); }
117122 void setObservedNonNumeric() { setBit(ObservedResults::NonNumeric); }
118  void setObservedBigInt() { setBit(ObservedResults::BigInt); }
 123 void setObservedHeapBigInt() { setBit(ObservedResults::HeapBigInt); }
 124 void setObservedBigInt32() { setBit(ObservedResults::BigInt32); }
119125 void setObservedInt32Overflow() { setBit(ObservedResults::Int32Overflow); }
120126 void setObservedInt52Overflow() { setBit(ObservedResults::Int52Overflow); }
121127

@@public:
127133 m_bits |= ObservedResults::Int32Overflow | ObservedResults::Int52Overflow | ObservedResults::NonNegZeroDouble | ObservedResults::NegZeroDouble;
128134 return;
129135 }
130  if (value && value.isBigInt()) {
131  m_bits |= ObservedResults::BigInt;
 136 if (value.isBigInt32()) {
 137 m_bits |= ObservedResults::BigInt32;
 138 return;
 139 }
 140 if (value && value.isHeapBigInt()) {
 141 m_bits |= ObservedResults::HeapBigInt;
132142 return;
133143 }
134144 m_bits |= ObservedResults::NonNumeric;

@@public:
139149#if ENABLE(JIT)
140150 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a
141151 // double. Sets NonNumeric if it sees a non-numeric.
142  void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters);
 152 void emitObserveResult(CCallHelpers&, JSValueRegs, GPRReg tempGPR, TagRegistersMode = HaveTagRegisters);
143153
144154 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble).
145155 bool shouldEmitSetDouble() const;
146156 void emitSetDouble(CCallHelpers&) const;
147157
148  // Sets NonNumeric
149158 void emitSetNonNumeric(CCallHelpers&) const;
150159 bool shouldEmitSetNonNumeric() const;
151160
152  // Sets BigInt
153  void emitSetBigInt(CCallHelpers&) const;
154  bool shouldEmitSetBigInt() const;
 161 bool shouldEmitSetHeapBigInt() const;
 162 void emitSetHeapBigInt(CCallHelpers&) const;
 163
 164 bool shouldEmitSetBigInt32() const;
 165#if USE(BIGINT32)
 166 void emitSetBigInt32(CCallHelpers&) const;
 167#endif
155168
156169 void emitUnconditionalSet(CCallHelpers&, BitfieldType) const;
157170#endif // ENABLE(JIT)

@@using UnaryArithProfileBase = uint16_t;
175188class UnaryArithProfile : public ArithProfile<UnaryArithProfileBase> {
176189 static constexpr unsigned argObservedTypeShift = ObservedResults::numBitsNeeded;
177190
178  static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(UnaryArithProfileBase) * 8, "Should fit in a the type of the underlying bitfield.");
 191 static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(UnaryArithProfileBase) * 8, "Should fit in the type of the underlying bitfield.");
179192
180193 static constexpr UnaryArithProfileBase clearArgObservedTypeBitMask = static_cast<UnaryArithProfileBase>(~(0b111 << argObservedTypeShift));
181194

@@class BinaryArithProfile : public ArithProfile<BinaryArithProfileBase> {
257270
258271public:
259272 static constexpr BinaryArithProfileBase specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
260  static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(BinaryArithProfileBase) * 8, "Should fit in a uint32_t.");
 273 static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(BinaryArithProfileBase) * 8, "Should fit in the underlying type.");
261274 static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
262275 static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
263276 static_assert(static_cast<unsigned>(specialFastPathBit) > static_cast<unsigned>(static_cast<BinaryArithProfileBase>(~clearLhsObservedTypeBitMask)), "These bits should not intersect and specialFastPathBit should be a higher bit.");

Source/JavaScriptCore/bytecode/BytecodeList.rb

@@op_group :UnaryOp,
329329 :is_undefined_or_null,
330330 :is_boolean,
331331 :is_number,
 332 :is_big_int,
332333 :is_object,
333334 :is_object_or_null,
334335 :is_function,

Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h

2929#include "BytecodeLivenessAnalysis.h"
3030#include "CodeBlock.h"
3131#include "InterpreterInlines.h"
32 #include "Operations.h"
3332
3433namespace JSC {
3534

Source/JavaScriptCore/bytecode/BytecodeUseDef.cpp

11/*
2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void computeUsesForBytecodeIndexImpl(VirtualRegister scopeRegister, const Instru
174174 USES(OpIsUndefinedOrNull, operand)
175175 USES(OpIsBoolean, operand)
176176 USES(OpIsNumber, operand)
 177 USES(OpIsBigInt, operand)
177178 USES(OpIsObject, operand)
178179 USES(OpIsObjectOrNull, operand)
179180 USES(OpIsCellWithType, operand)

@@void computeDefsForBytecodeIndexImpl(unsigned numVars, const Instruction* instru
423424 DEFS(OpIdentityWithProfile, srcDst)
424425 DEFS(OpIsEmpty, dst)
425426 DEFS(OpIsUndefined, dst)
426  USES(OpIsUndefinedOrNull, dst)
 427 DEFS(OpIsUndefinedOrNull, dst)
427428 DEFS(OpIsBoolean, dst)
428429 DEFS(OpIsNumber, dst)
 430 DEFS(OpIsBigInt, dst)
429431 DEFS(OpIsObject, dst)
430432 DEFS(OpIsObjectOrNull, dst)
431433 DEFS(OpIsCellWithType, dst)

Source/JavaScriptCore/bytecode/CodeBlock.cpp

6060#include "IsoCellSetInlines.h"
6161#include "JIT.h"
6262#include "JITMathIC.h"
63 #include "JSBigInt.h"
6463#include "JSCInlines.h"
6564#include "JSCJSValue.h"
6665#include "JSFunction.h"

Source/JavaScriptCore/bytecode/DataFormat.h

11/*
2  * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@enum DataFormat : uint8_t {
4444 DataFormatBoolean = 5,
4545 DataFormatCell = 6,
4646 DataFormatStorage = 7,
47  DataFormatJS = 8,
 47 DataFormatBigInt32 = 8, // FIXME: currently unused
 48 DataFormatJS = 16,
4849 DataFormatJSInt32 = DataFormatJS | DataFormatInt32,
4950 DataFormatJSDouble = DataFormatJS | DataFormatDouble,
5051 DataFormatJSCell = DataFormatJS | DataFormatCell,
5152 DataFormatJSBoolean = DataFormatJS | DataFormatBoolean,
52 
 53 DataFormatJSBigInt32 = DataFormatJS | DataFormatBigInt32,
 54
5355 // Marker deliminating ordinary data formats and OSR-only data formats.
5456 DataFormatOSRMarker = 32,
5557

Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.cpp

11/*
2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
 2 * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@MethodOfGettingAValueProfile MethodOfGettingAValueProfile::fromLazyOperand(
4646 return result;
4747}
4848
49 void MethodOfGettingAValueProfile::emitReportValue(CCallHelpers& jit, JSValueRegs regs) const
 49void MethodOfGettingAValueProfile::emitReportValue(CCallHelpers& jit, JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode) const
5050{
5151 switch (m_kind) {
5252 case None:

@@void MethodOfGettingAValueProfile::emitReportValue(CCallHelpers& jit, JSValueReg
6767 }
6868
6969 case UnaryArithProfileReady: {
70  u.unaryArithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters);
 70 u.unaryArithProfile->emitObserveResult(jit, regs, tempGPR, mode);
7171 return;
7272 }
7373
7474 case BinaryArithProfileReady: {
75  u.binaryArithProfile->emitObserveResult(jit, regs, DoNotHaveTagRegisters);
 75 u.binaryArithProfile->emitObserveResult(jit, regs, tempGPR, mode);
7676 return;
7777 }
7878 }

Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h

3434#include "BytecodeIndex.h"
3535#include "GPRInfo.h"
3636#include "Operands.h"
 37#include "TagRegistersMode.h"
3738
3839namespace JSC {
3940

@@public:
8384
8485 explicit operator bool() const { return m_kind != None; }
8586
86  void emitReportValue(CCallHelpers&, JSValueRegs) const;
 87 // The temporary register is only needed on 64-bits builds (for testing BigInt32).
 88 void emitReportValue(CCallHelpers&, JSValueRegs, GPRReg tempGPR, TagRegistersMode = HaveTagRegisters) const;
8789 void reportValue(JSValue);
8890
8991private:

Source/JavaScriptCore/bytecode/SpeculatedType.cpp

11/*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void dumpSpeculation(PrintStream& outStream, SpeculatedType value)
239239 strOut.print("Symbol");
240240 else
241241 isTop = false;
242 
243  if (value & SpecBigInt)
244  strOut.print("BigInt");
245  else
246  isTop = false;
247242 }
248243
249244 if (value == SpecInt32Only)

@@void dumpSpeculation(PrintStream& outStream, SpeculatedType value)
278273 else
279274 isTop = false;
280275 }
281 
 276
 277 if ((value & SpecBigInt) == SpecBigInt)
 278 strOut.print("BigInt");
 279#if USE(BIGINT32)
 280 else {
 281 if (value & SpecBigInt32)
 282 strOut.print("BigInt32");
 283 else
 284 isTop = false;
 285
 286 if (value & SpecHeapBigInt)
 287 strOut.print("HeapBigInt");
 288 else
 289 isTop = false;
 290 }
 291#endif
 292
282293 if (value & SpecDoubleImpureNaN)
283294 strOut.print("DoubleImpureNaN");
284295

@@SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo)
431442 return SpecSymbol;
432443
433444 if (classInfo == JSBigInt::info())
434  return SpecBigInt;
 445 return SpecHeapBigInt;
435446
436447 if (classInfo == JSFinalObject::info())
437448 return SpecFinalObject;

@@SpeculatedType speculationFromStructure(Structure* structure)
499510 return SpecString;
500511 if (structure->typeInfo().type() == SymbolType)
501512 return SpecSymbol;
502  if (structure->typeInfo().type() == BigIntType)
503  return SpecBigInt;
 513 if (structure->typeInfo().type() == HeapBigIntType)
 514 return SpecHeapBigInt;
504515 if (structure->typeInfo().type() == DerivedArrayType)
505516 return SpecDerivedArray;
506517 return speculationFromClassInfo(structure->classInfo());

@@SpeculatedType speculationFromValue(JSValue value)
536547 return SpecAnyIntAsDouble;
537548 return SpecNonIntAsDouble;
538549 }
 550 if (value.isBigInt32())
 551 return SpecBigInt32;
539552 if (value.isCell())
540553 return speculationFromCell(value.asCell());
541554 if (value.isBoolean())

@@Optional<SpeculatedType> speculationFromJSType(JSType type)
595608 return SpecString;
596609 case SymbolType:
597610 return SpecSymbol;
598  case BigIntType:
599  return SpecBigInt;
 611 case HeapBigIntType:
 612 return SpecHeapBigInt;
600613 case ArrayType:
601614 return SpecArray;
602615 case DerivedArrayType:

@@SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType ty
632645
633646 if (type & SpecString)
634647 type |= SpecString;
 648
 649 if (type & SpecBigInt)
 650 type |= SpecBigInt;
 651
635652 return type;
636653}
637654

Source/JavaScriptCore/bytecode/SpeculatedType.h

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@static constexpr SpeculatedType SpecBoolean = 1ull <<
9898static constexpr SpeculatedType SpecOther = 1ull << 39; // It's definitely either Null or Undefined.
9999static constexpr SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
100100static constexpr SpeculatedType SpecEmpty = 1ull << 40; // It's definitely an empty value marker.
101 static constexpr SpeculatedType SpecBigInt = 1ull << 41; // It's definitely a BigInt.
102 static constexpr SpeculatedType SpecDataViewObject = 1ull << 42; // It's definitely a JSDataView.
 101static constexpr SpeculatedType SpecHeapBigInt = 1ull << 41; // It's definitely a BigInt that is allocated on the heap
 102static constexpr SpeculatedType SpecBigInt32 = 1ull << 42; // It's definitely a small BigInt that is inline the JSValue
 103static constexpr SpeculatedType SpecBigInt = SpecBigInt32 | SpecHeapBigInt;
 104static constexpr SpeculatedType SpecDataViewObject = 1ull << 43; // It's definitely a JSDataView.
103105static constexpr SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue.
104106static 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.
105 static constexpr SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecBigInt; // It's definitely a JSCell.
106 static constexpr SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
 107static constexpr SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther | SpecHeapBigInt; // It's definitely a JSCell.
 108static constexpr SpeculatedType SpecHeapTop = SpecCell | SpecBigInt32 | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
107109static constexpr SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
108110static constexpr SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
109111

@@inline bool isSymbolSpeculation(SpeculatedType value)
185187 return value == SpecSymbol;
186188}
187189
 190inline bool isBigInt32Speculation(SpeculatedType value)
 191{
 192 return value == SpecBigInt32;
 193}
 194
 195inline bool isHeapBigIntSpeculation(SpeculatedType value)
 196{
 197 return value == SpecHeapBigInt;
 198}
 199
188200inline bool isBigIntSpeculation(SpeculatedType value)
189201{
190  return value == SpecBigInt;
 202 return !!value && (value & SpecBigInt) == value;
191203}
192204
193205inline bool isArraySpeculation(SpeculatedType value)

Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

@@bool BytecodeGenerator::emitEqualityOpImpl(RegisterID* dst, RegisterID* src1, Re
17031703 }
17041704 if (Options::useBigInt() && value == "bigint") {
17051705 rewind();
1706  OpIsCellWithType::emit(this, dst, op.m_value, BigIntType);
 1706#if USE(BIGINT32)
 1707 OpIsBigInt::emit(this, dst, op.m_value);
 1708#else
 1709 OpIsCellWithType::emit(this, dst, op.m_value, HeapBigIntType);
 1710#endif
17071711 return true;
17081712 }
17091713 if (value == "object") {

@@JSValue BytecodeGenerator::addBigIntConstant(const Identifier& identifier, uint8
29112915 return m_bigIntMap.ensure(BigIntMapEntry(identifier.impl(), radix, sign), [&] {
29122916 auto scope = DECLARE_CATCH_SCOPE(vm());
29132917 auto parseIntSign = sign ? JSBigInt::ParseIntSign::Signed : JSBigInt::ParseIntSign::Unsigned;
2914  JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign);
 2918 JSValue bigIntInMap = JSBigInt::parseInt(nullptr, vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign);
29152919 scope.assertNoException();
29162920 addConstantValue(bigIntInMap);
29172921

Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

@@namespace JSC {
10921092
10931093 using NumberMap = HashMap<double, JSValue>;
10941094 using IdentifierStringMap = HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash>;
1095  using IdentifierBigIntMap = HashMap<BigIntMapEntry, JSBigInt*>;
 1095 using IdentifierBigIntMap = HashMap<BigIntMapEntry, JSValue>;
10961096 using TemplateObjectDescriptorSet = HashSet<Ref<TemplateObjectDescriptor>>;
10971097 using TemplateDescriptorMap = HashMap<uint64_t, JSTemplateObjectDescriptor*, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
10981098

Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

11/*
2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

4646#include "JSPromiseConstructor.h"
4747#include "MathCommon.h"
4848#include "NumberConstructor.h"
49 #include "Operations.h"
5049#include "PutByIdStatus.h"
5150#include "StringObject.h"
5251#include "StructureCache.h"

@@inline ToThisResult isToThisAnIdentity(VM& vm, ECMAMode ecmaMode, AbstractValue&
215214 bool overridesToThis = false;
216215 valueForNode.m_structure.forEach([&](RegisteredStructure structure) {
217216 TypeInfo type = structure->typeInfo();
218  ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType || type.type() == BigIntType);
 217 ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType || type.type() == HeapBigIntType);
219218 if (!ecmaMode.isStrict())
220219 ASSERT(type.isObject());
221220 // We don't need to worry about strings/symbols here since either:

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
503502 break;
504503 }
505504
506  if (node->child1().useKind() == BigIntUse)
 505 if (node->child1().useKind() == BigInt32Use) {
 506#if USE(BIGINT32)
 507 setTypeForNode(node, SpecBigInt32);
 508#else
 509 RELEASE_ASSERT_NOT_REACHED();
 510#endif
 511 } else if (node->child1().useKind() == HeapBigIntUse)
 512 setTypeForNode(node, SpecHeapBigInt);
 513 else if (node->child1().useKind() == AnyBigIntUse)
507514 setTypeForNode(node, SpecBigInt);
508515 else {
509516 clobberWorld();

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
533540 if (handleConstantBinaryBitwiseOp(node))
534541 break;
535542
536  if (node->binaryUseKind() == BigIntUse)
 543 // FIXME: this use of binaryUseKind means that we cannot specialize to (for example) a HeapBigInt left-operand and a BigInt32 right-operand.
 544 if (node->binaryUseKind() == BigInt32Use) {
 545#if USE(BIGINT32)
 546 setTypeForNode(node, SpecBigInt32);
 547#else
 548 RELEASE_ASSERT_NOT_REACHED();
 549#endif
 550 } else if (node->binaryUseKind() == HeapBigIntUse)
 551 setTypeForNode(node, SpecHeapBigInt);
 552 else if (node->binaryUseKind() == AnyBigIntUse)
537553 setTypeForNode(node, SpecBigInt);
538554 else {
539555 clobberWorld();

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
723739
724740 case ValueSub:
725741 case ValueAdd: {
726  DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == BigIntUse);
727  if (node->binaryUseKind() == BigIntUse)
 742 if (node->binaryUseKind() == HeapBigIntUse)
 743 setTypeForNode(node, SpecHeapBigInt);
 744 else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
728745 setTypeForNode(node, SpecBigInt);
729746 else {
 747 DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse);
730748 clobberWorld();
 749 // FIXME: do we really need SpecString here for ValueSub? It seems like we only need it for ValueAdd.
731750 setTypeForNode(node, SpecString | SpecBytecodeNumber | SpecBigInt);
732751 }
733752 break;

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
887906 }
888907
889908 case ValueNegate: {
 909 // FIXME: we could do much smarter things for BigInts, see ValueAdd/ValueSub.
890910 clobberWorld();
891911 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
892912 break;

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
959979 case DoubleRepUse:
960980 setNonCellTypeForNode(node, typeOfDoubleIncOrDec(forNode(node->child1()).m_type));
961981 break;
962  case BigIntUse:
 982 case HeapBigIntUse:
 983 setTypeForNode(node, SpecHeapBigInt);
 984 break;
 985 case AnyBigIntUse:
 986 case BigInt32Use:
963987 setTypeForNode(node, SpecBigInt);
964988 break;
965989 default:

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
975999 JSValue childY = forNode(node->child2()).value();
9761000 if (childX && childY && childX.isNumber() && childY.isNumber()) {
9771001 // We need to call `didFoldClobberWorld` here because this path is only possible
978  // when node->useKind is UntypedUse. In the case of BigIntUse, children will be
 1002 // when node->useKind is UntypedUse. In the case of AnyBigIntUse or friends, children will be
9791003 // cleared by `AbstractInterpreter::executeEffects`.
9801004 didFoldClobberWorld();
9811005 // Our boxing scheme here matches what we do in operationValuePow.

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
9831007 break;
9841008 }
9851009
986  if (node->binaryUseKind() == BigIntUse)
 1010 if (node->binaryUseKind() == HeapBigIntUse)
 1011 setTypeForNode(node, SpecHeapBigInt);
 1012 else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
9871013 setTypeForNode(node, SpecBigInt);
9881014 else {
9891015 clobberWorld();

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
9931019 }
9941020
9951021 case ValueMul: {
996  if (node->binaryUseKind() == BigIntUse)
 1022 // FIXME: why is this code not shared with ValueSub?
 1023 if (node->binaryUseKind() == HeapBigIntUse)
 1024 setTypeForNode(node, SpecHeapBigInt);
 1025 else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
9971026 setTypeForNode(node, SpecBigInt);
9981027 else {
9991028 clobberWorld();

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
10571086 if (handleConstantDivOp(node))
10581087 break;
10591088
1060  if (node->binaryUseKind() == BigIntUse)
 1089 if (node->binaryUseKind() == HeapBigIntUse)
 1090 setTypeForNode(node, SpecHeapBigInt);
 1091 else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
10611092 setTypeForNode(node, SpecBigInt);
10621093 else {
10631094 clobberWorld();

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
13811412 case IsUndefinedOrNull:
13821413 case IsBoolean:
13831414 case IsNumber:
 1415 case IsBigInt:
13841416 case NumberIsInteger:
13851417 case IsObject:
13861418 case IsObjectOrNull:

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
14091441 case IsNumber:
14101442 setConstant(node, jsBoolean(child.value().isNumber()));
14111443 break;
 1444 case IsBigInt:
 1445 setConstant(node, jsBoolean(child.value().isBigInt()));
 1446 break;
14121447 case NumberIsInteger:
14131448 setConstant(node, jsBoolean(NumberConstructor::isIntegerImpl(child.value())));
14141449 break;

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
15631598 }
15641599
15651600 break;
 1601 case IsBigInt:
 1602 if (!(child.m_type & ~SpecBigInt)) {
 1603 setConstant(node, jsBoolean(true));
 1604 constantWasSet = true;
 1605 break;
 1606 }
 1607
 1608 if (!(child.m_type & SpecBigInt)) {
 1609 setConstant(node, jsBoolean(false));
 1610 constantWasSet = true;
 1611 break;
 1612 }
 1613
 1614 // FIXME: if the SpeculatedType informs us that we won't have a BigInt32 (or that we won't have a HeapBigInt), then we can transform this node into a IsCellWithType(HeapBigIntType) (or a hypothetical IsBigInt32 node).
15661615
 1616 break;
15671617 case NumberIsInteger:
15681618 if (!(child.m_type & ~SpecInt32Only)) {
15691619 setConstant(node, jsBoolean(true));

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
19371987 }
19381988 }
19391989
 1990 // FIXME: why is this check here, and not later (after the type-based replacement by false).
 1991 // Saam seems to agree that the two checks could be switched, I'll try that in a separate patch
19401992 if (node->isBinaryUseKind(UntypedUse)) {
1941  // FIXME: Revisit this condition when introducing BigInt to JSC.
1942  auto isNonStringCellConstant = [] (JSValue value) {
1943  return value && value.isCell() && !value.isString();
 1993 auto isNonStringOrBigIntCellConstant = [] (JSValue value) {
 1994 return value && value.isCell() && !value.isString() && !value.isHeapBigInt();
19441995 };
19451996
1946  if (isNonStringCellConstant(left) || isNonStringCellConstant(right)) {
 1997 if (isNonStringOrBigIntCellConstant(left) || isNonStringOrBigIntCellConstant(right)) {
19471998 m_state.setShouldTryConstantFolding(true);
19481999 setNonCellTypeForNode(node, SpecBoolean);
19492000 break;

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
19582009 }
19592010
19602011 if (node->child1() == node->child2()) {
1961  if (node->isBinaryUseKind(BooleanUse) ||
1962  node->isBinaryUseKind(Int32Use) ||
1963  node->isBinaryUseKind(Int52RepUse) ||
1964  node->isBinaryUseKind(StringUse) ||
1965  node->isBinaryUseKind(StringIdentUse) ||
1966  node->isBinaryUseKind(SymbolUse) ||
1967  node->isBinaryUseKind(ObjectUse) ||
1968  node->isBinaryUseKind(MiscUse, UntypedUse) ||
1969  node->isBinaryUseKind(UntypedUse, MiscUse) ||
1970  node->isBinaryUseKind(StringIdentUse, NotStringVarUse) ||
1971  node->isBinaryUseKind(NotStringVarUse, StringIdentUse) ||
1972  node->isBinaryUseKind(StringUse, UntypedUse) ||
1973  node->isBinaryUseKind(UntypedUse, StringUse)) {
 2012 // FIXME: Is there any case not involving NaN where x === x is not guaranteed to return true?
 2013 // If not I might slightly simplify that check.
 2014 if (node->isBinaryUseKind(BooleanUse)
 2015 || node->isBinaryUseKind(Int32Use)
 2016 || node->isBinaryUseKind(Int52RepUse)
 2017 || node->isBinaryUseKind(StringUse)
 2018 || node->isBinaryUseKind(StringIdentUse)
 2019 || node->isBinaryUseKind(SymbolUse)
 2020 || node->isBinaryUseKind(ObjectUse)
 2021 || node->isBinaryUseKind(MiscUse, UntypedUse)
 2022 || node->isBinaryUseKind(UntypedUse, MiscUse)
 2023 || node->isBinaryUseKind(StringIdentUse, NotStringVarUse)
 2024 || node->isBinaryUseKind(NotStringVarUse, StringIdentUse)
 2025 || node->isBinaryUseKind(StringUse, UntypedUse)
 2026 || node->isBinaryUseKind(UntypedUse, StringUse)
 2027 || node->isBinaryUseKind(BigInt32Use)
 2028 || node->isBinaryUseKind(HeapBigIntUse)
 2029 || node->isBinaryUseKind(AnyBigIntUse)) {
19742030 setConstant(node, jsBoolean(true));
19752031 break;
19762032 }

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@void ByteCodeParser::parseBlock(unsigned limit)
57305730 NEXT_OPCODE(op_is_number);
57315731 }
57325732
 5733 case op_is_big_int: {
 5734#if USE(BIGINT32)
 5735 auto bytecode = currentInstruction->as<OpIsBigInt>();
 5736 Node* value = get(bytecode.m_operand);
 5737 set(bytecode.m_dst, addToGraph(IsBigInt, value));
 5738 NEXT_OPCODE(op_is_big_int);
 5739#else
 5740 RELEASE_ASSERT_NOT_REACHED();
 5741#endif
 5742 }
 5743
57335744 case op_is_cell_with_type: {
57345745 auto bytecode = currentInstruction->as<OpIsCellWithType>();
57355746 Node* value = get(bytecode.m_operand);

Source/JavaScriptCore/dfg/DFGCapabilities.cpp

@@CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, const I
149149 case op_is_undefined_or_null:
150150 case op_is_boolean:
151151 case op_is_number:
 152 case op_is_big_int:
152153 case op_is_object:
153154 case op_is_object_or_null:
154155 case op_is_cell_with_type:

Source/JavaScriptCore/dfg/DFGClobberize.h

11/*
2  * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
175175 case IsUndefinedOrNull:
176176 case IsBoolean:
177177 case IsNumber:
 178 case IsBigInt:
178179 case NumberIsInteger:
179180 case IsObject:
180181 case IsTypedArrayView:

@@void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
260261 return;
261262
262263 case ValueBitNot:
263  if (node->child1().useKind() == BigIntUse) {
 264 if (node->child1().useKind() == AnyBigIntUse || node->child1().useKind() == BigInt32Use || node->child1().useKind() == HeapBigIntUse) {
264265 def(PureValue(node));
265266 return;
266267 }

@@void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
680681 case Int32Use:
681682 case Int52RepUse:
682683 case DoubleRepUse:
683  case BigIntUse:
 684 case BigInt32Use:
 685 case HeapBigIntUse:
 686 case AnyBigIntUse:
684687 def(PureValue(node));
685688 return;
686689 case UntypedUse:

@@void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
702705 case ValuePow:
703706 case ValueBitLShift:
704707 case ValueBitRShift:
705  if (node->isBinaryUseKind(BigIntUse)) {
 708 // FIXME: this use of single-argument isBinaryUseKind would prevent us from specializing (for example) for a HeapBigInt left-operand and a BigInt32 right-operand.
 709 if (node->isBinaryUseKind(AnyBigIntUse) || node->isBinaryUseKind(BigInt32Use) || node->isBinaryUseKind(HeapBigIntUse)) {
706710 def(PureValue(node));
707711 return;
708712 }

Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

@@private:
147147 JSValue child1Constant = m_state.forNode(node->child1().node()).value();
148148 JSValue child2Constant = m_state.forNode(node->child2().node()).value();
149149
150  // FIXME: Revisit this condition when introducing BigInt to JSC.
151150 auto isNonStringOrBigIntCellConstant = [] (JSValue value) {
152  return value && value.isCell() && !value.isString() && !value.isBigInt();
 151 return value && value.isCell() && !value.isString() && !value.isHeapBigInt();
153152 };
154153
155154 if (isNonStringOrBigIntCellConstant(child1Constant)) {

Source/JavaScriptCore/dfg/DFGDoesGC.cpp

3131#include "DFGClobberize.h"
3232#include "DFGGraph.h"
3333#include "DFGNode.h"
34 #include "Operations.h"
3534
3635namespace JSC { namespace DFG {
3736

@@bool doesGC(Graph& graph, Node* node)
147146 case IsUndefinedOrNull:
148147 case IsBoolean:
149148 case IsNumber:
 149 case IsBigInt:
150150 case NumberIsInteger:
151151 case IsObject:
152152 case IsObjectOrNull:

Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

11/*
2  * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2012-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@private:
202202 fixEdge<Int32Use>(node->child1());
203203 fixEdge<Int32Use>(node->child2());
204204 node->setResult(NodeResultInt32);
 205 } else if (node->child1()->shouldSpeculateHeapBigInt()) {
 206 // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
 207 // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
 208 node->setOp(op == Inc ? ValueAdd : ValueSub);
 209 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecHeapBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().heapBigIntConstantOne.get())));
 210 node->children.setChild2(Edge(nodeConstantOne));
 211 fixEdge<HeapBigIntUse>(node->child1());
 212 fixEdge<HeapBigIntUse>(node->child2());
 213 // HeapBigInts are cells, so the default of NodeResultJS is good here
 214#if USE(BIGINT32)
 215 } else if (node->child1()->shouldSpeculateBigInt32()) {
 216 node->setOp(op == Inc ? ValueAdd : ValueSub);
 217 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(JSValue(JSValue::JSBigInt32, 1))));
 218 node->children.setChild2(Edge(nodeConstantOne));
 219 fixEdge<BigInt32Use>(node->child1());
 220 fixEdge<BigInt32Use>(node->child2());
 221 // The default of NodeResultJS is good enough for now.
 222 // FIXME: consider having a special representation for small BigInts instead.
205223 } else if (node->child1()->shouldSpeculateBigInt()) {
206224 // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise.
 225 // FIXME: we might optimize inc/dec to a specialized function call instead in that case.
207226 node->setOp(op == Inc ? ValueAdd : ValueSub);
208  nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().bigIntConstantOne.get())));
 227 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt32, JSConstant, node->origin, OpInfo(m_graph.freeze(JSValue(JSValue::JSBigInt32, 1))));
209228 node->children.setChild2(Edge(nodeConstantOne));
210  fixEdge<BigIntUse>(node->child1());
211  fixEdge<BigIntUse>(node->child2());
212  // BigInts are currently cells, so the default of NodeResultJS is good here
 229 fixEdge<AnyBigIntUse>(node->child1());
 230 fixEdge<AnyBigIntUse>(node->child2());
 231 // The default of NodeResultJS is good here
 232#endif // USE(BIGINT32)
213233 } else if (node->child1()->shouldSpeculateInt52()) {
214234 node->setOp(op == Inc ? ArithAdd : ArithSub);
215235 node->setArithMode(Arith::CheckOverflow);

@@private:
235255 Edge& child1 = node->child1();
236256 Edge& child2 = node->child2();
237257
 258 if (Node::shouldSpeculateHeapBigInt(child1.node(), child2.node())) {
 259 fixEdge<HeapBigIntUse>(child1);
 260 fixEdge<HeapBigIntUse>(child2);
 261 break;
 262 }
 263
 264#if USE(BIGINT32)
238265 if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
239  fixEdge<BigIntUse>(child1);
240  fixEdge<BigIntUse>(child2);
 266 fixEdge<AnyBigIntUse>(child1);
 267 fixEdge<AnyBigIntUse>(child2);
241268 break;
242269 }
243 
 270#endif
 271
244272 if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
245273 fixEdge<UntypedUse>(child1);
246274 fixEdge<UntypedUse>(child2);

@@private:
268296 case ValueBitOr:
269297 case ValueBitAnd: {
270298 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
271  fixEdge<BigIntUse>(node->child1());
272  fixEdge<BigIntUse>(node->child2());
 299#if USE(BIGINT32)
 300 if (Node::shouldSpeculateBigInt32(node->child1().node(), node->child2().node())) {
 301 fixEdge<BigInt32Use>(node->child1());
 302 fixEdge<BigInt32Use>(node->child2());
 303 } else if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child2().node())) {
 304 fixEdge<HeapBigIntUse>(node->child1());
 305 fixEdge<HeapBigIntUse>(node->child2());
 306 } else {
 307 fixEdge<AnyBigIntUse>(node->child1());
 308 fixEdge<AnyBigIntUse>(node->child2());
 309 }
 310#else
 311 fixEdge<HeapBigIntUse>(node->child1());
 312 fixEdge<HeapBigIntUse>(node->child2());
 313#endif
273314 node->clearFlags(NodeMustGenerate);
274315 break;
275316 }

@@private:
313354
314355 if (operandEdge.node()->shouldSpeculateBigInt()) {
315356 node->clearFlags(NodeMustGenerate);
316  fixEdge<BigIntUse>(operandEdge);
 357
 358#if USE(BIGINT32)
 359 if (operandEdge.node()->shouldSpeculateBigInt32())
 360 fixEdge<BigInt32Use>(operandEdge);
 361 else if (operandEdge.node()->shouldSpeculateHeapBigInt())
 362 fixEdge<HeapBigIntUse>(operandEdge);
 363 else
 364 fixEdge<AnyBigIntUse>(operandEdge);
 365#else
 366 fixEdge<HeapBigIntUse>(operandEdge);
 367#endif
317368 } else if (operandEdge.node()->shouldSpeculateUntypedForBitOps())
318369 fixEdge<UntypedUse>(operandEdge);
319370 else {

@@private:
458509 }
459510 }
460511
461  if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
462  fixEdge<BigIntUse>(child1);
463  fixEdge<BigIntUse>(child2);
 512 if (Node::shouldSpeculateHeapBigInt(child1.node(), child2.node())) {
 513 fixEdge<HeapBigIntUse>(child1);
 514 fixEdge<HeapBigIntUse>(child2);
 515#if USE(BIGINT32)
 516 } else if (Node::shouldSpeculateBigInt32(child1.node(), child2.node())) {
 517 fixEdge<BigInt32Use>(child1);
 518 fixEdge<BigInt32Use>(child2);
 519 } else if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
 520 fixEdge<AnyBigIntUse>(child1);
 521 fixEdge<AnyBigIntUse>(child2);
 522#endif
464523 } else {
465524 fixEdge<UntypedUse>(child1);
466525 fixEdge<UntypedUse>(child2);

@@private:
546605 Edge& rightChild = node->child2();
547606
548607 if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
549  fixEdge<BigIntUse>(node->child1());
550  fixEdge<BigIntUse>(node->child2());
 608#if USE(BIGINT32)
 609 if (Node::shouldSpeculateBigInt32(leftChild.node(), rightChild.node())) {
 610 fixEdge<BigInt32Use>(node->child1());
 611 fixEdge<BigInt32Use>(node->child2());
 612 } else if (Node::shouldSpeculateHeapBigInt(leftChild.node(), rightChild.node())) {
 613 fixEdge<HeapBigIntUse>(node->child1());
 614 fixEdge<HeapBigIntUse>(node->child2());
 615 } else {
 616 fixEdge<AnyBigIntUse>(node->child1());
 617 fixEdge<AnyBigIntUse>(node->child2());
 618 }
 619#else
 620 fixEdge<HeapBigIntUse>(node->child1());
 621 fixEdge<HeapBigIntUse>(node->child2());
 622#endif
551623 node->clearFlags(NodeMustGenerate);
552624 break;
553625 }

@@private:
588660 Edge& leftChild = node->child1();
589661 Edge& rightChild = node->child2();
590662
 663 if (Node::shouldSpeculateHeapBigInt(leftChild.node(), rightChild.node())) {
 664 fixEdge<HeapBigIntUse>(leftChild);
 665 fixEdge<HeapBigIntUse>(rightChild);
 666 node->clearFlags(NodeMustGenerate);
 667 break;
 668 }
 669#if USE(BIGINT32)
591670 if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
592  fixEdge<BigIntUse>(leftChild);
593  fixEdge<BigIntUse>(rightChild);
 671 fixEdge<AnyBigIntUse>(leftChild);
 672 fixEdge<AnyBigIntUse>(rightChild);
594673 node->clearFlags(NodeMustGenerate);
595674 break;
596675 }
 676#endif
597677
598678 if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
599679 fixEdge<UntypedUse>(leftChild);

@@private:
657737 }
658738
659739 case ValuePow: {
 740 if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child1().node())) {
 741 fixEdge<HeapBigIntUse>(node->child1());
 742 fixEdge<HeapBigIntUse>(node->child2());
 743 node->clearFlags(NodeMustGenerate);
 744 break;
 745 }
 746#if USE(BIGINT32)
660747 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
661  fixEdge<BigIntUse>(node->child1());
662  fixEdge<BigIntUse>(node->child2());
 748 fixEdge<AnyBigIntUse>(node->child1());
 749 fixEdge<AnyBigIntUse>(node->child2());
663750 node->clearFlags(NodeMustGenerate);
664751 break;
665752 }
 753#endif
666754
667755 if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
668756 fixEdge<UntypedUse>(node->child1());

@@private:
25442632 case IsUndefinedOrNull:
25452633 case IsBoolean:
25462634 case IsNumber:
 2635 case IsBigInt:
25472636 case IsObjectOrNull:
25482637 case IsFunction:
25492638 case CreateDirectArguments:

@@private:
28852974 }
28862975
28872976 if (node->child1()->shouldSpeculateBigInt()) {
2888  fixEdge<BigIntUse>(node->child1());
 2977#if USE(BIGINT32)
 2978 if (node->child1()->shouldSpeculateBigInt32())
 2979 fixEdge<BigInt32Use>(node->child1());
 2980 else if (node->child1()->shouldSpeculateHeapBigInt())
 2981 fixEdge<HeapBigIntUse>(node->child1());
 2982 else
 2983 fixEdge<AnyBigIntUse>(node->child1());
 2984#else
 2985 fixEdge<HeapBigIntUse>(node->child1());
 2986#endif
28892987 node->convertToIdentity();
28902988 return;
28912989 }

@@private:
29583056 {
29593057 // If the prediction of the child is BigInt, we attempt to convert ToNumeric to Identity, since it can only return a BigInt when fed a BigInt.
29603058 if (node->child1()->shouldSpeculateBigInt()) {
2961  fixEdge<BigIntUse>(node->child1());
 3059#if USE(BIGINT32)
 3060 if (node->child1()->shouldSpeculateBigInt32())
 3061 fixEdge<BigInt32Use>(node->child1());
 3062 else if (node->child1()->shouldSpeculateHeapBigInt())
 3063 fixEdge<HeapBigIntUse>(node->child1());
 3064 else
 3065 fixEdge<AnyBigIntUse>(node->child1());
 3066#else
 3067 fixEdge<HeapBigIntUse>(node->child1());
 3068#endif
29623069 node->convertToIdentity();
29633070 return;
29643071 }

@@private:
34523559 case StringUse:
34533560 case KnownStringUse:
34543561 case SymbolUse:
3455  case BigIntUse:
 3562 case HeapBigIntUse:
34563563 case StringObjectUse:
34573564 case StringOrStringObjectUse:
34583565 if (alwaysUnboxSimplePrimitives()
34593566 || isCellSpeculation(variable->prediction()))
34603567 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
34613568 break;
 3569 // FIXME: what should we do about BigInt32Use and AnyBigIntUse ?
 3570 // Also more broadly, what about all of the UseKinds which are not listed in that switch?
34623571 default:
34633572 break;
34643573 }

@@private:
39724081 node->setOpAndDefaultFlags(CompareStrictEq);
39734082 return;
39744083 }
 4084 if (Node::shouldSpeculateHeapBigInt(node->child1().node(), node->child2().node())) {
 4085 fixEdge<HeapBigIntUse>(node->child1());
 4086 fixEdge<HeapBigIntUse>(node->child2());
 4087 node->setOpAndDefaultFlags(CompareStrictEq);
 4088 return;
 4089 }
 4090#if USE(BIGINT32)
 4091 if (Node::shouldSpeculateBigInt32(node->child1().node(), node->child2().node())) {
 4092 fixEdge<BigInt32Use>(node->child1());
 4093 fixEdge<BigInt32Use>(node->child2());
 4094 node->setOpAndDefaultFlags(CompareStrictEq);
 4095 return;
 4096 }
39754097 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
3976  fixEdge<BigIntUse>(node->child1());
3977  fixEdge<BigIntUse>(node->child2());
 4098 fixEdge<AnyBigIntUse>(node->child1());
 4099 fixEdge<AnyBigIntUse>(node->child2());
39784100 node->setOpAndDefaultFlags(CompareStrictEq);
39794101 return;
39804102 }
 4103#endif
39814104 if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
39824105 fixEdge<StringIdentUse>(node->child1());
39834106 fixEdge<StringIdentUse>(node->child2());

Source/JavaScriptCore/dfg/DFGMayExit.cpp

3232#include "DFGGraph.h"
3333#include "DFGNode.h"
3434#include "DFGNullAbstractState.h"
35 #include "Operations.h"
3635
3736namespace JSC { namespace DFG {
3837

Source/JavaScriptCore/dfg/DFGNode.h

11/*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@public:
26222622 {
26232623 return isSymbolSpeculation(prediction());
26242624 }
 2625
 2626#if USE(BIGINT32)
 2627 bool shouldSpeculateBigInt32()
 2628 {
 2629 return isBigInt32Speculation(prediction());
 2630 }
 2631#endif
 2632
 2633 bool shouldSpeculateHeapBigInt()
 2634 {
 2635 return isHeapBigIntSpeculation(prediction());
 2636 }
26252637
26262638 bool shouldSpeculateBigInt()
26272639 {

@@public:
28222834 {
28232835 return op1->shouldSpeculateBigInt() && op2->shouldSpeculateBigInt();
28242836 }
2825 
 2837
 2838#if USE(BIGINT32)
 2839 static bool shouldSpeculateBigInt32(Node* op1, Node* op2)
 2840 {
 2841 return op1->shouldSpeculateBigInt32() && op2->shouldSpeculateBigInt32();
 2842 }
 2843#endif
 2844
 2845 static bool shouldSpeculateHeapBigInt(Node* op1, Node* op2)
 2846 {
 2847 return op1->shouldSpeculateHeapBigInt() && op2->shouldSpeculateHeapBigInt();
 2848 }
 2849
28262850 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
28272851 {
28282852 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();

Source/JavaScriptCore/dfg/DFGNodeFlags.h

@@namespace JSC { namespace DFG {
5454#define NodeMayNegZeroInBaseline 0x00200
5555#define NodeMayNegZeroInDFG 0x00400
5656#define NodeMayHaveNonNumericResult 0x00800
 57// FIXME: we should have separate flags for HeapBigInt and BigInt32, currently prediction propagation will pessimize things.
5758#define NodeMayHaveBigIntResult 0x01000
5859#define NodeMayHaveNonIntResult (NodeMayHaveDoubleResult | NodeMayHaveNonNumericResult | NodeMayHaveBigIntResult)
5960

Source/JavaScriptCore/dfg/DFGNodeType.h

@@namespace JSC { namespace DFG {
396396 macro(IsUndefinedOrNull, NodeResultBoolean) \
397397 macro(IsBoolean, NodeResultBoolean) \
398398 macro(IsNumber, NodeResultBoolean) \
 399 /* IsBigInt is only used when USE_BIGINT32. Otherwise we emit IsCellWithType */\
 400 macro(IsBigInt, NodeResultBoolean) \
399401 macro(NumberIsInteger, NodeResultBoolean) \
400402 macro(IsObject, NodeResultBoolean) \
401403 macro(IsObjectOrNull, NodeResultBoolean) \

Source/JavaScriptCore/dfg/DFGOSRExit.cpp

@@void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
383383 // We can't be sure that we have a spare register. So use the numberTagRegister,
384384 // since we know how to restore it.
385385 jit.load64(AssemblyHelpers::Address(exit.m_jsValueSource.asAddress()), GPRInfo::numberTagRegister);
386  profile.emitReportValue(jit, JSValueRegs(GPRInfo::numberTagRegister));
 386 // We also use the notCellMaskRegister as the scratch register, for the same reason.
 387 // FIXME: find a less gross way of doing this, maybe through delaying these operations until we actually have some spare registers around?
 388 profile.emitReportValue(jit, JSValueRegs(GPRInfo::numberTagRegister), GPRInfo::notCellMaskRegister, DoNotHaveTagRegisters);
387389 jit.move(AssemblyHelpers::TrustedImm64(JSValue::NumberTag), GPRInfo::numberTagRegister);
388390 } else
389  profile.emitReportValue(jit, JSValueRegs(exit.m_jsValueSource.gpr()));
 391 profile.emitReportValue(jit, JSValueRegs(exit.m_jsValueSource.gpr()), GPRInfo::notCellMaskRegister, DoNotHaveTagRegisters);
 392 jit.move(AssemblyHelpers::TrustedImm64(JSValue::NotCellMask), GPRInfo::notCellMaskRegister);
390393#else // not USE(JSVALUE64)
391394 if (exit.m_jsValueSource.isAddress()) {
392395 // Save a register so we can use it.

@@void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
398401 JSValueRegs scratch(scratchTag, scratchPayload);
399402
400403 jit.loadValue(exit.m_jsValueSource.asAddress(), scratch);
401  profile.emitReportValue(jit, scratch);
 404 profile.emitReportValue(jit, scratch, InvalidGPRReg);
402405
403406 jit.popToRestore(scratchTag);
404407 jit.popToRestore(scratchPayload);

@@void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
407410 jit.pushToSave(scratchTag);
408411 jit.move(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), scratchTag);
409412 JSValueRegs value(scratchTag, exit.m_jsValueSource.payloadGPR());
410  profile.emitReportValue(jit, value);
 413 profile.emitReportValue(jit, value, InvalidGPRReg);
411414 jit.popToRestore(scratchTag);
412415 } else
413  profile.emitReportValue(jit, exit.m_jsValueSource.regs());
 416 profile.emitReportValue(jit, exit.m_jsValueSource.regs(), InvalidGPRReg);
414417#endif // USE(JSVALUE64)
415418 }
416419 }

Source/JavaScriptCore/dfg/DFGOSRExit.h

11/*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

Source/JavaScriptCore/dfg/DFGOperations.cpp

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

8989#include "TypedArrayInlines.h"
9090#include "VMInlines.h"
9191#include <wtf/InlineASM.h>
92 #include <wtf/Variant.h>
9392
9493#if ENABLE(JIT)
9594#if ENABLE(DFG_JIT)

@@static ALWAYS_INLINE void putWithThis(JSGlobalObject* globalObject, EncodedJSVal
224223 baseValue.putInline(globalObject, ident, putValue, slot);
225224}
226225
227 template<typename BigIntOperation, typename NumberOperation>
228 static ALWAYS_INLINE EncodedJSValue binaryOp(JSGlobalObject* globalObject, VM& vm, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, NumberOperation&& numberOp, const char* errorMessage)
229 {
230  auto scope = DECLARE_THROW_SCOPE(vm);
231 
232  JSValue op1 = JSValue::decode(encodedOp1);
233  JSValue op2 = JSValue::decode(encodedOp2);
234 
235  auto leftNumeric = op1.toNumeric(globalObject);
236  RETURN_IF_EXCEPTION(scope, encodedJSValue());
237  auto rightNumeric = op2.toNumeric(globalObject);
238  RETURN_IF_EXCEPTION(scope, encodedJSValue());
239 
240  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
241  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
242  RELEASE_AND_RETURN(scope, JSValue::encode(bigIntOp(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))));
243 
244  return throwVMTypeError(globalObject, scope, errorMessage);
245  }
246 
247  scope.release();
248 
249  return JSValue::encode(jsNumber(numberOp(WTF::get<double>(leftNumeric), WTF::get<double>(rightNumeric))));
250 }
251 
252 template<typename BigIntOperation, typename Int32Operation>
253 static ALWAYS_INLINE EncodedJSValue bitwiseBinaryOp(JSGlobalObject* globalObject, VM& vm, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, Int32Operation&& int32Op, const char* errorMessage)
254 {
255  auto scope = DECLARE_THROW_SCOPE(vm);
256 
257  JSValue op1 = JSValue::decode(encodedOp1);
258  JSValue op2 = JSValue::decode(encodedOp2);
259 
260  auto leftNumeric = op1.toBigIntOrInt32(globalObject);
261  RETURN_IF_EXCEPTION(scope, encodedJSValue());
262  auto rightNumeric = op2.toBigIntOrInt32(globalObject);
263  RETURN_IF_EXCEPTION(scope, encodedJSValue());
264 
265  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
266  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
267  RELEASE_AND_RETURN(scope, JSValue::encode(bigIntOp(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))));
268 
269  return throwVMTypeError(globalObject, scope, errorMessage);
270  }
271 
272  scope.release();
273 
274  return JSValue::encode(jsNumber(int32Op(WTF::get<int32_t>(leftNumeric), WTF::get<int32_t>(rightNumeric))));
275 }
276 
277226static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
278227{
279228 int asInt = static_cast<int>(input);

@@EncodedJSValue JIT_OPERATION operationValueMod(JSGlobalObject* globalObject, Enc
473422 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
474423 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
475424
476  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
477  return JSBigInt::remainder(globalObject, left, right);
478  };
479 
480  auto numberOp = [] (double left, double right) -> double {
481  return jsMod(left, right);
482  };
483 
484  return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in remainder operation.");
 425 return JSValue::encode(jsRemainder(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
485426}
486427
487 EncodedJSValue JIT_OPERATION operationInc(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
 428EncodedJSValue JIT_OPERATION operationInc(JSGlobalObject* globalObject, EncodedJSValue encodedOp)
488429{
489430 VM& vm = globalObject->vm();
490431 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
491432 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
492  auto scope = DECLARE_THROW_SCOPE(vm);
493433
494  JSValue op1 = JSValue::decode(encodedOp1);
495 
496  auto operandNumeric = op1.toNumeric(globalObject);
497  RETURN_IF_EXCEPTION(scope, encodedJSValue());
498 
499  if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
500  RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::inc(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
501 
502  double value = WTF::get<double>(operandNumeric);
503  return JSValue::encode(jsNumber(value + 1));
 434 return JSValue::encode(jsInc(globalObject, JSValue::decode(encodedOp)));
504435}
505436
506 EncodedJSValue JIT_OPERATION operationDec(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
 437EncodedJSValue JIT_OPERATION operationDec(JSGlobalObject* globalObject, EncodedJSValue encodedOp)
507438{
508439 VM& vm = globalObject->vm();
509440 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
510441 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
511  auto scope = DECLARE_THROW_SCOPE(vm);
512442
513  JSValue op1 = JSValue::decode(encodedOp1);
514 
515  auto operandNumeric = op1.toNumeric(globalObject);
516  RETURN_IF_EXCEPTION(scope, encodedJSValue());
517 
518  if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
519  RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::dec(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
520 
521  double value = WTF::get<double>(operandNumeric);
522  return JSValue::encode(jsNumber(value - 1));
 443 return JSValue::encode(jsDec(globalObject, JSValue::decode(encodedOp)));
523444}
524445
525 EncodedJSValue JIT_OPERATION operationValueBitNot(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
 446EncodedJSValue JIT_OPERATION operationValueBitNot(JSGlobalObject* globalObject, EncodedJSValue encodedOp)
526447{
527448 VM& vm = globalObject->vm();
528449 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
529450 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
530  auto scope = DECLARE_THROW_SCOPE(vm);
531 
532  JSValue op1 = JSValue::decode(encodedOp1);
533451
534  auto operandNumeric = op1.toBigIntOrInt32(globalObject);
535  RETURN_IF_EXCEPTION(scope, encodedJSValue());
536 
537  if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
538  RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::bitwiseNot(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
539 
540  return JSValue::encode(jsNumber(~WTF::get<int32_t>(operandNumeric)));
 452 return JSValue::encode(jsBitwiseNot(globalObject, JSValue::decode(encodedOp)));
541453}
542454
543455EncodedJSValue JIT_OPERATION operationValueBitAnd(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueBitAnd(JSGlobalObject* globalObject,
546458 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
547459 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
548460
549  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
550  return JSBigInt::bitwiseAnd(globalObject, left, right);
551  };
552 
553  auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
554  return left & right;
555  };
556 
557  return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'and' operation."_s);
 461 return JSValue::encode(jsBitwiseAnd(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
558462}
559463
560464EncodedJSValue JIT_OPERATION operationValueBitOr(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueBitOr(JSGlobalObject* globalObject, E
563467 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
564468 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
565469
566  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
567  return JSBigInt::bitwiseOr(globalObject, left, right);
568  };
569 
570  auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
571  return left | right;
572  };
573 
574  return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'or' operation."_s);
 470 return JSValue::encode(jsBitwiseOr(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
575471}
576472
577473EncodedJSValue JIT_OPERATION operationValueBitXor(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueBitXor(JSGlobalObject* globalObject,
580476 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
581477 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
582478
583  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
584  return JSBigInt::bitwiseXor(globalObject, left, right);
585  };
586 
587  auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
588  return left ^ right;
589  };
590 
591  return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'xor' operation."_s);
 479 return JSValue::encode(jsBitwiseXor(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
592480}
593481
594482EncodedJSValue JIT_OPERATION operationValueBitLShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueBitLShift(JSGlobalObject* globalObjec
597485 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
598486 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
599487
600  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
601  return JSBigInt::leftShift(globalObject, left, right);
602  };
603 
604  auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
605  return left << (right & 0x1f);
606  };
607 
608  return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in left shift operation."_s);
 488 return JSValue::encode(jsLShift(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
609489}
610490
611491EncodedJSValue JIT_OPERATION operationValueBitRShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueBitRShift(JSGlobalObject* globalObjec
614494 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
615495 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
616496
617  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
618  return JSBigInt::signedRightShift(globalObject, left, right);
619  };
620 
621  auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
622  return left >> (right & 0x1f);
623  };
624 
625  return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in signed right shift operation."_s);
 497 return JSValue::encode(jsRShift(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
626498}
627499
628500EncodedJSValue JIT_OPERATION operationValueBitURShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValueDiv(JSGlobalObject* globalObject, Enc
660532 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
661533 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
662534
663  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
664  return JSBigInt::divide(globalObject, left, right);
665  };
666 
667  auto numberOp = [] (double left, double right) -> double {
668  return left / right;
669  };
670 
671  return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in division operation.");
 535 return JSValue::encode(jsDiv(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
672536}
673537
674538EncodedJSValue JIT_OPERATION operationValuePow(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)

@@EncodedJSValue JIT_OPERATION operationValuePow(JSGlobalObject* globalObject, Enc
677541 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
678542 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
679543
680  auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
681  return JSBigInt::exponentiate(globalObject, left, right);
682  };
683 
684  auto numberOp = [] (double left, double right) -> double {
685  return operationMathPow(left, right);
686  };
687 
688  return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in exponentiation operation."_s);
 544 return JSValue::encode(jsPow(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
689545}
690546
691547double JIT_OPERATION operationArithAbs(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)

@@size_t JIT_OPERATION operationRegExpTestGeneric(JSGlobalObject* globalObject, En
14821338 RELEASE_AND_RETURN(scope, regexp->test(globalObject, input));
14831339}
14841340
1485 JSCell* JIT_OPERATION operationSubBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1341JSCell* JIT_OPERATION operationSubHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
14861342{
14871343 VM& vm = globalObject->vm();
14881344 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationSubBigInt(JSGlobalObject* globalObject, JSCell* o
14941350 return JSBigInt::sub(globalObject, leftOperand, rightOperand);
14951351}
14961352
1497 JSCell* JIT_OPERATION operationBitNotBigInt(JSGlobalObject* globalObject, JSCell* op1)
 1353JSCell* JIT_OPERATION operationBitNotHeapBigInt(JSGlobalObject* globalObject, JSCell* op1)
14981354{
14991355 VM& vm = globalObject->vm();
15001356 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationBitNotBigInt(JSGlobalObject* globalObject, JSCell
15051361 return JSBigInt::bitwiseNot(globalObject, operand);
15061362}
15071363
1508 JSCell* JIT_OPERATION operationMulBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1364JSCell* JIT_OPERATION operationMulHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15091365{
15101366 VM& vm = globalObject->vm();
15111367 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationMulBigInt(JSGlobalObject* globalObject, JSCell* o
15171373 return JSBigInt::multiply(globalObject, leftOperand, rightOperand);
15181374}
15191375
1520 JSCell* JIT_OPERATION operationModBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1376JSCell* JIT_OPERATION operationModHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15211377{
15221378 VM& vm = globalObject->vm();
15231379 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationModBigInt(JSGlobalObject* globalObject, JSCell* o
15291385 return JSBigInt::remainder(globalObject, leftOperand, rightOperand);
15301386}
15311387
1532 JSCell* JIT_OPERATION operationDivBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1388JSCell* JIT_OPERATION operationDivHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15331389{
15341390 VM& vm = globalObject->vm();
15351391 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationDivBigInt(JSGlobalObject* globalObject, JSCell* o
15411397 return JSBigInt::divide(globalObject, leftOperand, rightOperand);
15421398}
15431399
1544 JSCell* JIT_OPERATION operationPowBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1400JSCell* JIT_OPERATION operationPowHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15451401{
15461402 VM& vm = globalObject->vm();
15471403 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationPowBigInt(JSGlobalObject* globalObject, JSCell* o
15531409 return JSBigInt::exponentiate(globalObject, leftOperand, rightOperand);
15541410}
15551411
1556 JSCell* JIT_OPERATION operationBitAndBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1412JSCell* JIT_OPERATION operationBitAndHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15571413{
15581414 VM& vm = globalObject->vm();
15591415 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationBitAndBigInt(JSGlobalObject* globalObject, JSCell
15651421 return JSBigInt::bitwiseAnd(globalObject, leftOperand, rightOperand);
15661422}
15671423
1568 JSCell* JIT_OPERATION operationBitLShiftBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1424JSCell* JIT_OPERATION operationBitLShiftHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15691425{
15701426 VM& vm = globalObject->vm();
15711427 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationBitLShiftBigInt(JSGlobalObject* globalObject, JSC
15771433 return JSBigInt::leftShift(globalObject, leftOperand, rightOperand);
15781434}
15791435
1580 JSCell* JIT_OPERATION operationAddBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1436JSCell* JIT_OPERATION operationAddHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15811437{
15821438 VM& vm = globalObject->vm();
15831439 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationAddBigInt(JSGlobalObject* globalObject, JSCell* o
15891445 return JSBigInt::add(globalObject, leftOperand, rightOperand);
15901446}
15911447
1592 JSCell* JIT_OPERATION operationBitRShiftBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1448JSCell* JIT_OPERATION operationBitRShiftHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
15931449{
15941450 VM& vm = globalObject->vm();
15951451 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationBitRShiftBigInt(JSGlobalObject* globalObject, JSC
16011457 return JSBigInt::signedRightShift(globalObject, leftOperand, rightOperand);
16021458}
16031459
1604 JSCell* JIT_OPERATION operationBitOrBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1460JSCell* JIT_OPERATION operationBitOrHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
16051461{
16061462 VM& vm = globalObject->vm();
16071463 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@JSCell* JIT_OPERATION operationBitOrBigInt(JSGlobalObject* globalObject, JSCell*
16131469 return JSBigInt::bitwiseOr(globalObject, leftOperand, rightOperand);
16141470}
16151471
1616 JSCell* JIT_OPERATION operationBitXorBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
 1472JSCell* JIT_OPERATION operationBitXorHeapBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
16171473{
16181474 VM& vm = globalObject->vm();
16191475 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);

@@size_t JIT_OPERATION operationCompareStrictEqCell(JSGlobalObject* globalObject,
16311487 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
16321488 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
16331489
1634  return JSValue::strictEqualSlowCaseInline(globalObject, op1, op2);
 1490 return JSValue::strictEqualForCells(globalObject, op1, op2);
16351491}
16361492
16371493size_t JIT_OPERATION operationSameValue(JSGlobalObject* globalObject, EncodedJSValue arg1, EncodedJSValue arg2)

@@EncodedJSValue JIT_OPERATION operationToNumeric(JSGlobalObject* globalObject, En
16761532 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
16771533 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
16781534
1679  auto variant = JSValue::decode(value).toNumeric(globalObject);
1680  if (WTF::holds_alternative<JSBigInt*>(variant))
1681  return JSValue::encode(WTF::get<JSBigInt*>(variant));
1682  return JSValue::encode(jsNumber(WTF::get<double>(variant)));
 1535 return JSValue::encode(JSValue::decode(value).toNumeric(globalObject));
16831536}
16841537
16851538EncodedJSValue JIT_OPERATION operationGetByValWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)

Source/JavaScriptCore/dfg/DFGOperations.h

11/*
2  * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@size_t JIT_OPERATION operationRegExpTestString(JSGlobalObject*, RegExpObject*, J
183183size_t JIT_OPERATION operationRegExpTest(JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
184184size_t JIT_OPERATION operationRegExpTestGeneric(JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
185185size_t JIT_OPERATION operationCompareStrictEqCell(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
186 JSCell* JIT_OPERATION operationSubBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
187 JSCell* JIT_OPERATION operationMulBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
188 JSCell* JIT_OPERATION operationModBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
189 JSCell* JIT_OPERATION operationDivBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
190 JSCell* JIT_OPERATION operationPowBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
191 JSCell* JIT_OPERATION operationBitAndBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
192 JSCell* JIT_OPERATION operationBitNotBigInt(JSGlobalObject*, JSCell* op1) WTF_INTERNAL;
193 JSCell* JIT_OPERATION operationBitOrBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
194 JSCell* JIT_OPERATION operationBitLShiftBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
195 JSCell* JIT_OPERATION operationAddBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
196 JSCell* JIT_OPERATION operationBitRShiftBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
197 JSCell* JIT_OPERATION operationBitXorBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 186JSCell* JIT_OPERATION operationSubHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 187JSCell* JIT_OPERATION operationMulHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 188JSCell* JIT_OPERATION operationModHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 189JSCell* JIT_OPERATION operationDivHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 190JSCell* JIT_OPERATION operationPowHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 191JSCell* JIT_OPERATION operationBitAndHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 192JSCell* JIT_OPERATION operationBitNotHeapBigInt(JSGlobalObject*, JSCell* op1) WTF_INTERNAL;
 193JSCell* JIT_OPERATION operationBitOrHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 194JSCell* JIT_OPERATION operationBitLShiftHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 195JSCell* JIT_OPERATION operationAddHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 196JSCell* JIT_OPERATION operationBitRShiftHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 197JSCell* JIT_OPERATION operationBitXorHeapBigInt(JSGlobalObject*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
198198size_t JIT_OPERATION operationSameValue(JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
199199JSCell* JIT_OPERATION operationCreateActivationDirect(VM*, Structure*, JSScope*, SymbolTable*, EncodedJSValue);
200200JSCell* JIT_OPERATION operationCreateDirectArguments(VM*, Structure*, uint32_t length, uint32_t minCapacity);

Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

@@private:
532532 changed |= mergePrediction(SpecSymbol);
533533 break;
534534 }
535 
 535
 536#if USE(BIGINT32)
 537 if (node->child1()->shouldSpeculateBigInt32()) {
 538 changed |= mergePrediction(SpecBigInt32);
 539 break;
 540 }
 541#endif
 542
 543 if (node->child1()->shouldSpeculateHeapBigInt()) {
 544 changed |= mergePrediction(SpecHeapBigInt);
 545 break;
 546 }
 547
536548 if (node->child1()->shouldSpeculateBigInt()) {
537549 changed |= mergePrediction(SpecBigInt);
538550 break;

@@private:
10041016 case IsUndefinedOrNull:
10051017 case IsBoolean:
10061018 case IsNumber:
 1019 case IsBigInt:
10071020 case NumberIsInteger:
10081021 case IsObject:
10091022 case IsObjectOrNull:

Source/JavaScriptCore/dfg/DFGSafeToExecute.h

@@public:
7979 case StringUse:
8080 case StringOrOtherUse:
8181 case SymbolUse:
82  case BigIntUse:
 82 case AnyBigIntUse:
 83 case HeapBigIntUse:
 84 case BigInt32Use:
8385 case StringObjectUse:
8486 case StringOrStringObjectUse:
8587 case NotStringVarUse:

@@bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
263265 case IsUndefinedOrNull:
264266 case IsBoolean:
265267 case IsNumber:
 268 case IsBigInt:
266269 case NumberIsInteger:
267270 case IsObject:
268271 case IsObjectOrNull:

@@bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
677680 case ValueDiv:
678681 case ValueMod:
679682 case ValuePow:
680  return node->isBinaryUseKind(BigIntUse);
 683 return node->isBinaryUseKind(AnyBigIntUse) || node->isBinaryUseKind(BigInt32Use) || node->isBinaryUseKind(HeapBigIntUse);
681684
682685 case ValueBitNot:
683  return node->child1().useKind() == BigIntUse;
 686 return node->child1().useKind() == AnyBigIntUse || node->child1().useKind() == BigInt32Use || node->child1().useKind() == HeapBigIntUse;
684687
685688 case LastNodeType:
686689 RELEASE_ASSERT_NOT_REACHED();

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType t
368368 speculationCheck(exitKind, source, edge.node(), jumpToFail);
369369}
370370
 371void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::JumpList jumpListToFail, ExitKind exitKind)
 372{
 373 ASSERT(needsTypeCheck(edge, typesPassedThrough));
 374 m_interpreter.filter(edge, typesPassedThrough);
 375 speculationCheck(exitKind, source, edge.node(), jumpListToFail);
 376}
 377
371378RegisterSet SpeculativeJIT::usedRegisters()
372379{
373380 RegisterSet result;

@@bool SpeculativeJIT::compilePeepHoleBranch(Node* node, MacroAssembler::Relationa
17081715
17091716 if (node->isBinaryUseKind(Int32Use))
17101717 compilePeepHoleInt32Branch(node, branchNode, condition);
 1718#if USE(BIGINT32)
 1719 else if (node->isBinaryUseKind(BigInt32Use) && (condition == MacroAssembler::Equal || condition == MacroAssembler::NotEqual))
 1720 compilePeepHoleBigInt32Branch(node, branchNode, condition);
 1721#endif
17111722#if USE(JSVALUE64)
17121723 else if (node->isBinaryUseKind(Int52RepUse))
17131724 compilePeepHoleInt52Branch(node, branchNode, condition);

@@void SpeculativeJIT::compileValueBitNot(Node* node)
35353546{
35363547 Edge& child1 = node->child1();
35373548
3538  if (child1.useKind() == BigIntUse) {
 3549#if USE(BIGINT32)
 3550 if (child1.useKind() == BigInt32Use) {
 3551 SpeculateBigInt32Operand operand(this, child1);
 3552 GPRTemporary result(this);
 3553 GPRReg resultGPR = result.gpr();
 3554
 3555 // The following trick relies on details of the representation of BigInt32, and will have to be updated if we move bits around.
 3556 static_assert(JSValue::BigInt32Tag == 0x12);
 3557 static_assert(JSValue::BigInt32Mask == 0xfffe000000000012);
 3558 constexpr uint64_t maskForBigInt32Bits = 0x0000ffffffff0000;
 3559 static_assert(!(JSValue::BigInt32Mask & maskForBigInt32Bits));
 3560 m_jit.move(TrustedImm64(maskForBigInt32Bits), resultGPR);
 3561 m_jit.xor64(operand.gpr(), resultGPR);
 3562
 3563 jsValueResult(resultGPR, node);
 3564
 3565 return;
 3566 }
 3567 // FIXME: add support for mixed BigInt32 / HeapBigInt
 3568#endif
 3569
 3570 if (child1.useKind() == HeapBigIntUse) {
35393571 SpeculateCellOperand operand(this, child1);
35403572 GPRReg operandGPR = operand.gpr();
35413573
3542  speculateBigInt(child1, operandGPR);
 3574 speculateHeapBigInt(child1, operandGPR);
35433575
35443576 flushRegisters();
35453577 GPRFlushedCallResult result(this);
35463578 GPRReg resultGPR = result.gpr();
35473579
3548  callOperation(operationBitNotBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), operandGPR);
 3580 callOperation(operationBitNotHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), operandGPR);
35493581 m_jit.exceptionCheck();
35503582 cellResult(resultGPR, node);
35513583
35523584 return;
35533585 }
35543586
3555  JSValueOperand operand(this, child1);
 3587 ASSERT(child1.useKind() == UntypedUse || child1.useKind() == AnyBigIntUse);
 3588 JSValueOperand operand(this, child1, ManualOperandSpeculation);
 3589 speculate(node, child1); // Required for the AnyBigIntUse case
35563590 JSValueRegs operandRegs = operand.jsValueRegs();
35573591
35583592 flushRegisters();

@@void SpeculativeJIT::compileBitwiseNot(Node* node)
35803614}
35813615
35823616template<typename SnippetGenerator, J_JITOperation_GJJ snippetSlowPathFunction>
3583 void SpeculativeJIT::emitUntypedBitOp(Node* node)
 3617void SpeculativeJIT::emitUntypedOrAnyBigIntBitOp(Node* node)
35843618{
35853619 Edge& leftChild = node->child1();
35863620 Edge& rightChild = node->child2();
35873621
 3622 ASSERT(leftChild.useKind() == UntypedUse || leftChild.useKind() == AnyBigIntUse || rightChild.useKind() == UntypedUse || rightChild.useKind() == AnyBigIntUse);
 3623
35883624 if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3589  JSValueOperand left(this, leftChild);
3590  JSValueOperand right(this, rightChild);
 3625 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 3626 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 3627 speculate(node, leftChild);
 3628 speculate(node, rightChild);
35913629 JSValueRegs leftRegs = left.jsValueRegs();
35923630 JSValueRegs rightRegs = right.jsValueRegs();
35933631

@@void SpeculativeJIT::emitUntypedBitOp(Node* node)
36323670 RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
36333671
36343672 if (!leftOperand.isConst()) {
3635  left.emplace(this, leftChild);
 3673 left.emplace(this, leftChild, ManualOperandSpeculation);
 3674 speculate(node, leftChild); // Required for AnyBigIntUse
36363675 leftRegs = left->jsValueRegs();
36373676 }
36383677 if (!rightOperand.isConst()) {
3639  right.emplace(this, rightChild);
 3678 right.emplace(this, rightChild, ManualOperandSpeculation);
 3679 speculate(node, rightChild); // Required for AnyBigIntUse
36403680 rightRegs = right->jsValueRegs();
36413681 }
36423682

@@void SpeculativeJIT::compileValueBitwiseOp(Node* node)
36723712 Edge& leftChild = node->child1();
36733713 Edge& rightChild = node->child2();
36743714
3675  if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
 3715#if USE(BIGINT32)
 3716 if (leftChild.useKind() == BigInt32Use && rightChild.useKind() == BigInt32Use) {
 3717 SpeculateBigInt32Operand left(this, leftChild);
 3718 SpeculateBigInt32Operand right(this, rightChild);
 3719 GPRTemporary result(this);
 3720 GPRReg resultGPR = result.gpr();
 3721
 3722 m_jit.move(left.gpr(), resultGPR);
 3723
36763724 switch (op) {
36773725 case ValueBitAnd:
3678  emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
3679  return;
3680  case ValueBitXor:
3681  emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
3682  return;
 3726 // No need to unbox/box: bitAnd does not interfere with the encoding of BigInt32
 3727 m_jit.and64(right.gpr(), resultGPR);
 3728 break;
36833729 case ValueBitOr:
3684  emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
3685  return;
 3730 // No need to unbox/box: bitOr does not interfere with the encoding of BigInt32
 3731 m_jit.or64(right.gpr(), resultGPR);
 3732 break;
 3733 case ValueBitXor:
 3734 // BitXor removes the tag, so we must add it back after doing the operation
 3735 m_jit.xor64(right.gpr(), resultGPR);
 3736 m_jit.or64(TrustedImm32(JSValue::BigInt32Tag), resultGPR);
 3737 break;
36863738 default:
36873739 RELEASE_ASSERT_NOT_REACHED();
36883740 }
 3741
 3742 jsValueResult(resultGPR, node);
 3743 return;
36893744 }
3690 
3691  ASSERT(leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse);
3692 
3693  SpeculateCellOperand left(this, node->child1());
3694  SpeculateCellOperand right(this, node->child2());
3695  GPRReg leftGPR = left.gpr();
3696  GPRReg rightGPR = right.gpr();
 3745 // FIXME: add support for mixed BigInt32 / HeapBigInt
 3746#endif
36973747
3698  speculateBigInt(leftChild, leftGPR);
3699  speculateBigInt(rightChild, rightGPR);
 3748 if (leftChild.useKind() == HeapBigIntUse && rightChild.useKind() == HeapBigIntUse) {
 3749 SpeculateCellOperand left(this, node->child1());
 3750 SpeculateCellOperand right(this, node->child2());
 3751 GPRReg leftGPR = left.gpr();
 3752 GPRReg rightGPR = right.gpr();
37003753
3701  flushRegisters();
3702  GPRFlushedCallResult result(this);
3703  GPRReg resultGPR = result.gpr();
 3754 speculateHeapBigInt(leftChild, leftGPR);
 3755 speculateHeapBigInt(rightChild, rightGPR);
 3756
 3757 flushRegisters();
 3758 GPRFlushedCallResult result(this);
 3759 GPRReg resultGPR = result.gpr();
 3760
 3761 switch (op) {
 3762 case ValueBitAnd:
 3763 callOperation(operationBitAndHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 3764 break;
 3765 case ValueBitXor:
 3766 callOperation(operationBitXorHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 3767 break;
 3768 case ValueBitOr:
 3769 callOperation(operationBitOrHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 3770 break;
 3771 default:
 3772 RELEASE_ASSERT_NOT_REACHED();
 3773 }
 3774
 3775 m_jit.exceptionCheck();
 3776 cellResult(resultGPR, node);
 3777 return;
 3778 }
37043779
37053780 switch (op) {
37063781 case ValueBitAnd:
3707  callOperation(operationBitAndBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
3708  break;
 3782 emitUntypedOrAnyBigIntBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
 3783 return;
37093784 case ValueBitXor:
3710  callOperation(operationBitXorBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
3711  break;
 3785 emitUntypedOrAnyBigIntBitOp<JITBitXorGenerator, operationValueBitXor>(node);
 3786 return;
37123787 case ValueBitOr:
3713  callOperation(operationBitOrBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
3714  break;
 3788 emitUntypedOrAnyBigIntBitOp<JITBitOrGenerator, operationValueBitOr>(node);
 3789 return;
37153790 default:
37163791 RELEASE_ASSERT_NOT_REACHED();
37173792 }
3718 
3719  m_jit.exceptionCheck();
3720  cellResult(resultGPR, node);
37213793}
37223794
37233795void SpeculativeJIT::compileBitwiseOp(Node* node)

@@void SpeculativeJIT::compileBitwiseOp(Node* node)
37573829 strictInt32Result(result.gpr(), node);
37583830}
37593831
3760 void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
 3832void SpeculativeJIT::emitUntypedOrBigIntRightShiftBitOp(Node* node)
37613833{
37623834 J_JITOperation_GJJ snippetSlowPathFunction = node->op() == ValueBitRShift
37633835 ? operationValueBitRShift : operationValueBitURShift;

@@void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
37673839 Edge& leftChild = node->child1();
37683840 Edge& rightChild = node->child2();
37693841
3770  if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3771  JSValueOperand left(this, leftChild);
3772  JSValueOperand right(this, rightChild);
 3842 if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node()) || node->isBinaryUseKind(BigInt32Use) || node->isBinaryUseKind(AnyBigIntUse)) {
 3843 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 3844 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 3845 speculate(node, leftChild);
 3846 speculate(node, rightChild);
37733847 JSValueRegs leftRegs = left.jsValueRegs();
37743848 JSValueRegs rightRegs = right.jsValueRegs();
37753849

@@void SpeculativeJIT::compileValueLShiftOp(Node* node)
38613935 Edge& leftChild = node->child1();
38623936 Edge& rightChild = node->child2();
38633937
3864  if (node->binaryUseKind() == BigIntUse) {
 3938 // FIXME: support BigInt32
 3939 if (node->binaryUseKind() == HeapBigIntUse) {
38653940 SpeculateCellOperand left(this, leftChild);
38663941 SpeculateCellOperand right(this, rightChild);
38673942 GPRReg leftGPR = left.gpr();
38683943 GPRReg rightGPR = right.gpr();
38693944
3870  speculateBigInt(leftChild, leftGPR);
3871  speculateBigInt(rightChild, rightGPR);
 3945 speculateHeapBigInt(leftChild, leftGPR);
 3946 speculateHeapBigInt(rightChild, rightGPR);
38723947
38733948 flushRegisters();
38743949 GPRFlushedCallResult result(this);
38753950 GPRReg resultGPR = result.gpr();
38763951
3877  callOperation(operationBitLShiftBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 3952 callOperation(operationBitLShiftHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
38783953 m_jit.exceptionCheck();
38793954 cellResult(resultGPR, node);
38803955 return;
38813956 }
38823957
3883  ASSERT(leftChild.useKind() == UntypedUse && rightChild.useKind() == UntypedUse);
3884  emitUntypedBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
 3958 emitUntypedOrAnyBigIntBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
38853959}
38863960
38873961void SpeculativeJIT::compileValueBitRShift(Node* node)

@@void SpeculativeJIT::compileValueBitRShift(Node* node)
38893963 Edge& leftChild = node->child1();
38903964 Edge& rightChild = node->child2();
38913965
3892  if (node->isBinaryUseKind(BigIntUse)) {
 3966 // FIXME: support BigInt32
 3967 if (node->isBinaryUseKind(HeapBigIntUse)) {
38933968 SpeculateCellOperand left(this, leftChild);
38943969 SpeculateCellOperand right(this, rightChild);
38953970 GPRReg leftGPR = left.gpr();
38963971 GPRReg rightGPR = right.gpr();
38973972
3898  speculateBigInt(leftChild, leftGPR);
3899  speculateBigInt(rightChild, rightGPR);
 3973 speculateHeapBigInt(leftChild, leftGPR);
 3974 speculateHeapBigInt(rightChild, rightGPR);
39003975
39013976 flushRegisters();
39023977 GPRFlushedCallResult result(this);
39033978 GPRReg resultGPR = result.gpr();
3904  callOperation(operationBitRShiftBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 3979 callOperation(operationBitRShiftHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
39053980 m_jit.exceptionCheck();
39063981
39073982 cellResult(resultGPR, node);
39083983 return;
39093984 }
39103985
3911  ASSERT(leftChild.useKind() == UntypedUse && rightChild.useKind() == UntypedUse);
3912  emitUntypedRightShiftBitOp(node);
 3986 emitUntypedOrBigIntRightShiftBitOp(node);
39133987}
39143988
39153989void SpeculativeJIT::compileShiftOp(Node* node)

@@void SpeculativeJIT::compileShiftOp(Node* node)
39203994
39213995 if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
39223996 RELEASE_ASSERT(op == BitURShift);
3923  emitUntypedRightShiftBitOp(node);
 3997 emitUntypedOrBigIntRightShiftBitOp(node);
39243998 return;
39253999 }
39264000

@@void SpeculativeJIT::compileValueAdd(Node* node)
39504024 Edge& leftChild = node->child1();
39514025 Edge& rightChild = node->child2();
39524026
3953  if (node->isBinaryUseKind(BigIntUse)) {
3954  SpeculateCellOperand left(this, node->child1());
3955  SpeculateCellOperand right(this, node->child2());
 4027#if USE(BIGINT32)
 4028 if (node->isBinaryUseKind(BigInt32Use)) {
 4029 SpeculateBigInt32Operand left(this, leftChild);
 4030 SpeculateBigInt32Operand right(this, rightChild);
 4031
 4032 // FIXME: do we really need this extra register, or can we mutate left/right ?
 4033 // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
 4034 GPRTemporary result(this);
 4035 GPRReg resultGPR = result.gpr();
 4036 GPRTemporary temp(this);
 4037 GPRReg tempGPR = temp.gpr();
 4038
 4039 m_jit.move(left.gpr(), resultGPR);
 4040 m_jit.unboxBigInt32(resultGPR);
 4041 m_jit.move(right.gpr(), tempGPR);
 4042 m_jit.unboxBigInt32(tempGPR);
 4043
 4044 // FIXME: add some way to eliminate the overflow check
 4045 MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
 4046
 4047 speculationCheck(Overflow, JSValueRegs(), 0, check);
 4048
 4049 m_jit.boxBigInt32(resultGPR);
 4050 jsValueResult(resultGPR, node);
 4051 return;
 4052 }
 4053
 4054 if (node->isBinaryUseKind(AnyBigIntUse)) {
 4055 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 4056 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 4057 speculate(node, leftChild);
 4058 speculate(node, rightChild);
 4059 JSValueRegs leftRegs = left.jsValueRegs();
 4060 JSValueRegs rightRegs = right.jsValueRegs();
 4061
 4062 flushRegisters();
 4063 JSValueRegsFlushedCallResult result(this);
 4064 JSValueRegs resultRegs = result.regs();
 4065 // FIXME: call a more specialized function
 4066 callOperation(operationValueAddNotNumber, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftRegs, rightRegs);
 4067 m_jit.exceptionCheck();
 4068
 4069 jsValueResult(resultRegs, node);
 4070 return;
 4071 }
 4072 // FIXME: add support for mixed BigInt32/HeapBigInt
 4073#endif // USE(BIGINT32)
 4074
 4075 if (node->isBinaryUseKind(HeapBigIntUse)) {
 4076 SpeculateCellOperand left(this, leftChild);
 4077 SpeculateCellOperand right(this, rightChild);
39564078 GPRReg leftGPR = left.gpr();
39574079 GPRReg rightGPR = right.gpr();
39584080
3959  speculateBigInt(leftChild, leftGPR);
3960  speculateBigInt(rightChild, rightGPR);
 4081 speculateHeapBigInt(leftChild, leftGPR);
 4082 speculateHeapBigInt(rightChild, rightGPR);
39614083
39624084 flushRegisters();
39634085 GPRFlushedCallResult result(this);
39644086 GPRReg resultGPR = result.gpr();
3965  callOperation(operationAddBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 4087 callOperation(operationAddHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
39664088 m_jit.exceptionCheck();
39674089
39684090 cellResult(resultGPR, node);

@@void SpeculativeJIT::compileValueSub(Node* node)
40084130 Edge& leftChild = node->child1();
40094131 Edge& rightChild = node->child2();
40104132
4011  if (node->binaryUseKind() == UntypedUse) {
4012 #if USE(JSVALUE64)
4013  bool needsScratchGPRReg = true;
4014  bool needsScratchFPRReg = false;
4015 #else
4016  bool needsScratchGPRReg = true;
4017  bool needsScratchFPRReg = true;
4018 #endif
 4133#if USE(BIGINT32)
 4134 if (node->binaryUseKind() == BigInt32Use) {
 4135 SpeculateBigInt32Operand left(this, node->child1());
 4136 SpeculateBigInt32Operand right(this, node->child2());
 4137
 4138 // FIXME: do we really need this extra register, or can we mutate left/right ?
 4139 // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
 4140 GPRTemporary result(this);
 4141 GPRReg resultGPR = result.gpr();
 4142 GPRTemporary temp(this);
 4143 GPRReg tempGPR = temp.gpr();
 4144
 4145 m_jit.move(left.gpr(), resultGPR);
 4146 m_jit.unboxBigInt32(resultGPR);
 4147 m_jit.move(right.gpr(), tempGPR);
 4148 m_jit.unboxBigInt32(tempGPR);
40194149
4020  CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
4021  BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
4022  BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
4023  JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile);
4024  auto repatchingFunction = operationValueSubOptimize;
4025  auto nonRepatchingFunction = operationValueSub;
 4150 // FIXME: add some way to eliminate the overflow check
 4151 MacroAssembler::Jump check = m_jit.branchSub32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
40264152
4027  compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
 4153 speculationCheck(Overflow, JSValueRegs(), 0, check);
 4154
 4155 m_jit.boxBigInt32(resultGPR);
 4156 jsValueResult(resultGPR, node);
40284157 return;
40294158 }
 4159 // FIXME: add support for mixed BigInt32/HeapBigInt
40304160
4031  ASSERT(leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse);
 4161 // FIXME: why do compileValueAdd/compileValueMul use isKnownNotNumber but not ValueSub?
 4162 if (node->binaryUseKind() == AnyBigIntUse) {
 4163 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 4164 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 4165 speculateAnyBigInt(leftChild);
 4166 speculateAnyBigInt(rightChild);
 4167 JSValueRegs leftRegs = left.jsValueRegs();
 4168 JSValueRegs rightRegs = right.jsValueRegs();
40324169
4033  SpeculateCellOperand left(this, node->child1());
4034  SpeculateCellOperand right(this, node->child2());
4035  GPRReg leftGPR = left.gpr();
4036  GPRReg rightGPR = right.gpr();
 4170 flushRegisters();
 4171 JSValueRegsFlushedCallResult result(this);
 4172 JSValueRegs resultRegs = result.regs();
 4173 callOperation(operationValueSub, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftRegs, rightRegs);
 4174 m_jit.exceptionCheck();
 4175
 4176 jsValueResult(resultRegs, node);
 4177 return;
 4178 }
 4179#endif // USE(BIGINT32)
40374180
4038  speculateBigInt(leftChild, leftGPR);
4039  speculateBigInt(rightChild, rightGPR);
 4181 if (node->binaryUseKind() == HeapBigIntUse) {
 4182 SpeculateCellOperand left(this, node->child1());
 4183 SpeculateCellOperand right(this, node->child2());
 4184 GPRReg leftGPR = left.gpr();
 4185 GPRReg rightGPR = right.gpr();
40404186
4041  flushRegisters();
4042  GPRFlushedCallResult result(this);
4043  GPRReg resultGPR = result.gpr();
 4187 speculateHeapBigInt(leftChild, leftGPR);
 4188 speculateHeapBigInt(rightChild, rightGPR);
40444189
4045  callOperation(operationSubBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 4190 flushRegisters();
 4191 GPRFlushedCallResult result(this);
 4192 GPRReg resultGPR = result.gpr();
40464193
4047  m_jit.exceptionCheck();
4048  cellResult(resultGPR, node);
 4194 callOperation(operationSubHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 4195
 4196 m_jit.exceptionCheck();
 4197 cellResult(resultGPR, node);
 4198 return;
 4199 }
 4200
 4201#if USE(JSVALUE64)
 4202 bool needsScratchGPRReg = true;
 4203 bool needsScratchFPRReg = false;
 4204#else
 4205 bool needsScratchGPRReg = true;
 4206 bool needsScratchFPRReg = true;
 4207#endif
 4208
 4209 CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
 4210 BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
 4211 BinaryArithProfile* arithProfile = baselineCodeBlock->binaryArithProfileForBytecodeIndex(bytecodeIndex);
 4212 JITSubIC* subIC = m_jit.codeBlock()->addJITSubIC(arithProfile);
 4213 auto repatchingFunction = operationValueSubOptimize;
 4214 auto nonRepatchingFunction = operationValueSub;
 4215
 4216 compileMathIC(node, subIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
40494217}
40504218
40514219template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>

@@void SpeculativeJIT::compileIncOrDec(Node* node)
46304798
46314799void SpeculativeJIT::compileValueNegate(Node* node)
46324800{
 4801 // FIXME: add a fast path, at least for BigInt32, but probably also for HeapBigInt here.
46334802 CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic);
46344803 BytecodeIndex bytecodeIndex = node->origin.semantic.bytecodeIndex();
46354804 UnaryArithProfile* arithProfile = baselineCodeBlock->unaryArithProfileForBytecodeIndex(bytecodeIndex);

@@void SpeculativeJIT::compileValueMul(Node* node)
48104979 Edge& leftChild = node->child1();
48114980 Edge& rightChild = node->child2();
48124981
4813  if (leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse) {
 4982#if USE(BIGINT32)
 4983 if (node->binaryUseKind() == BigInt32Use) {
 4984 // FIXME: the code between compileValueAdd, compileValueSub and compileValueMul for BigInt32 is nearly identical, so try to get rid of the duplication.
 4985 SpeculateBigInt32Operand left(this, node->child1());
 4986 SpeculateBigInt32Operand right(this, node->child2());
 4987
 4988 // FIXME: do we really need this extra register, or can we mutate left/right ?
 4989 // FIXME: also, look into Reuse and other tricks for a more efficient generated code.
 4990 GPRTemporary result(this);
 4991 GPRReg resultGPR = result.gpr();
 4992 GPRTemporary temp(this);
 4993 GPRReg tempGPR = temp.gpr();
 4994
 4995 m_jit.move(left.gpr(), resultGPR);
 4996 m_jit.unboxBigInt32(resultGPR);
 4997 m_jit.move(right.gpr(), tempGPR);
 4998 m_jit.unboxBigInt32(tempGPR);
 4999
 5000 // FIXME: add some way to eliminate the overflow check
 5001 MacroAssembler::Jump check = m_jit.branchMul32(MacroAssembler::Overflow, resultGPR, tempGPR, resultGPR);
 5002
 5003 speculationCheck(Overflow, JSValueRegs(), 0, check);
 5004
 5005 m_jit.boxBigInt32(resultGPR);
 5006 jsValueResult(resultGPR, node);
 5007 return;
 5008 }
 5009 // FIXME: add support for mixed BigInt32/HeapBigInt
 5010#endif
 5011
 5012 if (leftChild.useKind() == HeapBigIntUse && rightChild.useKind() == HeapBigIntUse) {
48145013 SpeculateCellOperand left(this, leftChild);
48155014 SpeculateCellOperand right(this, rightChild);
48165015 GPRReg leftGPR = left.gpr();
48175016 GPRReg rightGPR = right.gpr();
48185017
4819  speculateBigInt(leftChild, leftGPR);
4820  speculateBigInt(rightChild, rightGPR);
 5018 speculateHeapBigInt(leftChild, leftGPR);
 5019 speculateHeapBigInt(rightChild, rightGPR);
48215020
48225021 flushRegisters();
48235022 GPRFlushedCallResult result(this);
48245023 GPRReg resultGPR = result.gpr();
48255024
4826  callOperation(operationMulBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 5025 callOperation(operationMulHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
48275026
48285027 m_jit.exceptionCheck();
48295028 cellResult(resultGPR, node);
48305029 return;
48315030 }
48325031
4833  if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
4834  JSValueOperand left(this, leftChild);
4835  JSValueOperand right(this, rightChild);
 5032 if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node()) || node->isBinaryUseKind(AnyBigIntUse)) {
 5033 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 5034 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 5035 speculate(node, leftChild);
 5036 speculate(node, rightChild);
48365037 JSValueRegs leftRegs = left.jsValueRegs();
48375038 JSValueRegs rightRegs = right.jsValueRegs();
48385039

@@void SpeculativeJIT::compileValueDiv(Node* node)
50125213 Edge& leftChild = node->child1();
50135214 Edge& rightChild = node->child2();
50145215
5015  if (leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse) {
 5216 // FIXME: add a fast path for BigInt32. Currently we go through the slow path, because of how ugly the code for Div gets.
 5217
 5218 if (node->isBinaryUseKind(HeapBigIntUse)) {
50165219 SpeculateCellOperand left(this, leftChild);
50175220 SpeculateCellOperand right(this, rightChild);
50185221 GPRReg leftGPR = left.gpr();
50195222 GPRReg rightGPR = right.gpr();
50205223
5021  speculateBigInt(leftChild, leftGPR);
5022  speculateBigInt(rightChild, rightGPR);
 5224 speculateHeapBigInt(leftChild, leftGPR);
 5225 speculateHeapBigInt(rightChild, rightGPR);
50235226
50245227 flushRegisters();
50255228 GPRFlushedCallResult result(this);
50265229 GPRReg resultGPR = result.gpr();
50275230
5028  callOperation(operationDivBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 5231 callOperation(operationDivHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
50295232
50305233 m_jit.exceptionCheck();
50315234 cellResult(resultGPR, node);
50325235 return;
50335236 }
50345237
5035  if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
5036  JSValueOperand left(this, leftChild);
5037  JSValueOperand right(this, rightChild);
 5238 if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node()) || node->isBinaryUseKind(AnyBigIntUse) || node->isBinaryUseKind(BigInt32Use)) {
 5239 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 5240 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 5241 speculate(node, leftChild);
 5242 speculate(node, rightChild);
50385243 JSValueRegs leftRegs = left.jsValueRegs();
50395244 JSValueRegs rightRegs = right.jsValueRegs();
50405245

@@void SpeculativeJIT::compileValueDiv(Node* node)
50485253 return;
50495254 }
50505255
 5256 ASSERT(node->isBinaryUseKind(UntypedUse));
 5257
50515258 Optional<JSValueOperand> left;
50525259 Optional<JSValueOperand> right;
50535260

@@void SpeculativeJIT::compileValueMod(Node* node)
52975504 Edge& leftChild = node->child1();
52985505 Edge& rightChild = node->child2();
52995506
5300  if (node->binaryUseKind() == BigIntUse) {
 5507 // FIXME: add a fast path for BigInt32. Currently we go through the slow path, because of how ugly the code for Mod gets.
 5508
 5509 if (node->binaryUseKind() == HeapBigIntUse) {
53015510 SpeculateCellOperand left(this, leftChild);
53025511 SpeculateCellOperand right(this, rightChild);
53035512 GPRReg leftGPR = left.gpr();
53045513 GPRReg rightGPR = right.gpr();
53055514
5306  speculateBigInt(leftChild, leftGPR);
5307  speculateBigInt(rightChild, rightGPR);
 5515 speculateHeapBigInt(leftChild, leftGPR);
 5516 speculateHeapBigInt(rightChild, rightGPR);
53085517
53095518 flushRegisters();
53105519 GPRFlushedCallResult result(this);
53115520 GPRReg resultGPR = result.gpr();
53125521
5313  callOperation(operationModBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 5522 callOperation(operationModHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
53145523
53155524 m_jit.exceptionCheck();
53165525 cellResult(resultGPR, node);
53175526 return;
53185527 }
53195528
5320  DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse, node->binaryUseKind());
5321  JSValueOperand op1(this, leftChild);
5322  JSValueOperand op2(this, rightChild);
 5529 DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use, node->binaryUseKind());
 5530 JSValueOperand op1(this, leftChild, ManualOperandSpeculation);
 5531 JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
 5532 speculate(node, leftChild);
 5533 speculate(node, rightChild);
53235534 JSValueRegs op1Regs = op1.jsValueRegs();
53245535 JSValueRegs op2Regs = op2.jsValueRegs();
53255536 flushRegisters();

@@void SpeculativeJIT::compileValuePow(Node* node)
58616072 Edge& leftChild = node->child1();
58626073 Edge& rightChild = node->child2();
58636074
5864  if (node->binaryUseKind() == BigIntUse) {
 6075 // FIXME: do we want a fast path for BigInt32 for Pow? I expect it would overflow pretty often.
 6076 if (node->binaryUseKind() == HeapBigIntUse) {
58656077 SpeculateCellOperand left(this, leftChild);
58666078 SpeculateCellOperand right(this, rightChild);
58676079 GPRReg leftGPR = left.gpr();
58686080 GPRReg rightGPR = right.gpr();
58696081
5870  speculateBigInt(leftChild, leftGPR);
5871  speculateBigInt(rightChild, rightGPR);
 6082 speculateHeapBigInt(leftChild, leftGPR);
 6083 speculateHeapBigInt(rightChild, rightGPR);
58726084
58736085 flushRegisters();
58746086 GPRFlushedCallResult result(this);
58756087 GPRReg resultGPR = result.gpr();
58766088
5877  callOperation(operationPowBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
 6089 callOperation(operationPowHeapBigInt, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), leftGPR, rightGPR);
58786090
58796091 m_jit.exceptionCheck();
58806092 cellResult(resultGPR, node);
58816093 return;
58826094 }
58836095
5884  DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse, node->binaryUseKind());
 6096 DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse || node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use, node->binaryUseKind());
58856097
5886  JSValueOperand left(this, leftChild);
5887  JSValueOperand right(this, rightChild);
 6098 JSValueOperand left(this, leftChild, ManualOperandSpeculation);
 6099 JSValueOperand right(this, rightChild, ManualOperandSpeculation);
 6100 speculate(node, leftChild);
 6101 speculate(node, rightChild);
58886102 JSValueRegs leftRegs = left.jsValueRegs();
58896103 JSValueRegs rightRegs = right.jsValueRegs();
58906104

@@bool SpeculativeJIT::compare(Node* node, MacroAssembler::RelationalCondition con
60326246 return false;
60336247 }
60346248
 6249#if USE(BIGINT32)
 6250 if (node->isBinaryUseKind(BigInt32Use)) {
 6251 compileBigInt32Compare(node, condition);
 6252 return false;
 6253 }
 6254#endif
60356255#if USE(JSVALUE64)
60366256 if (node->isBinaryUseKind(Int52RepUse)) {
60376257 compileInt52Compare(node, condition);

@@bool SpeculativeJIT::compare(Node* node, MacroAssembler::RelationalCondition con
60606280 return false;
60616281 }
60626282
 6283 // FIXME: add HeapBigInt case here.
 6284 // Not having it means that the compare will not be fused with the branch for this case.
 6285
60636286 if (node->op() == CompareEq) {
60646287 if (node->isBinaryUseKind(BooleanUse)) {
60656288 compileBooleanCompare(node, condition);

@@bool SpeculativeJIT::compileStrictEq(Node* node)
61386361 return false;
61396362 }
61406363
6141 #if USE(JSVALUE64)
 6364#if USE(BIGINT32)
 6365 if (node->isBinaryUseKind(BigInt32Use)) {
 6366 unsigned branchIndexInBlock = detectPeepHoleBranch();
 6367 if (branchIndexInBlock != UINT_MAX) {
 6368 Node* branchNode = m_block->at(branchIndexInBlock);
 6369 compilePeepHoleBigInt32Branch(node, branchNode, MacroAssembler::Equal);
 6370 use(node->child1());
 6371 use(node->child2());
 6372 m_indexInBlock = branchIndexInBlock;
 6373 m_currentNode = branchNode;
 6374 return true;
 6375 }
 6376 compileBigInt32Compare(node, MacroAssembler::Equal);
 6377 return false;
 6378 }
 6379#endif
 6380
 6381#if USE(JSVALUE64)
61426382 if (node->isBinaryUseKind(Int52RepUse)) {
61436383 unsigned branchIndexInBlock = detectPeepHoleBranch();
61446384 if (branchIndexInBlock != UINT_MAX) {

@@bool SpeculativeJIT::compileStrictEq(Node* node)
61856425 return false;
61866426 }
61876427
6188  if (node->isBinaryUseKind(BigIntUse)) {
6189  compileBigIntEquality(node);
 6428 if (node->isBinaryUseKind(HeapBigIntUse)) {
 6429 compileHeapBigIntEquality(node);
61906430 return false;
61916431 }
61926432

@@bool SpeculativeJIT::compileStrictEq(Node* node)
62806520 compileStringToUntypedEquality(node, node->child2(), node->child1());
62816521 return false;
62826522 }
6283 
6284  RELEASE_ASSERT(node->isBinaryUseKind(UntypedUse));
 6523
 6524 ASSERT(node->isBinaryUseKind(UntypedUse) || node->isBinaryUseKind(AnyBigIntUse));
62856525 return nonSpeculativeStrictEq(node);
62866526}
62876527

@@void SpeculativeJIT::speculateSymbol(Edge edge)
1054010780 speculateSymbol(edge, operand.gpr());
1054110781}
1054210782
10543 void SpeculativeJIT::speculateBigInt(Edge edge, GPRReg cell)
 10783void SpeculativeJIT::speculateHeapBigInt(Edge edge, GPRReg cell)
1054410784{
10545  DFG_TYPE_CHECK(JSValueSource::unboxedCell(cell), edge, ~SpecCellCheck | SpecBigInt, m_jit.branchIfNotBigInt(cell));
 10785 DFG_TYPE_CHECK(JSValueSource::unboxedCell(cell), edge, ~SpecCellCheck | SpecHeapBigInt, m_jit.branchIfNotHeapBigInt(cell));
1054610786}
1054710787
10548 void SpeculativeJIT::speculateBigInt(Edge edge)
 10788void SpeculativeJIT::speculateHeapBigInt(Edge edge)
1054910789{
1055010790 if (!needsTypeCheck(edge, SpecBigInt))
1055110791 return;
1055210792
1055310793 SpeculateCellOperand operand(this, edge);
10554  speculateBigInt(edge, operand.gpr());
 10794 speculateHeapBigInt(edge, operand.gpr());
1055510795}
1055610796
1055710797void SpeculativeJIT::speculateNotCell(Edge edge, JSValueRegs regs)

@@void SpeculativeJIT::speculate(Node*, Edge edge)
1072110961 case SymbolUse:
1072210962 speculateSymbol(edge);
1072310963 break;
10724  case BigIntUse:
10725  speculateBigInt(edge);
 10964#if USE(BIGINT32)
 10965 case BigInt32Use:
 10966 speculateBigInt32(edge);
 10967 break;
 10968 case AnyBigIntUse:
 10969 speculateAnyBigInt(edge);
 10970 break;
 10971#endif
 10972 case HeapBigIntUse:
 10973 speculateHeapBigInt(edge);
1072610974 break;
1072710975 case StringObjectUse:
1072810976 speculateStringObject(edge);

@@void SpeculativeJIT::compileToNumeric(Node* node)
1308113329 JSValueRegs argumentRegs = argument.jsValueRegs();
1308213330 JSValueRegs resultRegs = result.regs();
1308313331 GPRReg scratch = temp.gpr();
 13332 // FIXME: add a fast path for BigInt32 here (and for typeOf, and for boolify or whatever it is called in this file).
1308413333
1308513334 MacroAssembler::JumpList slowCases;
1308613335
1308713336 MacroAssembler::Jump notCell = m_jit.branchIfNotCell(argumentRegs);
13088  slowCases.append(m_jit.branchIfNotBigInt(argumentRegs.payloadGPR()));
13089  MacroAssembler::Jump isBigInt = m_jit.jump();
 13337 slowCases.append(m_jit.branchIfNotHeapBigInt(argumentRegs.payloadGPR()));
 13338 MacroAssembler::Jump isHeapBigInt = m_jit.jump();
1309013339
1309113340 notCell.link(&m_jit);
1309213341 slowCases.append(m_jit.branchIfNotNumber(argumentRegs, scratch));
1309313342
13094  isBigInt.link(&m_jit);
 13343 isHeapBigInt.link(&m_jit);
1309513344 m_jit.moveValueRegs(argumentRegs, resultRegs);
1309613345
1309713346 addSlowPathGenerator(slowPathCall(slowCases, this, operationToNumeric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), argumentRegs));

@@void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode,
1398014229 m_currentNode = branchNode;
1398114230}
1398214231
13983 void SpeculativeJIT::compileBigIntEquality(Node* node)
 14232void SpeculativeJIT::compileHeapBigIntEquality(Node* node)
1398414233{
13985  // FIXME: [ESNext][BigInt] Create specialized version of strict equals for BigIntUse
 14234 // FIXME: [ESNext][BigInt] Create specialized version of strict equals for big ints
1398614235 // https://bugs.webkit.org/show_bug.cgi?id=182895
1398714236 SpeculateCellOperand left(this, node->child1());
1398814237 SpeculateCellOperand right(this, node->child2());

@@void SpeculativeJIT::compileBigIntEquality(Node* node)
1399414243 left.use();
1399514244 right.use();
1399614245
13997  speculateBigInt(node->child1(), leftGPR);
13998  speculateBigInt(node->child2(), rightGPR);
 14246 speculateHeapBigInt(node->child1(), leftGPR);
 14247 speculateHeapBigInt(node->child2(), rightGPR);
1399914248
1400014249 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, leftGPR, rightGPR);
1400114250

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@public:
346346 FPRReg fillSpeculateDouble(Edge);
347347 GPRReg fillSpeculateCell(Edge);
348348 GPRReg fillSpeculateBoolean(Edge);
 349#if USE(BIGINT32)
 350 GPRReg fillSpeculateBigInt32(Edge);
 351#endif
349352 GeneratedOperandType checkGeneratedTypeForToInt32(Node*);
350353
351354 void addSlowPathGenerator(std::unique_ptr<SlowPathGenerator>);

@@public:
11481151 bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_JITOperation_GJJ);
11491152 void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
11501153 void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
 1154#if USE(BIGINT32)
 1155 void compilePeepHoleBigInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
 1156#endif
11511157 void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition);
11521158 void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition);
11531159 void compilePeepHoleObjectEquality(Node*, Node* branchNode);

@@public:
11721178 void compileMiscStrictEq(Node*);
11731179
11741180 void compileSymbolEquality(Node*);
1175  void compileBigIntEquality(Node*);
 1181 void compileHeapBigIntEquality(Node*);
11761182 void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
11771183 void compileSymbolUntypedEquality(Node*, Edge symbolEdge, Edge untypedEdge);
11781184

@@public:
12221228
12231229 void compileInt32Compare(Node*, MacroAssembler::RelationalCondition);
12241230 void compileInt52Compare(Node*, MacroAssembler::RelationalCondition);
 1231#if USE(BIGINT32)
 1232 void compileBigInt32Compare(Node*, MacroAssembler::RelationalCondition);
 1233#endif
12251234 void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition);
12261235 void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition);
12271236 void compileStringCompare(Node*, MacroAssembler::RelationalCondition);

@@public:
12971306 void compileBitwiseNot(Node*);
12981307
12991308 template<typename SnippetGenerator, J_JITOperation_GJJ slowPathFunction>
1300  void emitUntypedBitOp(Node*);
 1309 void emitUntypedOrAnyBigIntBitOp(Node*);
13011310 void compileBitwiseOp(Node*);
13021311 void compileValueBitwiseOp(Node*);
13031312
1304  void emitUntypedRightShiftBitOp(Node*);
 1313 void emitUntypedOrBigIntRightShiftBitOp(Node*);
13051314 void compileValueLShiftOp(Node*);
13061315 void compileValueBitRShift(Node*);
13071316 void compileShiftOp(Node*);

@@public:
15611570 // Helpers for performing type checks on an edge stored in the given registers.
15621571 bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); }
15631572 void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind = BadType);
 1573 void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::JumpList jumpListToFail, ExitKind = BadType);
15641574
15651575 void speculateCellTypeWithoutTypeFiltering(Edge, GPRReg cellGPR, JSType);
15661576 void speculateCellType(Edge, GPRReg cellGPR, SpeculatedType, JSType);

@@public:
15721582 void speculateInt32(Edge, JSValueRegs);
15731583 void speculateDoubleRepAnyInt(Edge);
15741584#endif // USE(JSVALUE64)
 1585#if USE(BIGINT32)
 1586 void speculateBigInt32(Edge);
 1587 void speculateAnyBigInt(Edge);
 1588#endif // USE(BIGINT32)
15751589 void speculateNumber(Edge);
15761590 void speculateRealNumber(Edge);
15771591 void speculateDoubleRepReal(Edge);

@@public:
16211635 void speculateStringOrStringObject(Edge);
16221636 void speculateSymbol(Edge, GPRReg cell);
16231637 void speculateSymbol(Edge);
1624  void speculateBigInt(Edge, GPRReg cell);
1625  void speculateBigInt(Edge);
 1638 void speculateHeapBigInt(Edge, GPRReg cell);
 1639 void speculateHeapBigInt(Edge);
16261640 void speculateNotCell(Edge, JSValueRegs);
16271641 void speculateNotCell(Edge);
16281642 void speculateOther(Edge, JSValueRegs, GPRReg temp);

@@private:
26002614 GPRReg m_gprOrInvalid;
26012615};
26022616
 2617#if USE(BIGINT32)
 2618class SpeculateBigInt32Operand {
 2619 WTF_MAKE_FAST_ALLOCATED;
 2620public:
 2621 explicit SpeculateBigInt32Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
 2622 : m_jit(jit)
 2623 , m_edge(edge)
 2624 , m_gprOrInvalid(InvalidGPRReg)
 2625 {
 2626 ASSERT(m_jit);
 2627 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BigInt32Use);
 2628 if (jit->isFilled(node()))
 2629 gpr();
 2630 }
 2631
 2632 ~SpeculateBigInt32Operand()
 2633 {
 2634 ASSERT(m_gprOrInvalid != InvalidGPRReg);
 2635 m_jit->unlock(m_gprOrInvalid);
 2636 }
 2637
 2638 Edge edge() const
 2639 {
 2640 return m_edge;
 2641 }
 2642
 2643 Node* node() const
 2644 {
 2645 return edge().node();
 2646 }
 2647
 2648 GPRReg gpr()
 2649 {
 2650 if (m_gprOrInvalid == InvalidGPRReg)
 2651 m_gprOrInvalid = m_jit->fillSpeculateBigInt32(edge());
 2652 return m_gprOrInvalid;
 2653 }
 2654
 2655 void use()
 2656 {
 2657 m_jit->use(node());
 2658 }
 2659
 2660private:
 2661 SpeculativeJIT* m_jit;
 2662 Edge m_edge;
 2663 GPRReg m_gprOrInvalid;
 2664};
 2665#endif // USE(BIGINT32)
 2666
26032667#define DFG_TYPE_CHECK_WITH_EXIT_KIND(exitKind, source, edge, typesPassedThrough, jumpToFail) do { \
26042668 JSValueSource _dtc_source = (source); \
26052669 Edge _dtc_edge = (edge); \

Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

@@void SpeculativeJIT::compile(Node* node)
41864186 case CheckArrayOrEmpty:
41874187 DFG_CRASH(m_jit.graph(), node, "CheckArrayOrEmpty only used in 64-bit DFG");
41884188 break;
4189 
 4189
 4190 case IsBigInt:
 4191 DFG_CRASH(m_jit.graph(), node, "IsBigInt is only used when USE_BIGINT32, which can only be true in 64 bit mode");
 4192 break;
 4193
41904194 case FilterCallLinkStatus:
41914195 case FilterGetByStatus:
41924196 case FilterPutByIdStatus:

Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@GPRReg SpeculativeJIT::fillJSValue(Edge edge)
138138 case DataFormatJSInt32:
139139 case DataFormatJSDouble:
140140 case DataFormatJSCell:
141  case DataFormatJSBoolean: {
 141 case DataFormatJSBoolean:
 142 case DataFormatJSBigInt32: {
142143 GPRReg gpr = info.gpr();
143144 m_gprs.lock(gpr);
144145 return gpr;

@@void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode
340341 notTaken = tmp;
341342 }
342343
343  JSValueOperand arg1(this, node->child1());
344  JSValueOperand arg2(this, node->child2());
 344 ASSERT(node->isBinaryUseKind(UntypedUse) || node->isBinaryUseKind(AnyBigIntUse));
 345 JSValueOperand arg1(this, node->child1(), ManualOperandSpeculation);
 346 JSValueOperand arg2(this, node->child2(), ManualOperandSpeculation);
 347 speculate(node, node->child1());
 348 speculate(node, node->child2());
345349 GPRReg arg1GPR = arg1.gpr();
346350 GPRReg arg2GPR = arg2.gpr();
347351

@@void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode
363367
364368 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
365369 } else {
366  m_jit.or64(arg1GPR, arg2GPR, resultGPR);
367 
368  JITCompiler::Jump twoCellsCase = m_jit.branchIfCell(resultGPR);
369 
370  JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1GPR);
371  JITCompiler::Jump leftDouble = m_jit.branchIfNumber(arg1GPR);
372  leftOK.link(&m_jit);
373  JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2GPR);
374  JITCompiler::Jump rightDouble = m_jit.branchIfNumber(arg2GPR);
375  rightOK.link(&m_jit);
376 
377  branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
378  jump(notTaken, ForceJump);
379 
380  twoCellsCase.link(&m_jit);
 370 /* At a high level we do (assuming 'invert' to be false):
 371 If (left is Double || right is Double)
 372 goto slowPath;
 373 if (left == right)
 374 goto taken;
 375 if (left is Cell || right is Cell)
 376 goto slowPath;
 377 goto notTaken;
 378 */
 379
 380 JITCompiler::JumpList slowPathCases;
 381
 382 // This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 383 // The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 384 // If it is not a number at all, then 1<<49 will be its only high bit set
 385 // Leaving only doubles above or equal 1<<50.
 386 GPRTemporary scratch(this);
 387 m_jit.move(arg1GPR, resultGPR);
 388 m_jit.move(arg2GPR, scratch.gpr());
 389 m_jit.add64(TrustedImm64(JSValue::LowestOfHighBits), resultGPR);
 390 m_jit.add64(TrustedImm64(JSValue::LowestOfHighBits), scratch.gpr());
 391 m_jit.or64(scratch.gpr(), resultGPR, resultGPR);
 392 constexpr uint64_t nextLowestOfHighBits = JSValue::LowestOfHighBits << 1;
 393 slowPathCases.append(m_jit.branch64(JITCompiler::AboveOrEqual, resultGPR, TrustedImm64(nextLowestOfHighBits)));
 394
381395 branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
382396
383  leftDouble.link(&m_jit);
384  rightDouble.link(&m_jit);
385 
386  silentSpillAllRegisters(resultGPR);
387  callOperation(operationCompareStrictEq, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR);
388  silentFillAllRegisters();
389  m_jit.exceptionCheck();
390 
 397 // If we support BigInt32 we must go to a slow path if at least one operand is a cell (for HeapBigInt === BigInt32)
 398 // If we don't support BigInt32, we only have to go to a slow path if both operands are cells (for HeapBigInt === HeapBigInt and String === String)
 399 // Instead of doing two branches, we can do a single one, by observing that
 400 // 1. (left is Cell && right is Cell) is the same as ((left | right) is Cell)
 401 // Both are "All high bits are 0"
 402 // 2. Since we know that neither is a double, (left is Cell || right is Cell) is equivalent to ((left & right) is Cell)
 403 // If both are Int32, then the top bits will be set and the test will fail
 404 // If at least one is not Int32, then the top bits will be 0.
 405 // And if at least one is a cell, then the 'Other' tag will also be 0, making the test succeed
 406#if USE(BIGINT32)
 407 m_jit.and64(arg1GPR, arg2GPR, resultGPR);
 408#else
 409 m_jit.or64(arg1GPR, arg2GPR, resultGPR);
 410#endif
 411 slowPathCases.append(m_jit.branchIfCell(resultGPR));
 412
 413 jump(invert ? taken : notTaken, ForceJump);
 414
 415 addSlowPathGenerator(slowPathCall(slowPathCases, this, operationCompareStrictEq, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR));
391416 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
392417 }
393 
 418
394419 jump(notTaken);
395420}
396421
397422void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
398423{
 424 // FIXME: some of this code should be shareable with nonSpeculativePeepholeStrictEq
399425 JSValueOperand arg1(this, node->child1());
400426 JSValueOperand arg2(this, node->child2());
401427 JSValueRegs arg1Regs = arg1.jsValueRegs();
402428 JSValueRegs arg2Regs = arg2.jsValueRegs();
 429 GPRReg arg1GPR = arg1.gpr();
 430 GPRReg arg2GPR = arg2.gpr();
403431
404432 GPRTemporary result(this);
405433 GPRReg resultGPR = result.gpr();

@@void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
428456 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
429457 return;
430458 }
431 
432  m_jit.or64(arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
 459 /* At a high level we do (assuming 'invert' to be false):
 460 If (left is Double || right is Double)
 461 goto slowPath;
 462 result = (left == right);
 463 if (result)
 464 goto done;
 465 if (left is Cell || right is Cell)
 466 goto slowPath;
 467 done:
 468 return result;
 469 */
433470
434471 JITCompiler::JumpList slowPathCases;
435472
436  JITCompiler::Jump twoCellsCase = m_jit.branchIfCell(resultGPR);
437 
438  JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1Regs);
439  slowPathCases.append(m_jit.branchIfNumber(arg1Regs, InvalidGPRReg));
440  leftOK.link(&m_jit);
441  JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2Regs);
442  slowPathCases.append(m_jit.branchIfNumber(arg2Regs, InvalidGPRReg));
443  rightOK.link(&m_jit);
444 
445  m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
446 
447  JITCompiler::Jump done = m_jit.jump();
448 
449  twoCellsCase.link(&m_jit);
450  slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr()));
 473 // This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 474 // The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 475 // If it is not a number at all, then 1<<49 will be its only high bit set
 476 // Leaving only doubles above or equal 1<<50.
 477 GPRTemporary scratch(this);
 478 m_jit.move(arg1GPR, resultGPR);
 479 m_jit.move(arg2GPR, scratch.gpr());
 480 m_jit.add64(TrustedImm64(JSValue::LowestOfHighBits), resultGPR);
 481 m_jit.add64(TrustedImm64(JSValue::LowestOfHighBits), scratch.gpr());
 482 m_jit.or64(scratch.gpr(), resultGPR, resultGPR);
 483 constexpr uint64_t nextLowestOfHighBits = JSValue::LowestOfHighBits << 1;
 484 slowPathCases.append(m_jit.branch64(JITCompiler::AboveOrEqual, resultGPR, TrustedImm64(nextLowestOfHighBits)));
 485
 486 m_jit.compare64(JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
 487 JITCompiler::Jump done = m_jit.branchTest64(JITCompiler::NonZero, resultGPR);
 488
 489 // If we support BigInt32 we must go to a slow path if at least one operand is a cell (for HeapBigInt === BigInt32)
 490 // If we don't support BigInt32, we only have to go to a slow path if both operands are cells (for HeapBigInt === HeapBigInt and String === String)
 491 // Instead of doing two branches, we can do a single one, by observing that
 492 // 1. (left is Cell && right is Cell) is the same as ((left | right) is Cell)
 493 // Both are "All high bits are 0"
 494 // 2. Since we know that neither is a double, (left is Cell || right is Cell) is equivalent to ((left & right) is Cell)
 495 // If both are Int32, then the top bits will be set and the test will fail
 496 // If at least one is not Int32, then the top bits will be 0.
 497 // And if at least one is a cell, then the 'Other' tag will also be 0, making the test succeed
 498#if USE(BIGINT32)
 499 m_jit.and64(arg1GPR, arg2GPR, resultGPR);
 500#else
 501 m_jit.or64(arg1GPR, arg2GPR, resultGPR);
 502#endif
 503 slowPathCases.append(m_jit.branchIfCell(resultGPR));
451504
452  m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR);
 505 m_jit.move(TrustedImm64(0), resultGPR);
453506
454507 addSlowPathGenerator(slowPathCall(slowPathCases, this, operationCompareStrictEq, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1Regs, arg2Regs));
455508
456509 done.link(&m_jit);
457510
 511 m_jit.xor64(TrustedImm64(invert), resultGPR);
 512
458513 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
459514}
460515

@@GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
10041059 case DataFormatStorage:
10051060 case DataFormatInt52:
10061061 case DataFormatStrictInt52:
 1062 case DataFormatBigInt32:
 1063 case DataFormatJSBigInt32:
10071064 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
10081065
10091066 default:

@@GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
11841241 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
11851242
11861243 switch (info.registerFormat()) {
 1244 // FIXME: some of these cases look like they could share code.
 1245 // Look at fillSpeculateInt32Internal for an example.
11871246 case DataFormatNone: {
11881247 GPRReg gpr = allocate();
11891248

@@GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
12351294 case DataFormatStorage:
12361295 case DataFormatInt52:
12371296 case DataFormatStrictInt52:
 1297 case DataFormatBigInt32:
 1298 case DataFormatJSBigInt32:
12381299 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
12391300
12401301 default:

@@GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
13121373 case DataFormatStorage:
13131374 case DataFormatInt52:
13141375 case DataFormatStrictInt52:
 1376 case DataFormatBigInt32:
 1377 case DataFormatJSBigInt32:
13151378 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
13161379
13171380 default:

@@GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
13201383 }
13211384}
13221385
 1386#if USE(BIGINT32)
 1387void SpeculativeJIT::speculateBigInt32(Edge edge)
 1388{
 1389 if (!needsTypeCheck(edge, SpecBigInt32))
 1390 return;
 1391
 1392 (SpeculateBigInt32Operand(this, edge)).gpr();
 1393}
 1394
 1395void SpeculativeJIT::speculateAnyBigInt(Edge edge)
 1396{
 1397 if (!needsTypeCheck(edge, SpecBigInt))
 1398 return;
 1399
 1400 JSValueOperand value(this, edge, ManualOperandSpeculation);
 1401 JSValueRegs valueRegs = value.jsValueRegs();
 1402 GPRReg tempGPR = allocate();
 1403 JITCompiler::Jump notCell = m_jit.branchIfNotCell(valueRegs);
 1404 // I inlined speculateHeapBigInt because it would be incorrect to call it here if it did JSValueOperand / SpeculateXXXOperand,
 1405 // as it would confuse the DFG register allocator.
 1406 DFG_TYPE_CHECK(valueRegs, edge, ~SpecCellCheck | SpecHeapBigInt, m_jit.branchIfNotHeapBigInt(valueRegs.gpr()));
 1407 auto done = m_jit.jump();
 1408 notCell.link(&m_jit);
 1409 DFG_TYPE_CHECK(valueRegs, edge, SpecCellCheck | SpecBigInt32, m_jit.branchIfNotBigInt32(valueRegs.gpr(), tempGPR));
 1410 done.link(&m_jit);
 1411 unlock(tempGPR);
 1412}
 1413
 1414GPRReg SpeculativeJIT::fillSpeculateBigInt32(Edge edge)
 1415{
 1416 AbstractValue& value = m_state.forNode(edge);
 1417 SpeculatedType type = value.m_type;
 1418
 1419 m_interpreter.filter(value, SpecBigInt32);
 1420 if (value.isClear()) {
 1421 if (mayHaveTypeCheck(edge.useKind()))
 1422 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
 1423 return allocate();
 1424 }
 1425
 1426 VirtualRegister virtualRegister = edge->virtualRegister();
 1427 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
 1428
 1429 switch (info.registerFormat()) {
 1430 case DataFormatNone: {
 1431 GPRReg gpr = allocate();
 1432
 1433 if (edge->hasConstant()) {
 1434 JSValue jsValue = edge->asJSValue();
 1435 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
 1436 ASSERT(jsValue.isBigInt32());
 1437 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
 1438 info.fillJSValue(*m_stream, gpr, DataFormatJSBigInt32);
 1439 return gpr;
 1440 }
 1441
 1442 DataFormat spillFormat = info.spillFormat();
 1443 DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatBigInt32, spillFormat);
 1444
 1445 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
 1446
 1447 if (spillFormat == DataFormatBigInt32) {
 1448 // We have not yet implemented this
 1449 RELEASE_ASSERT_NOT_REACHED();
 1450 }
 1451 if (spillFormat == DataFormatJSBigInt32) {
 1452 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
 1453 info.fillJSValue(*m_stream, gpr, DataFormatJSBigInt32);
 1454 return gpr;
 1455 }
 1456
 1457 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
 1458
 1459 info.fillJSValue(*m_stream, gpr, DataFormatJS);
 1460 m_gprs.unlock(gpr);
 1461 FALLTHROUGH;
 1462 }
 1463
 1464 case DataFormatJS: {
 1465 GPRReg gpr = info.gpr();
 1466 m_gprs.lock(gpr);
 1467 if (type & ~SpecBigInt32) {
 1468 CCallHelpers::JumpList failureCases;
 1469 GPRReg tempGPR = allocate();
 1470 failureCases.append(m_jit.branchIfNumber(gpr));
 1471 failureCases.append(m_jit.branchIfNotBigInt32KnownNotNumber(gpr, tempGPR));
 1472 speculationCheck(BadType, JSValueRegs(gpr), edge, failureCases);
 1473 unlock(tempGPR);
 1474 }
 1475 info.fillJSValue(*m_stream, gpr, DataFormatJSBigInt32);
 1476 return gpr;
 1477 }
 1478
 1479 case DataFormatJSBigInt32: {
 1480 GPRReg gpr = info.gpr();
 1481 m_gprs.lock(gpr);
 1482 return gpr;
 1483 }
 1484
 1485 case DataFormatBoolean:
 1486 case DataFormatJSBoolean:
 1487 case DataFormatJSInt32:
 1488 case DataFormatInt32:
 1489 case DataFormatJSDouble:
 1490 case DataFormatJSCell:
 1491 case DataFormatCell:
 1492 case DataFormatDouble:
 1493 case DataFormatStorage:
 1494 case DataFormatInt52:
 1495 case DataFormatStrictInt52:
 1496 case DataFormatBigInt32:
 1497 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
 1498
 1499 default:
 1500 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
 1501 return InvalidGPRReg;
 1502 }
 1503}
 1504#endif // USE(BIGINT32)
 1505
13231506void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
13241507{
13251508 SpeculateCellOperand op1(this, objectChild);

@@void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JI
15561739 jump(notTaken);
15571740}
15581741
 1742#if USE(BIGINT32)
 1743void SpeculativeJIT::compileBigInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
 1744{
 1745 SpeculateBigInt32Operand op1(this, node->child1());
 1746 SpeculateBigInt32Operand op2(this, node->child2());
 1747 GPRTemporary result(this, Reuse, op1, op2);
 1748
 1749 if (condition == MacroAssembler::Equal || condition == MacroAssembler::NotEqual) {
 1750 // No need to unbox the operands, since the tag bits are identical
 1751 m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
 1752 } else {
 1753 GPRTemporary temp(this);
 1754 m_jit.move(op1.gpr(), result.gpr());
 1755 m_jit.unboxBigInt32(result.gpr());
 1756 m_jit.move(op2.gpr(), temp.gpr());
 1757 m_jit.unboxBigInt32(temp.gpr());
 1758 m_jit.compare64(condition, result.gpr(), temp.gpr(), result.gpr());
 1759 }
 1760
 1761 // If we add a DataFormatBool, we should use it here.
 1762 m_jit.or32(TrustedImm32(JSValue::ValueFalse), result.gpr());
 1763 jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
 1764}
 1765
 1766void SpeculativeJIT::compilePeepHoleBigInt32Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
 1767{
 1768 // Other conditions would require unboxing the BigInt32 to get correct results on negative numbers.
 1769 ASSERT(condition == MacroAssembler::Equal || condition == MacroAssembler::NotEqual);
 1770
 1771 BasicBlock* taken = branchNode->branchData()->taken.block;
 1772 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
 1773
 1774 // The branch instruction will branch to the taken block.
 1775 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
 1776 if (taken == nextBlock()) {
 1777 condition = JITCompiler::invert(condition);
 1778 BasicBlock* tmp = taken;
 1779 taken = notTaken;
 1780 notTaken = tmp;
 1781 }
 1782
 1783 SpeculateBigInt32Operand op1(this, node->child1());
 1784 SpeculateBigInt32Operand op2(this, node->child2());
 1785
 1786 branch64(condition, op1.gpr(), op2.gpr(), taken);
 1787 jump(notTaken);
 1788}
 1789#endif // USE(BIGINT32)
 1790
15591791void SpeculativeJIT::compileCompareEqPtr(Node* node)
15601792{
15611793 JSValueOperand value(this, node->child1());

@@void SpeculativeJIT::compile(Node* node)
40874319 break;
40884320 }
40894321
 4322 case IsBigInt: {
 4323#if USE(BIGINT32)
 4324 JSValueOperand value(this, node->child1());
 4325 GPRTemporary result(this);
 4326 GPRReg resultGPR = result.gpr();
 4327
 4328 JITCompiler::Jump isCell = m_jit.branchIfCell(value.gpr());
 4329
 4330 m_jit.move(TrustedImm64(JSValue::BigInt32Mask), resultGPR);
 4331 m_jit.and64(value.gpr(), result.gpr());
 4332 m_jit.compare64(JITCompiler::Equal, resultGPR, TrustedImm32(JSValue::BigInt32Tag), resultGPR);
 4333 JITCompiler::Jump continuation = m_jit.jump();
 4334
 4335 isCell.link(&m_jit);
 4336 JSValueRegs valueRegs = value.jsValueRegs();
 4337 m_jit.compare8(JITCompiler::Equal, JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()), TrustedImm32(HeapBigIntType), resultGPR);
 4338
 4339 continuation.link(&m_jit);
 4340 unblessedBooleanResult(resultGPR, node);
 4341#else
 4342 RELEASE_ASSERT_NOT_REACHED();
 4343#endif
 4344 break;
 4345 }
 4346
40904347 case NumberIsInteger: {
40914348 JSValueOperand value(this, node->child1());
40924349 GPRTemporary result(this, Reuse, value);

Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

@@private:
125125 case ValueBitOr:
126126 case ValueBitAnd:
127127 case ValueBitXor: {
128  if (m_node->binaryUseKind() == BigIntUse)
 128 // FIXME: we should maybe support the case where one operand is always HeapBigInt and the other is always BigInt32?
 129 if (m_node->binaryUseKind() == AnyBigIntUse || m_node->binaryUseKind() == BigInt32Use || m_node->binaryUseKind() == HeapBigIntUse)
129130 handleCommutativity();
130131 break;
131132 }

@@private:
375376 break;
376377 }
377378
378  if (m_node->binaryUseKind() == BigIntUse)
 379 if (m_node->binaryUseKind() == BigInt32Use || m_node->binaryUseKind() == HeapBigIntUse || m_node->binaryUseKind() == AnyBigIntUse)
379380 handleCommutativity();
380381
381382 break;

Source/JavaScriptCore/dfg/DFGUseKind.cpp

11/*
2  * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@void printInternal(PrintStream& out, UseKind useKind)
145145 case SymbolUse:
146146 out.print("Symbol");
147147 return;
148  case BigIntUse:
149  out.print("BigInt");
 148 case AnyBigIntUse:
 149 out.print("AnyBigInt");
 150 return;
 151 case HeapBigIntUse:
 152 out.print("HeapBigInt");
 153 return;
 154 case BigInt32Use:
 155 out.print("BigInt32");
150156 return;
151157 case StringObjectUse:
152158 out.print("StringObject");

Source/JavaScriptCore/dfg/DFGUseKind.h

11/*
2  * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
 2 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@enum UseKind {
6666 KnownStringUse,
6767 KnownPrimitiveUse, // This bizarre type arises for op_strcat, which has a bytecode guarantee that it will only see primitives (i.e. not objects).
6868 SymbolUse,
69  BigIntUse,
 69 AnyBigIntUse,
 70 HeapBigIntUse,
 71 BigInt32Use,
7072 DateObjectUse,
7173 MapObjectUse,
7274 SetObjectUse,

@@inline SpeculatedType typeFilterFor(UseKind useKind)
152154 return SpecHeapTop & ~SpecObject;
153155 case SymbolUse:
154156 return SpecSymbol;
155  case BigIntUse:
 157 case AnyBigIntUse:
156158 return SpecBigInt;
 159 case HeapBigIntUse:
 160 return SpecHeapBigInt;
 161 case BigInt32Use:
 162 return SpecBigInt32;
157163 case PromiseObjectUse:
158164 return SpecPromiseObject;
159165 case DateObjectUse:

@@inline bool mayHaveTypeCheck(UseKind kind)
212218 return !shouldNotHaveTypeCheck(kind);
213219}
214220
215 inline bool isNumerical(UseKind kind)
216 {
217  switch (kind) {
218  case Int32Use:
219  case KnownInt32Use:
220  case NumberUse:
221  case RealNumberUse:
222  case Int52RepUse:
223  case DoubleRepUse:
224  case DoubleRepRealUse:
225  case AnyIntUse:
226  case DoubleRepAnyIntUse:
227  return true;
228  default:
229  return false;
230  }
231 }
232 
233221inline bool isDouble(UseKind kind)
234222{
235223 switch (kind) {

@@inline bool isCell(UseKind kind)
261249 case StringUse:
262250 case KnownStringUse:
263251 case SymbolUse:
264  case BigIntUse:
 252 case HeapBigIntUse:
265253 case StringObjectUse:
266254 case StringOrStringObjectUse:
267255 case DateObjectUse:

Source/JavaScriptCore/ftl/FTLCapabilities.cpp

@@inline CapabilityLevel canCompile(Node* node)
261261 case IsUndefinedOrNull:
262262 case IsBoolean:
263263 case IsNumber:
 264 case IsBigInt:
264265 case NumberIsInteger:
265266 case IsObject:
266267 case IsObjectOrNull:

@@CapabilityLevel canCompile(Graph& graph)
484485 case StringObjectUse:
485486 case StringOrStringObjectUse:
486487 case SymbolUse:
487  case BigIntUse:
 488 case AnyBigIntUse:
 489 case BigInt32Use:
 490 case HeapBigIntUse:
488491 case DateObjectUse:
489492 case MapObjectUse:
490493 case SetObjectUse:

Source/JavaScriptCore/ftl/FTLCommonValues.cpp

@@void CommonValues::initializeConstants(B3::Procedure& proc, B3::BasicBlock* bloc
5858 intPtrThree = block->appendNew<ConstPtrValue>(proc, Origin(), 3);
5959 intPtrEight = block->appendNew<ConstPtrValue>(proc, Origin(), 8);
6060 doubleZero = block->appendNew<ConstDoubleValue>(proc, Origin(), 0.);
 61#if USE(BIGINT32)
 62 bigInt32Zero = block->appendNew<Const64Value>(proc, Origin(), JSValue::BigInt32Tag);
 63#endif
6164}
6265
6366} } // namespace JSC::FTL

Source/JavaScriptCore/ftl/FTLCommonValues.h

@@public:
5656 LValue intPtrThree { nullptr };
5757 LValue intPtrEight { nullptr };
5858 LValue doubleZero { nullptr };
59 
 59#if USE(BIGINT32)
 60 LValue bigInt32Zero { nullptr };
 61#endif
 62
6063 const unsigned rangeKind { 0 };
6164 const unsigned profKind { 0 };
6265 const LValue branchWeights { nullptr };

Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

@@private:
13581358 case IsNumber:
13591359 compileIsNumber();
13601360 break;
 1361 case IsBigInt:
 1362 compileIsBigInt();
 1363 break;
13611364 case NumberIsInteger:
13621365 compileNumberIsInteger();
13631366 break;

@@private:
21412144 {
21422145 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
21432146
2144  if (m_node->isBinaryUseKind(BigIntUse)) {
2145  LValue left = lowBigInt(m_node->child1());
2146  LValue right = lowBigInt(m_node->child2());
 2147#if USE(BIGINT32)
 2148 if (m_node->isBinaryUseKind(BigInt32Use)) {
 2149 LValue left = lowBigInt32(m_node->child1());
 2150 LValue right = lowBigInt32(m_node->child2());
 2151
 2152 LValue unboxedLeft = unboxBigInt32(left);
 2153 LValue unboxedRight = unboxBigInt32(right);
 2154
 2155 CheckValue* result = m_out.speculateAdd(unboxedLeft, unboxedRight);
 2156 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
 2157
 2158 LValue boxedResult = boxBigInt32(result);
 2159 setJSValue(boxedResult);
 2160 return;
 2161 }
 2162#endif
 2163
 2164 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 2165 LValue left = lowHeapBigInt(m_node->child1());
 2166 LValue right = lowHeapBigInt(m_node->child2());
21472167
2148  LValue result = vmCall(pointerType(), operationAddBigInt, weakPointer(globalObject), left, right);
 2168 LValue result = vmCall(pointerType(), operationAddHeapBigInt, weakPointer(globalObject), left, right);
21492169 setJSValue(result);
21502170 return;
21512171 }

@@private:
21622182 {
21632183 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
21642184
2165  if (m_node->isBinaryUseKind(BigIntUse)) {
2166  LValue left = lowBigInt(m_node->child1());
2167  LValue right = lowBigInt(m_node->child2());
 2185#if USE(BIGINT32)
 2186 if (m_node->isBinaryUseKind(BigInt32Use)) {
 2187 LValue left = lowBigInt32(m_node->child1());
 2188 LValue right = lowBigInt32(m_node->child2());
 2189
 2190 LValue unboxedLeft = unboxBigInt32(left);
 2191 LValue unboxedRight = unboxBigInt32(right);
 2192
 2193 CheckValue* result = m_out.speculateSub(unboxedLeft, unboxedRight);
 2194 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
 2195
 2196 LValue boxedResult = boxBigInt32(result);
 2197 setJSValue(boxedResult);
 2198 return;
 2199 }
 2200#endif
 2201
 2202 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 2203 LValue left = lowHeapBigInt(m_node->child1());
 2204 LValue right = lowHeapBigInt(m_node->child2());
21682205
2169  LValue result = vmCall(pointerType(), operationSubBigInt, weakPointer(globalObject), left, right);
 2206 LValue result = vmCall(pointerType(), operationSubHeapBigInt, weakPointer(globalObject), left, right);
21702207 setJSValue(result);
21712208 return;
21722209 }

@@private:
21832220 {
21842221 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
21852222
2186  if (m_node->isBinaryUseKind(BigIntUse)) {
2187  LValue left = lowBigInt(m_node->child1());
2188  LValue right = lowBigInt(m_node->child2());
 2223#if USE(BIGINT32)
 2224 if (m_node->isBinaryUseKind(BigInt32Use)) {
 2225 LValue left = lowBigInt32(m_node->child1());
 2226 LValue right = lowBigInt32(m_node->child2());
 2227
 2228 LValue unboxedLeft = unboxBigInt32(left);
 2229 LValue unboxedRight = unboxBigInt32(right);
 2230
 2231 CheckValue* result = m_out.speculateMul(unboxedLeft, unboxedRight);
 2232 blessSpeculation(result, Overflow, noValue(), nullptr, m_origin);
 2233
 2234 LValue boxedResult = boxBigInt32(result);
 2235 setJSValue(boxedResult);
 2236 return;
 2237 }
 2238#endif
 2239
 2240 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 2241 LValue left = lowHeapBigInt(m_node->child1());
 2242 LValue right = lowHeapBigInt(m_node->child2());
21892243
2190  LValue result = vmCall(Int64, operationMulBigInt, weakPointer(globalObject), left, right);
 2244 LValue result = vmCall(Int64, operationMulHeapBigInt, weakPointer(globalObject), left, right);
21912245 setJSValue(result);
21922246 return;
21932247 }

@@private:
22912345 void compileBinaryMathIC(BinaryArithProfile* arithProfile, Func1 repatchingFunction, Func2 nonRepatchingFunction)
22922346 {
22932347 Node* node = m_node;
2294 
 2348
 2349#if USE(BIGINT32)
 2350 if (node->isBinaryUseKind(AnyBigIntUse)) {
 2351 // FIXME: This is not supported by the IC yet.
 2352 LValue left = lowJSValue(node->child1(), ManualOperandSpeculation);
 2353 LValue right = lowJSValue(node->child2(), ManualOperandSpeculation);
 2354 speculate(node, node->child1());
 2355 speculate(node, node->child2());
 2356
 2357 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
 2358 setJSValue(vmCall(pointerType(), nonRepatchingFunction, weakPointer(globalObject), left, right));
 2359 return;
 2360 }
 2361#endif
 2362
22952363 LValue left = lowJSValue(node->child1());
22962364 LValue right = lowJSValue(node->child2());
22972365

@@private:
25602628 void compileValueDiv()
25612629 {
25622630 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2563  if (m_node->isBinaryUseKind(BigIntUse)) {
2564  LValue left = lowBigInt(m_node->child1());
2565  LValue right = lowBigInt(m_node->child2());
 2631 // FIXME: add a fast path for BigInt32 here
 2632 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 2633 LValue left = lowHeapBigInt(m_node->child1());
 2634 LValue right = lowHeapBigInt(m_node->child2());
25662635
2567  LValue result = vmCall(pointerType(), operationDivBigInt, weakPointer(globalObject), left, right);
 2636 LValue result = vmCall(pointerType(), operationDivHeapBigInt, weakPointer(globalObject), left, right);
25682637 setJSValue(result);
25692638 return;
25702639 }

@@private:
26392708 void compileValueMod()
26402709 {
26412710 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2642  if (m_node->binaryUseKind() == BigIntUse) {
2643  LValue left = lowBigInt(m_node->child1());
2644  LValue right = lowBigInt(m_node->child2());
 2711 // FIXME: add a BigInt32 fast path here
 2712 if (m_node->binaryUseKind() == HeapBigIntUse) {
 2713 LValue left = lowHeapBigInt(m_node->child1());
 2714 LValue right = lowHeapBigInt(m_node->child2());
26452715
2646  LValue result = vmCall(pointerType(), operationModBigInt, weakPointer(globalObject), left, right);
 2716 LValue result = vmCall(pointerType(), operationModHeapBigInt, weakPointer(globalObject), left, right);
26472717 setJSValue(result);
26482718 return;
26492719 }
26502720
2651  DFG_ASSERT(m_graph, m_node, m_node->binaryUseKind() == UntypedUse, m_node->binaryUseKind());
2652  LValue left = lowJSValue(m_node->child1());
2653  LValue right = lowJSValue(m_node->child2());
 2721 DFG_ASSERT(m_graph, m_node, m_node->binaryUseKind() == UntypedUse || m_node->binaryUseKind() == AnyBigIntUse, m_node->binaryUseKind());
 2722 LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
 2723 LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
 2724 speculate(m_node, m_node->child1());
 2725 speculate(m_node, m_node->child2());
26542726 LValue result = vmCall(Int64, operationValueMod, weakPointer(globalObject), left, right);
26552727 setJSValue(result);
26562728 }

@@private:
28152887 void compileValuePow()
28162888 {
28172889 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
2818  if (m_node->isBinaryUseKind(BigIntUse)) {
2819  LValue base = lowBigInt(m_node->child1());
2820  LValue exponent = lowBigInt(m_node->child2());
 2890 // FIXME: maybe add a fast path for BigInt32 here
 2891 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 2892 LValue base = lowHeapBigInt(m_node->child1());
 2893 LValue exponent = lowHeapBigInt(m_node->child2());
28212894
2822  LValue result = vmCall(pointerType(), operationPowBigInt, weakPointer(globalObject), base, exponent);
 2895 LValue result = vmCall(pointerType(), operationPowHeapBigInt, weakPointer(globalObject), base, exponent);
28232896 setJSValue(result);
28242897 return;
28252898 }
28262899
2827  LValue base = lowJSValue(m_node->child1());
2828  LValue exponent = lowJSValue(m_node->child2());
 2900 ASSERT(m_node->isBinaryUseKind(UntypedUse) || m_node->isBinaryUseKind(AnyBigIntUse));
 2901 LValue base = lowJSValue(m_node->child1(), ManualOperandSpeculation);
 2902 LValue exponent = lowJSValue(m_node->child2(), ManualOperandSpeculation);
 2903 speculate(m_node, m_node->child1());
 2904 speculate(m_node, m_node->child2());
28292905 LValue result = vmCall(Int64, operationValuePow, weakPointer(globalObject), base, exponent);
28302906 setJSValue(result);
28312907 }

@@private:
32063282 void compileValueBitNot()
32073283 {
32083284 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3209  if (m_node->child1().useKind() == BigIntUse) {
3210  LValue operand = lowBigInt(m_node->child1());
3211  LValue result = vmCall(pointerType(), operationBitNotBigInt, weakPointer(globalObject), operand);
 3285
 3286#if USE(BIGINT32)
 3287 if (m_node->child1().useKind() == BigInt32Use) {
 3288 LValue operand = lowBigInt32(m_node->child1());
 3289 // The following trick relies on details of the representation of BigInt32, and will have to be updated if we move bits around.
 3290 static_assert(JSValue::BigInt32Tag == 0x12);
 3291 static_assert(JSValue::BigInt32Mask == 0xfffe000000000012);
 3292 uint64_t maskForBigInt32Bits = 0x0000ffffffff0000;
 3293 LValue result = m_out.bitXor(operand, m_out.constInt64(maskForBigInt32Bits));
 3294 setJSValue(result);
 3295 return;
 3296 }
 3297#endif
 3298
 3299 if (m_node->child1().useKind() == HeapBigIntUse) {
 3300 LValue operand = lowHeapBigInt(m_node->child1());
 3301 LValue result = vmCall(pointerType(), operationBitNotHeapBigInt, weakPointer(globalObject), operand);
32123302 setJSValue(result);
32133303 return;
32143304 }

@@private:
32263316 void compileValueBitAnd()
32273317 {
32283318 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3229  if (m_node->isBinaryUseKind(BigIntUse)) {
3230  LValue left = lowBigInt(m_node->child1());
3231  LValue right = lowBigInt(m_node->child2());
 3319
 3320#if USE(BIGINT32)
 3321 if (m_node->isBinaryUseKind(BigInt32Use)) {
 3322 LValue left = lowBigInt32(m_node->child1());
 3323 LValue right = lowBigInt32(m_node->child2());
 3324 // No need to unbox, since the tagging is not affected by bitAnd
 3325 LValue result = m_out.bitAnd(left, right);
 3326 setJSValue(result);
 3327 return;
 3328 }
 3329#endif
 3330
 3331 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 3332 LValue left = lowHeapBigInt(m_node->child1());
 3333 LValue right = lowHeapBigInt(m_node->child2());
32323334
3233  LValue result = vmCall(pointerType(), operationBitAndBigInt, weakPointer(globalObject), left, right);
 3335 LValue result = vmCall(pointerType(), operationBitAndHeapBigInt, weakPointer(globalObject), left, right);
32343336 setJSValue(result);
32353337 return;
32363338 }

@@private:
32463348 void compileValueBitOr()
32473349 {
32483350 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3249  if (m_node->isBinaryUseKind(BigIntUse)) {
3250  LValue left = lowBigInt(m_node->child1());
3251  LValue right = lowBigInt(m_node->child2());
32523351
3253  LValue result = vmCall(pointerType(), operationBitOrBigInt, weakPointer(globalObject), left, right);
 3352#if USE(BIGINT32)
 3353 if (m_node->isBinaryUseKind(BigInt32Use)) {
 3354 LValue left = lowBigInt32(m_node->child1());
 3355 LValue right = lowBigInt32(m_node->child2());
 3356 // No need to unbox, since the tagging is not affected by bitAnd
 3357 LValue result = m_out.bitOr(left, right);
 3358 setJSValue(result);
 3359 return;
 3360 }
 3361#endif
 3362
 3363 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 3364 LValue left = lowHeapBigInt(m_node->child1());
 3365 LValue right = lowHeapBigInt(m_node->child2());
 3366
 3367 LValue result = vmCall(pointerType(), operationBitOrHeapBigInt, weakPointer(globalObject), left, right);
32543368 setJSValue(result);
32553369 return;
32563370 }

@@private:
32663380 void compileValueBitXor()
32673381 {
32683382 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3269  if (m_node->isBinaryUseKind(BigIntUse)) {
3270  LValue left = lowBigInt(m_node->child1());
3271  LValue right = lowBigInt(m_node->child2());
32723383
3273  LValue result = vmCall(pointerType(), operationBitXorBigInt, weakPointer(globalObject), left, right);
 3384#if USE(BIGINT32)
 3385 if (m_node->isBinaryUseKind(BigInt32Use)) {
 3386 LValue left = lowBigInt32(m_node->child1());
 3387 LValue right = lowBigInt32(m_node->child2());
 3388 LValue resultMissingTag = m_out.bitXor(left, right);
 3389 LValue result = m_out.bitOr(resultMissingTag, m_out.constInt64(JSValue::BigInt32Tag));
 3390 setJSValue(result);
 3391 return;
 3392 }
 3393#endif
 3394
 3395 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 3396 LValue left = lowHeapBigInt(m_node->child1());
 3397 LValue right = lowHeapBigInt(m_node->child2());
 3398
 3399 LValue result = vmCall(pointerType(), operationBitXorHeapBigInt, weakPointer(globalObject), left, right);
32743400 setJSValue(result);
32753401 return;
32763402 }

@@private:
32863412 void compileValueBitRShift()
32873413 {
32883414 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3289  if (m_node->isBinaryUseKind(BigIntUse)) {
3290  LValue left = lowBigInt(m_node->child1());
3291  LValue right = lowBigInt(m_node->child2());
32923415
3293  LValue result = vmCall(pointerType(), operationBitRShiftBigInt, weakPointer(globalObject), left, right);
 3416#if USE(BIGINT32)
 3417 if (m_node->isBinaryUseKind(AnyBigIntUse) || m_node->isBinaryUseKind(BigInt32Use)) {
 3418 // FIXME: do something smarter here
 3419 // Things are a bit tricky because a right-shift by a negative number is a left-shift for BigInts.
 3420 // So even a right shift can overflow.
 3421
 3422 LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
 3423 LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
 3424 speculate(m_node, m_node->child1());
 3425 speculate(m_node, m_node->child2());
 3426
 3427 LValue result = vmCall(pointerType(), operationValueBitRShift, weakPointer(globalObject), left, right);
 3428 setJSValue(result);
 3429 return;
 3430 }
 3431#endif // USE(BIGINT32)
 3432
 3433 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 3434 LValue left = lowHeapBigInt(m_node->child1());
 3435 LValue right = lowHeapBigInt(m_node->child2());
 3436
 3437 LValue result = vmCall(pointerType(), operationBitRShiftHeapBigInt, weakPointer(globalObject), left, right);
32943438 setJSValue(result);
32953439 return;
32963440 }

@@private:
33023446 {
33033447 setInt32(m_out.aShr(
33043448 lowInt32(m_node->child1()),
3305  m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
 3449 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); // FIXME: I don't think that the BitAnd is useful, it is included in the semantics of shift in B3
33063450 }
33073451
33083452 void compileArithBitLShift()
33093453 {
33103454 setInt32(m_out.shl(
33113455 lowInt32(m_node->child1()),
3312  m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
 3456 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); // FIXME: I don't think that the BitAnd is useful, it is included in the semantics of shift in B3
33133457 }
33143458
33153459 void compileValueBitLShift()
33163460 {
33173461 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
3318  if (m_node->isBinaryUseKind(BigIntUse)) {
3319  LValue left = lowBigInt(m_node->child1());
3320  LValue right = lowBigInt(m_node->child2());
 3462 // FIXME: consider adding a fast path for BigInt32 here.
 3463 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 3464 LValue left = lowHeapBigInt(m_node->child1());
 3465 LValue right = lowHeapBigInt(m_node->child2());
33213466
3322  LValue result = vmCall(pointerType(), operationBitLShiftBigInt, weakPointer(globalObject), left, right);
 3467 LValue result = vmCall(pointerType(), operationBitLShiftHeapBigInt, weakPointer(globalObject), left, right);
33233468 setJSValue(result);
33243469 return;
33253470 }

@@private:
33363481 }
33373482 setInt32(m_out.lShr(
33383483 lowInt32(m_node->child1()),
3339  m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
 3484 m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31)))); // FIXME: I don't think that the BitAnd is useful, it is included in the semantics of shift in B3
33403485 }
33413486
33423487 void compileUInt32ToNumber()

@@private:
74097554
74107555 if (abstractValue(m_node->child1()).m_type & (SpecBytecodeNumber | SpecBigInt)) {
74117556 LBasicBlock notNumber = m_out.newBlock();
 7557#if USE(BIGINT32)
 7558 LBasicBlock notBigInt32 = m_out.newBlock();
 7559#endif
74127560 LBasicBlock isCellPath = m_out.newBlock();
74137561 LBasicBlock slowPath = m_out.newBlock();
74147562 LBasicBlock continuation = m_out.newBlock();

@@private:
74187566
74197567 // notNumber case.
74207568 LBasicBlock lastNext = m_out.appendTo(notNumber, continuation);
 7569#if USE(BIGINT32)
 7570 m_out.branch(isBigInt32(value, provenType(m_node->child1())), unsure(continuation), unsure(notBigInt32));
 7571 m_out.appendTo(notBigInt32);
 7572#endif
74217573 m_out.branch(isCell(value, provenType(m_node->child1())), unsure(isCellPath), unsure(slowPath));
74227574
74237575 m_out.appendTo(isCellPath);
7424  m_out.branch(isBigInt(value, provenType(m_node->child1())), unsure(continuation), unsure(slowPath));
 7576 m_out.branch(isHeapBigInt(value, provenType(m_node->child1())), unsure(continuation), unsure(slowPath));
74257577
74267578 m_out.appendTo(slowPath);
74277579 // We have several attempts to remove ToNumeric. But ToNumeric still exists.

@@private:
84918643 || m_node->isBinaryUseKind(BooleanUse)
84928644 || m_node->isBinaryUseKind(SymbolUse)
84938645 || m_node->isBinaryUseKind(StringIdentUse)
8494  || m_node->isBinaryUseKind(StringUse)) {
 8646 || m_node->isBinaryUseKind(StringUse)
 8647 || m_node->isBinaryUseKind(BigInt32Use)
 8648 || m_node->isBinaryUseKind(HeapBigIntUse)
 8649 || m_node->isBinaryUseKind(AnyBigIntUse)) {
84958650 compileCompareStrictEq();
84968651 return;
84978652 }

@@private:
85348689 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
85358690 return;
85368691 }
8537 
 8692
 8693#if USE(BIGINT32)
 8694 if (m_node->isBinaryUseKind(BigInt32Use)) {
 8695 LValue left = lowBigInt32(m_node->child1());
 8696 LValue right = lowBigInt32(m_node->child2());
 8697
 8698 // No need to unbox since the tag bits are the same on both sides
 8699 LValue result = m_out.equal(left, right);
 8700 setBoolean(result);
 8701 return;
 8702 }
 8703
 8704 if (m_node->isBinaryUseKind(AnyBigIntUse)) {
 8705 LValue left = lowJSValue(m_node->child1(), ManualOperandSpeculation);
 8706 LValue right = lowJSValue(m_node->child2(), ManualOperandSpeculation);
 8707
 8708 // Note that we cannot start with if (left == right), because we must insert the right checks (see ManualOperandSpeculation above)
 8709 // The code that we generate looks like the following pseudo-code:
 8710 /*
 8711 if (isBigInt32(left)) {
 8712 if (isBigInt32(right))
 8713 return left == right;
 8714 CHECK(isHeapBigInt(right));
 8715 return call(JSBigInt::equalsToInt32(right, unboxed(left));
 8716 }
 8717 CHECK(isHeapBigInt(left))
 8718 if (left == right)
 8719 return true;
 8720 if (isBigInt32(right))
 8721 return call(JSBigInt::equalsToInt32(left, unboxed(right));
 8722 CHECK(isHeapBigInt(right));
 8723 return call(JSBigInt::equals(left, right));
 8724 */
 8725 LBasicBlock leftIsBigInt32 = m_out.newBlock();
 8726 LBasicBlock bothAreBigInt32 = m_out.newBlock();
 8727 LBasicBlock onlyLeftIsBigInt32 = m_out.newBlock();
 8728 LBasicBlock leftIsNotBigInt32 = m_out.newBlock();
 8729 LBasicBlock leftEqualsRight = m_out.newBlock();
 8730 LBasicBlock leftIsHeapBigInt = m_out.newBlock();
 8731 LBasicBlock rightIsBigInt32 = m_out.newBlock();
 8732 LBasicBlock rightIsNotBigInt32 = m_out.newBlock();
 8733 LBasicBlock continuation = m_out.newBlock();
 8734
 8735 m_out.branch(isBigInt32(left, provenType(m_node->child1())), unsure(leftIsBigInt32), unsure(leftIsNotBigInt32));
 8736
 8737 // FIXME: set the order of the blocks to maximize fallthrough
 8738 m_out.appendTo(leftIsBigInt32);
 8739 m_out.branch(isBigInt32(right, provenType(m_node->child2())), unsure(bothAreBigInt32), unsure(onlyLeftIsBigInt32));
 8740
 8741 m_out.appendTo(bothAreBigInt32);
 8742 ValueFromBlock resultBothAreBigInt32 = m_out.anchor(m_out.equal(left, right));
 8743 m_out.jump(continuation);
 8744
 8745 m_out.appendTo(onlyLeftIsBigInt32);
 8746 speculateHeapBigIntUnknownWhetherCell(m_node->child2());
 8747 LValue unboxedLeft = unboxBigInt32(left);
 8748 ValueFromBlock resultLeftIsBigInt32 = m_out.anchor(m_out.notNull(vmCall(pointerType(), operationCompareEqHeapBigIntToInt32, weakPointer(globalObject), right, unboxedLeft)));
 8749 m_out.jump(continuation);
 8750
 8751 m_out.appendTo(leftIsNotBigInt32);
 8752 speculateHeapBigIntUnknownWhetherCell(m_node->child1());
 8753 m_out.branch(m_out.equal(left, right), unsure(leftEqualsRight), unsure(leftIsHeapBigInt));
 8754
 8755 m_out.appendTo(leftEqualsRight);
 8756 ValueFromBlock resultLeftEqualsRight = m_out.anchor(m_out.booleanTrue);
 8757 m_out.jump(continuation);
 8758
 8759 m_out.appendTo(leftIsHeapBigInt);
 8760 m_out.branch(isBigInt32(right, provenType(m_node->child2())), unsure(rightIsBigInt32), unsure(rightIsNotBigInt32));
 8761
 8762 m_out.appendTo(rightIsBigInt32);
 8763 LValue unboxedRight = unboxBigInt32(right);
 8764 ValueFromBlock resultRightIsBigInt32 = m_out.anchor(m_out.notNull(vmCall(pointerType(), operationCompareEqHeapBigIntToInt32, weakPointer(globalObject), left, unboxedRight)));
 8765 m_out.jump(continuation);
 8766
 8767 m_out.appendTo(rightIsNotBigInt32);
 8768 speculateHeapBigIntUnknownWhetherCell(m_node->child2());
 8769 // FIXME: [ESNext][BigInt] Create specialized version of strict equals for big ints
 8770 // https://bugs.webkit.org/show_bug.cgi?id=182895
 8771 ValueFromBlock resultBothHeapBigInt = m_out.anchor(m_out.notNull(vmCall(pointerType(), operationCompareStrictEq, weakPointer(globalObject), left, right)));
 8772 m_out.jump(continuation);
 8773
 8774 m_out.appendTo(continuation);
 8775 setBoolean(m_out.phi(Int32, resultBothAreBigInt32, resultLeftIsBigInt32, resultLeftEqualsRight, resultRightIsBigInt32, resultBothHeapBigInt));
 8776 return;
 8777 }
 8778#endif // USE(BIGINT32)
 8779
85388780 if (m_node->isBinaryUseKind(Int52RepUse)) {
85398781 Int52Kind kind;
85408782 LValue left = lowWhicheverInt52(m_node->child1(), kind);

@@private:
86178859 return;
86188860 }
86198861
8620  if (m_node->isBinaryUseKind(BigIntUse)) {
8621  // FIXME: [ESNext][BigInt] Create specialized version of strict equals for BigIntUse
 8862 if (m_node->isBinaryUseKind(HeapBigIntUse)) {
 8863 // FIXME: [ESNext][BigInt] Create specialized version of strict equals for big ints
86228864 // https://bugs.webkit.org/show_bug.cgi?id=182895
8623  LValue left = lowBigInt(m_node->child1());
8624  LValue right = lowBigInt(m_node->child2());
 8865 LValue left = lowHeapBigInt(m_node->child1());
 8866 LValue right = lowHeapBigInt(m_node->child2());
86258867
86268868 LBasicBlock notTriviallyEqualCase = m_out.newBlock();
86278869 LBasicBlock continuation = m_out.newBlock();

@@private:
87078949 return;
87088950 }
87098951
 8952 // FIXME: we can do something much smarter here, see the DFGSpeculativeJIT approach in e.g. SpeculativeJIT::nonSpeculativePeepholeStrictEq
87108953 DFG_ASSERT(m_graph, m_node, m_node->isBinaryUseKind(UntypedUse), m_node->child1().useKind(), m_node->child2().useKind());
87118954 nonSpeculativeCompare(
87128955 [&] (LValue left, LValue right) {

@@private:
1067010913 m_out.appendTo(continuation, lastNext);
1067110914 setBoolean(m_out.phi(Int32, trueResult, falseResult, patchpointResult));
1067210915 }
10673 
 10916
 10917#if USE(BIGINT32)
 10918 void compileIsBigInt()
 10919 {
 10920 LValue value = lowJSValue(m_node->child1());
 10921
 10922 LBasicBlock isCellCase = m_out.newBlock();
 10923 LBasicBlock isNotCellCase = m_out.newBlock();
 10924 LBasicBlock continuation = m_out.newBlock();
 10925
 10926 m_out.branch(isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(isNotCellCase));
 10927
 10928 LBasicBlock lastNext = m_out.appendTo(isNotCellCase, isCellCase);
 10929 ValueFromBlock notCellResult = m_out.anchor(isBigInt32(value, provenType(m_node->child1())));
 10930 m_out.jump(continuation);
 10931
 10932 m_out.appendTo(isCellCase, continuation);
 10933 ValueFromBlock cellResult = m_out.anchor(isCellWithType(value, m_node->queriedType(), m_node->speculatedTypeForQuery(), provenType(m_node->child1())));
 10934 m_out.jump(continuation);
 10935
 10936 m_out.appendTo(continuation, lastNext);
 10937 setBoolean(m_out.phi(Int32, notCellResult, cellResult));
 10938 }
 10939#else // if !USE(BIGINT32)
 10940 NO_RETURN_DUE_TO_CRASH ALWAYS_INLINE void compileIsBigInt()
 10941 {
 10942 // If we are not dealing with BigInt32, we should just emit IsCellWithType(HeapBigInt) instead.
 10943 RELEASE_ASSERT_NOT_REACHED();
 10944 }
 10945#endif
1067410946 void compileIsCellWithType()
1067510947 {
1067610948 if (m_node->child1().useKind() == UntypedUse) {

@@private:
1440014672 void emitBinarySnippet(J_JITOperation_GJJ slowPathFunction)
1440114673 {
1440214674 Node* node = m_node;
14403 
14404  LValue left = lowJSValue(node->child1());
14405  LValue right = lowJSValue(node->child2());
 14675
 14676 speculate(node->child1());
 14677 speculate(node->child2());
 14678 LValue left = lowJSValue(node->child1(), ManualOperandSpeculation);
 14679 LValue right = lowJSValue(node->child2(), ManualOperandSpeculation);
1440614680
1440714681 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
1440814682 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());

@@private:
1446814742 {
1446914743 Node* node = m_node;
1447014744
14471  LValue left = lowJSValue(node->child1());
14472  LValue right = lowJSValue(node->child2());
 14745 ASSERT(node->isBinaryUseKind(UntypedUse) || node->isBinaryUseKind(AnyBigIntUse));
 14746 LValue left = lowJSValue(node->child1(), ManualOperandSpeculation);
 14747 LValue right = lowJSValue(node->child2(), ManualOperandSpeculation);
 14748 speculate(node, node->child1());
 14749 speculate(node, node->child2());
1447314750
1447414751 SnippetOperand leftOperand(m_state.forNode(node->child1()).resultType());
1447514752 SnippetOperand rightOperand(m_state.forNode(node->child2()).resultType());

@@private:
1508115358
1508215359 // Implements the following control flow structure:
1508315360 // if (value is cell) {
15084  // if (value is string or value is BigInt)
 15361 // if (value is string or value is HeapBigInt)
1508515362 // result = !!value->length
1508615363 // else {
1508715364 // do evil things for masquerades-as-undefined

@@private:
1509115368 // result = !!unboxInt32(value)
1509215369 // } else if (value is number) {
1509315370 // result = !!unboxDouble(value)
 15371 // } else if (value is BigInt32) {
 15372 // result = (value != BigInt32Tag)
1509415373 // } else {
1509515374 // result = value == jsTrue
1509615375 // }

@@private:
1509815377 LBasicBlock cellCase = m_out.newBlock();
1509915378 LBasicBlock notStringCase = m_out.newBlock();
1510015379 LBasicBlock stringCase = m_out.newBlock();
15101  LBasicBlock bigIntCase = m_out.newBlock();
15102  LBasicBlock notStringOrBigIntCase = m_out.newBlock();
 15380 LBasicBlock heapBigIntCase = m_out.newBlock();
 15381 LBasicBlock notStringNorHeapBigIntCase = m_out.newBlock();
1510315382 LBasicBlock notCellCase = m_out.newBlock();
1510415383 LBasicBlock int32Case = m_out.newBlock();
1510515384 LBasicBlock notInt32Case = m_out.newBlock();
1510615385 LBasicBlock doubleCase = m_out.newBlock();
1510715386 LBasicBlock notDoubleCase = m_out.newBlock();
 15387#if USE(BIGINT32)
 15388 LBasicBlock bigInt32Case = m_out.newBlock();
 15389 LBasicBlock notBigInt32Case = m_out.newBlock();
 15390#endif
1510815391 LBasicBlock continuation = m_out.newBlock();
1510915392
1511015393 Vector<ValueFromBlock> results;

@@private:
1511815401
1511915402 m_out.appendTo(notStringCase, stringCase);
1512015403 m_out.branch(
15121  isBigInt(value, provenType(edge) & (SpecCell - SpecString)),
15122  unsure(bigIntCase), unsure(notStringOrBigIntCase));
 15404 isHeapBigInt(value, provenType(edge) & (SpecCell - SpecString)),
 15405 unsure(heapBigIntCase), unsure(notStringNorHeapBigIntCase));
1512315406
15124  m_out.appendTo(stringCase, bigIntCase);
 15407 m_out.appendTo(stringCase, heapBigIntCase);
1512515408 results.append(m_out.anchor(m_out.notEqual(value, weakPointer(jsEmptyString(m_graph.m_vm)))));
1512615409 m_out.jump(continuation);
1512715410
15128  m_out.appendTo(bigIntCase, notStringOrBigIntCase);
 15411 m_out.appendTo(heapBigIntCase, notStringNorHeapBigIntCase);
1512915412 LValue nonZeroBigInt = m_out.notZero32(
1513015413 m_out.load32NonNegative(value, m_heaps.JSBigInt_length));
1513115414 results.append(m_out.anchor(nonZeroBigInt));
1513215415 m_out.jump(continuation);
1513315416
15134  m_out.appendTo(notStringOrBigIntCase, notCellCase);
 15417 m_out.appendTo(notStringNorHeapBigIntCase, notCellCase);
1513515418 LValue isTruthyObject;
1513615419 if (masqueradesAsUndefinedWatchpointIsStillValid())
1513715420 isTruthyObject = m_out.booleanTrue;

@@private:
1517415457 unboxDouble(value), m_out.constDouble(0));
1517515458 results.append(m_out.anchor(doubleIsTruthy));
1517615459 m_out.jump(continuation);
 15460
 15461#if USE(BIGINT32)
 15462 m_out.appendTo(notDoubleCase, bigInt32Case);
 15463 m_out.branch(
 15464 isBigInt32(value, provenType(edge) & ~SpecCell),
 15465 unsure(bigInt32Case), unsure(notBigInt32Case));
 15466
 15467 m_out.appendTo(bigInt32Case, notBigInt32Case);
 15468 LValue bigInt32NotZero = m_out.notEqual(value, m_out.constInt64(JSValue::BigInt32Tag));
 15469 results.append(m_out.anchor(bigInt32NotZero));
 15470 m_out.jump(continuation);
1517715471
 15472 m_out.appendTo(notBigInt32Case, continuation);
 15473#else
1517815474 m_out.appendTo(notDoubleCase, continuation);
 15475#endif
1517915476 LValue miscIsTruthy = m_out.equal(
1518015477 value, m_out.constInt64(JSValue::encode(jsBoolean(true))));
1518115478 results.append(m_out.anchor(miscIsTruthy));

@@private:
1578016077 // }
1578116078 // } else if (is string) {
1578216079 // return string
15783  // } else if (is bigint) {
 16080 // } else if (is heapbigint) {
1578416081 // return bigint
1578516082 // } else {
1578616083 // return symbol
1578716084 // }
1578816085 // } else if (is number) {
1578916086 // return number
 16087 // } else if (is bigint32) {
 16088 // return bigint
1579016089 // } else if (is null) {
1579116090 // return object
1579216091 // } else if (is boolean) {

@@private:
1581416113 LBasicBlock notCellCase = m_out.newBlock();
1581516114 LBasicBlock numberCase = m_out.newBlock();
1581616115 LBasicBlock notNumberCase = m_out.newBlock();
 16116#if USE(BIGINT32)
 16117 LBasicBlock notBigInt32Case = m_out.newBlock();
 16118#endif
1581716119 LBasicBlock notNullCase = m_out.newBlock();
1581816120 LBasicBlock booleanCase = m_out.newBlock();
1581916121 LBasicBlock undefinedCase = m_out.newBlock();

@@private:
1586616168
1586716169 m_out.appendTo(notStringCase, bigIntCase);
1586816170 m_out.branch(
15869  isBigInt(value, provenType(child) & (SpecCell - SpecObject - SpecString)),
 16171 isHeapBigInt(value, provenType(child) & (SpecCell - SpecObject - SpecString)),
1587016172 unsure(bigIntCase), unsure(symbolCase));
1587116173
1587216174 m_out.appendTo(bigIntCase, symbolCase);

@@private:
1588216184
1588316185 m_out.appendTo(numberCase, notNumberCase);
1588416186 functor(TypeofType::Number);
15885 
 16187
 16188#if USE(BIGINT32)
 16189 m_out.appendTo(notNumberCase, notBigInt32Case);
 16190 m_out.branch(isBigInt32(value, provenType(child) & ~SpecCell), unsure(bigIntCase), unsure(notBigInt32Case));
 16191
 16192 m_out.appendTo(notBigInt32Case, notNullCase);
 16193#else
1588616194 m_out.appendTo(notNumberCase, notNullCase);
 16195#endif
1588716196 LValue isNull;
1588816197 if (provenType(child) & SpecOther)
1588916198 isNull = m_out.equal(value, m_out.constInt64(JSValue::ValueNull));

@@private:
1658116890 return result;
1658216891 }
1658316892
16584  LValue lowBigInt(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
 16893 LValue lowHeapBigInt(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1658516894 {
16586  ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BigIntUse);
 16895 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == HeapBigIntUse);
1658716896
1658816897 LValue result = lowCell(edge, mode);
16589  speculateBigInt(edge, result);
 16898 speculateHeapBigInt(edge, result);
1659016899 return result;
1659116900 }
16592 
 16901
 16902#if USE(BIGINT32)
 16903 LValue lowBigInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
 16904 {
 16905 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BigInt32Use);
 16906
 16907 LoweredNodeValue value = m_jsValueValues.get(edge.node());
 16908 if (isValid(value)) {
 16909 LValue result = value.value();
 16910 FTL_TYPE_CHECK(jsValueValue(result), edge, SpecBigInt32, isNotBigInt32(result));
 16911 return result;
 16912 }
 16913
 16914 if (mayHaveTypeCheck(edge.useKind()))
 16915 terminate(Uncountable);
 16916 return m_out.bigInt32Zero;
 16917 }
 16918#endif
 16919
1659316920 LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
1659416921 {
1659516922 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);

@@private:
1677517102 {
1677617103 return m_out.add(m_out.zeroExt(value, Int64), m_numberTag);
1677717104 }
16778 
 17105
 17106#if USE(BIGINT32)
 17107 LValue isBigInt32(LValue jsValue, SpeculatedType type = SpecFullTop)
 17108 {
 17109 if (LValue proven = isProvenValue(type, SpecBigInt32))
 17110 return proven;
 17111 return m_out.equal(
 17112 m_out.bitAnd(jsValue, m_out.constInt64(JSValue::BigInt32Mask)),
 17113 m_out.constInt64(JSValue::BigInt32Tag));
 17114 }
 17115 LValue isNotBigInt32(LValue jsValue, SpeculatedType type = SpecFullTop)
 17116 {
 17117 if (LValue proven = isProvenValue(type, ~SpecBigInt32))
 17118 return proven;
 17119 return m_out.notEqual(
 17120 m_out.bitAnd(jsValue, m_out.constInt64(JSValue::BigInt32Mask)),
 17121 m_out.constInt64(JSValue::BigInt32Tag));
 17122 }
 17123 LValue unboxBigInt32(LValue jsValue)
 17124 {
 17125 return m_out.castToInt32(m_out.lShr(jsValue, m_out.constInt64(16)));
 17126 }
 17127 LValue boxBigInt32(LValue int32Value)
 17128 {
 17129 return m_out.bitOr(
 17130 m_out.shl(m_out.zeroExt(int32Value, B3::Int64), m_out.constInt64(16)),
 17131 m_out.constInt64(JSValue::BigInt32Tag));
 17132 }
 17133 LValue isNotAnyBigInt(LValue jsValue, SpeculatedType type = SpecFullTop)
 17134 {
 17135 if (LValue proven = isProvenValue(type, ~SpecBigInt))
 17136 return proven;
 17137
 17138 // if (isBigInt32)
 17139 // return false
 17140 // if (!isCell)
 17141 // return true;
 17142 // return !isHeapBigInt
 17143 LBasicBlock isBigInt32Case = m_out.newBlock();
 17144 LBasicBlock isNotBigInt32Case = m_out.newBlock();
 17145 LBasicBlock isCellCase = m_out.newBlock();
 17146 LBasicBlock isNotCellCase = m_out.newBlock();
 17147 LBasicBlock continuation = m_out.newBlock();
 17148
 17149 m_out.branch(isBigInt32(jsValue, type), unsure(isBigInt32Case), unsure(isNotBigInt32Case));
 17150
 17151 m_out.appendTo(isBigInt32Case);
 17152 ValueFromBlock returnFalse = m_out.anchor(m_out.booleanFalse);
 17153 m_out.jump(continuation);
 17154
 17155 m_out.appendTo(isNotBigInt32Case);
 17156 m_out.branch(isCell(jsValue, type), unsure(isCellCase), unsure(isNotCellCase));
 17157
 17158 m_out.appendTo(isNotCellCase);
 17159 ValueFromBlock returnTrue = m_out.anchor(m_out.booleanTrue);
 17160 m_out.jump(continuation);
 17161
 17162 m_out.appendTo(isCellCase);
 17163 ValueFromBlock returnIsNotHeapBigInt = m_out.anchor(isNotHeapBigInt(jsValue));
 17164 m_out.jump(continuation);
 17165
 17166 m_out.appendTo(continuation);
 17167 return m_out.phi(Int32, returnFalse, returnTrue, returnIsNotHeapBigInt);
 17168 }
 17169#endif // USE(BIGINT32)
 17170
1677917171 LValue isCellOrMisc(LValue jsValue, SpeculatedType type = SpecFullTop)
1678017172 {
1678117173 if (LValue proven = isProvenValue(type, SpecCellCheck | SpecMisc))

@@private:
1708717479 case BooleanUse:
1708817480 speculateBoolean(edge);
1708917481 break;
17090  case BigIntUse:
17091  speculateBigInt(edge);
 17482#if USE(BIGINT32)
 17483 case BigInt32Use:
 17484 speculateBigInt32(edge);
 17485 break;
 17486 case AnyBigIntUse:
 17487 speculateAnyBigInt(edge);
 17488 break;
 17489#endif // USE(BIGINT32)
 17490 case HeapBigIntUse:
 17491 speculateHeapBigInt(edge);
1709217492 break;
1709317493 case NotStringVarUse:
1709417494 speculateNotStringVar(edge);

@@private:
1727417674 m_out.constInt32(vm().symbolStructure->id()));
1727517675 }
1727617676
17277  LValue isNotBigInt(LValue cell, SpeculatedType type = SpecFullTop)
 17677 LValue isNotHeapBigIntUnknownWhetherCell(LValue value, SpeculatedType type = SpecFullTop)
1727817678 {
17279  if (LValue proven = isProvenValue(type & SpecCell, ~SpecBigInt))
 17679 if (LValue proven = isProvenValue(type, ~SpecHeapBigInt))
 17680 return proven;
 17681
 17682 LBasicBlock isCellCase = m_out.newBlock();
 17683 LBasicBlock continuation = m_out.newBlock();
 17684
 17685 ValueFromBlock defaultToFalse = m_out.anchor(m_out.booleanFalse);
 17686 m_out.branch(isCell(value, type), unsure(isCellCase), unsure(continuation));
 17687
 17688 LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
 17689 ValueFromBlock returnForCell = m_out.anchor(isHeapBigInt(value, type));
 17690 m_out.jump(continuation);
 17691
 17692 m_out.appendTo(continuation, lastNext);
 17693 LValue result = m_out.phi(Int32, defaultToFalse, returnForCell);
 17694 return result;
 17695 }
 17696
 17697 LValue isNotHeapBigInt(LValue cell, SpeculatedType type = SpecFullTop)
 17698 {
 17699 if (LValue proven = isProvenValue(type & SpecCell, ~SpecHeapBigInt))
1728017700 return proven;
1728117701 return m_out.notEqual(
1728217702 m_out.load32(cell, m_heaps.JSCell_structureID),
1728317703 m_out.constInt32(vm().bigIntStructure->id()));
1728417704 }
1728517705
17286  LValue isBigInt(LValue cell, SpeculatedType type = SpecFullTop)
 17706 LValue isHeapBigInt(LValue cell, SpeculatedType type = SpecFullTop)
1728717707 {
17288  if (LValue proven = isProvenValue(type & SpecCell, SpecBigInt))
 17708 if (LValue proven = isProvenValue(type & SpecCell, SpecHeapBigInt))
1728917709 return proven;
1729017710 return m_out.equal(
1729117711 m_out.load32(cell, m_heaps.JSCell_structureID),

@@private:
1774318163 speculateSymbol(edge, lowCell(edge));
1774418164 }
1774518165
17746  void speculateBigInt(Edge edge, LValue cell)
 18166 void speculateHeapBigInt(Edge edge, LValue cell)
 18167 {
 18168 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecHeapBigInt, isNotHeapBigInt(cell));
 18169 }
 18170 void speculateHeapBigInt(Edge edge)
1774718171 {
17748  FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecBigInt, isNotBigInt(cell));
 18172 speculateHeapBigInt(edge, lowCell(edge));
1774918173 }
1775018174
17751  void speculateBigInt(Edge edge)
 18175 void speculateHeapBigIntUnknownWhetherCell(Edge edge)
1775218176 {
17753  speculateBigInt(edge, lowCell(edge));
 18177 LValue value = lowJSValue(edge, ManualOperandSpeculation);
 18178 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecHeapBigInt, isNotHeapBigIntUnknownWhetherCell(value));
1775418179 }
1775518180
 18181#if USE(BIGINT32)
 18182 void speculateBigInt32(Edge edge)
 18183 {
 18184 LValue value = lowJSValue(edge, ManualOperandSpeculation);
 18185 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBigInt32, isNotBigInt32(value));
 18186 }
 18187
 18188 void speculateAnyBigInt(Edge edge)
 18189 {
 18190 LValue value = lowJSValue(edge, ManualOperandSpeculation);
 18191 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBigInt, isNotAnyBigInt(value));
 18192 }
 18193#endif
 18194
1775618195 void speculateNonNullObject(Edge edge, LValue cell)
1775718196 {
1775818197 FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));

Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp

@@static void compileStub(VM& vm, unsigned exitID, JITCode* jitCode, OSRExit& exit
282282 }
283283
284284 if (exit.m_descriptor->m_valueProfile)
285  exit.m_descriptor->m_valueProfile.emitReportValue(jit, JSValueRegs(GPRInfo::regT0));
 285 exit.m_descriptor->m_valueProfile.emitReportValue(jit, JSValueRegs(GPRInfo::regT0), GPRInfo::regT1);
286286 }
287287
288288 // Materialize all objects. Don't materialize an object until all

Source/JavaScriptCore/heap/HeapSnapshotBuilder.cpp

@@String HeapSnapshotBuilder::json(Function<bool (const HeapSnapshotNode&)> allowN
422422
423423 void* wrappedAddress = 0;
424424 unsigned labelIndex = 0;
425  if (!node.cell->isString() && !node.cell->isBigInt()) {
 425 if (!node.cell->isString() && !node.cell->isHeapBigInt()) {
426426 Structure* structure = node.cell->structure(vm);
427427 if (!structure || !structure->globalObject())
428428 flags |= static_cast<unsigned>(NodeFlags::Internal);

Source/JavaScriptCore/heap/MarkedBlockInlines.h

2929#include "JSCast.h"
3030#include "MarkedBlock.h"
3131#include "MarkedSpace.h"
32 #include "Operations.h"
 32#include "Scribble.h"
3333#include "SuperSampler.h"
3434#include "VM.h"
3535

Source/JavaScriptCore/heap/PreciseAllocation.cpp

3030#include "Heap.h"
3131#include "IsoCellSetInlines.h"
3232#include "JSCInlines.h"
33 #include "Operations.h"
 33#include "Scribble.h"
3434#include "SubspaceInlines.h"
3535
3636namespace JSC {

Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp

@@void InspectorHeapAgent::getPreview(ErrorString& errorString, int heapObjectId,
187187 }
188188
189189 // BigInt preview.
190  if (cell->isBigInt()) {
191  resultString = JSBigInt::tryGetString(vm, asBigInt(cell), 10);
 190 if (cell->isHeapBigInt()) {
 191 resultString = JSBigInt::tryGetString(vm, asHeapBigInt(cell), 10);
192192 return;
193193 }
194194

Source/JavaScriptCore/interpreter/Interpreter.cpp

@@unsigned sizeOfVarargs(JSGlobalObject* globalObject, JSValue arguments, uint32_t
205205 break;
206206 case StringType:
207207 case SymbolType:
208  case BigIntType:
 208 case HeapBigIntType:
209209 throwException(globalObject, scope, createInvalidFunctionApplyParameterError(globalObject, arguments));
210210 return 0;
211211

Source/JavaScriptCore/jit/AssemblyHelpers.cpp

@@void AssemblyHelpers::emitConvertValueToBoolean(VM& vm, JSValueRegs value, GPRRe
688688{
689689 // Implements the following control flow structure:
690690 // if (value is cell) {
691  // if (value is string or value is BigInt)
 691 // if (value is string or value is HeapBigInt)
692692 // result = !!value->length
693693 // else {
694694 // do evil things for masquerades-as-undefined

@@void AssemblyHelpers::emitConvertValueToBoolean(VM& vm, JSValueRegs value, GPRRe
698698 // result = !!unboxInt32(value)
699699 // } else if (value is number) {
700700 // result = !!unboxDouble(value)
 701 // } else if (value is BigInt32) {
 702 // result = !!unboxBigInt32(value)
701703 // } else {
702704 // result = value == jsTrue
703705 // }

@@void AssemblyHelpers::emitConvertValueToBoolean(VM& vm, JSValueRegs value, GPRRe
706708
707709 auto notCell = branchIfNotCell(value);
708710 auto isString = branchIfString(value.payloadGPR());
709  auto isBigInt = branchIfBigInt(value.payloadGPR());
 711 auto isHeapBigInt = branchIfHeapBigInt(value.payloadGPR());
710712
711713 if (shouldCheckMasqueradesAsUndefined) {
712714 ASSERT(scratchIfShouldCheckMasqueradesAsUndefined != InvalidGPRReg);

@@void AssemblyHelpers::emitConvertValueToBoolean(VM& vm, JSValueRegs value, GPRRe
729731 comparePtr(invert ? Equal : NotEqual, value.payloadGPR(), result, result);
730732 done.append(jump());
731733
732  isBigInt.link(this);
 734 isHeapBigInt.link(this);
733735 load32(Address(value.payloadGPR(), JSBigInt::offsetOfLength()), result);
734736 compare32(invert ? Equal : NotEqual, result, TrustedImm32(0), result);
735737 done.append(jump());

@@void AssemblyHelpers::emitConvertValueToBoolean(VM& vm, JSValueRegs value, GPRRe
752754 done.append(jump());
753755
754756 notDouble.link(this);
 757#if USE(BIGINT32)
 758 auto isNotBigInt32 = branchIfNotBigInt32KnownNotNumber(value.gpr(), result);
 759 move(value.gpr(), result);
 760 urshift64(TrustedImm32(16), result);
 761 compare32(invert ? Equal : NotEqual, result, TrustedImm32(0), result);
 762 done.append(jump());
 763
 764 isNotBigInt32.link(this);
 765#endif // USE(BIGINT32)
755766#if USE(JSVALUE64)
756767 compare64(invert ? NotEqual : Equal, value.gpr(), TrustedImm32(JSValue::ValueTrue), result);
757768#else

@@AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs val
767778{
768779 // Implements the following control flow structure:
769780 // if (value is cell) {
770  // if (value is string or value is BigInt)
 781 // if (value is string or value is HeapBigInt)
771782 // result = !!value->length
772783 // else {
773784 // do evil things for masquerades-as-undefined

@@AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs val
777788 // result = !!unboxInt32(value)
778789 // } else if (value is number) {
779790 // result = !!unboxDouble(value)
 791 // } else if (value is BigInt32) {
 792 // result = !!unboxBigInt32(value)
780793 // } else {
781794 // result = value == jsTrue
782795 // }

@@AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs val
786799
787800 auto notCell = branchIfNotCell(value);
788801 auto isString = branchIfString(value.payloadGPR());
789  auto isBigInt = branchIfBigInt(value.payloadGPR());
 802 auto isHeapBigInt = branchIfHeapBigInt(value.payloadGPR());
790803
791804 if (shouldCheckMasqueradesAsUndefined) {
792805 ASSERT(scratchIfShouldCheckMasqueradesAsUndefined != InvalidGPRReg);

@@AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs val
817830 truthy.append(branchPtr(invert ? Equal : NotEqual, value.payloadGPR(), TrustedImmPtr(jsEmptyString(vm))));
818831 done.append(jump());
819832
820  isBigInt.link(this);
 833 isHeapBigInt.link(this);
821834 truthy.append(branchTest32(invert ? Zero : NonZero, Address(value.payloadGPR(), JSBigInt::offsetOfLength())));
822835 done.append(jump());
823836

@@AssemblyHelpers::JumpList AssemblyHelpers::branchIfValue(VM& vm, JSValueRegs val
842855 }
843856
844857 notDouble.link(this);
 858#if USE(BIGINT32)
 859 auto isNotBigInt32 = branchIfNotBigInt32KnownNotNumber(value.gpr(), scratch);
 860 move(value.gpr(), scratch);
 861 urshift64(TrustedImm32(16), scratch);
 862 truthy.append(branchTest32(invert ? Zero : NonZero, scratch));
 863 done.append(jump());
 864
 865 isNotBigInt32.link(this);
 866#endif // USE(BIGINT32)
845867#if USE(JSVALUE64)
846868 truthy.append(branch64(invert ? NotEqual : Equal, value.gpr(), TrustedImm64(JSValue::encode(jsBoolean(true)))));
847869#else

Source/JavaScriptCore/jit/AssemblyHelpers.h

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

@@public:
929929 return branchIfNotBoolean(regs.tagGPR(), tempGPR);
930930#endif
931931 }
932 
 932
 933#if USE(BIGINT32)
 934 Jump branchIfBigInt32(GPRReg gpr, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
 935 {
 936 Jump number = branchIfNumber(gpr, mode);
 937 Jump bigInt32 = branchIfBigInt32KnownNotNumber(gpr, tempGPR);
 938 number.link(this);
 939 return bigInt32;
 940 }
 941 JumpList branchIfNotBigInt32(GPRReg gpr, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
 942 {
 943 JumpList result;
 944 result.append(branchIfNumber(gpr, mode));
 945 Jump bigInt32 = branchIfBigInt32KnownNotNumber(gpr, tempGPR);
 946 result.append(jump());
 947 bigInt32.link(this);
 948 return result;
 949 }
 950
 951 Jump branchIfBigInt32KnownNotNumber(GPRReg gpr, GPRReg tempGPR)
 952 {
 953 ASSERT(tempGPR != InvalidGPRReg);
 954 move(gpr, tempGPR);
 955 and64(TrustedImm32(JSValue::BigInt32Tag), tempGPR);
 956 return branch64(Equal, tempGPR, TrustedImm32(JSValue::BigInt32Tag));
 957 }
 958 Jump branchIfNotBigInt32KnownNotNumber(JSValueRegs regs, GPRReg tempGPR)
 959 {
 960 return branchIfNotBigInt32KnownNotNumber(regs.gpr(), tempGPR);
 961 }
 962 Jump branchIfNotBigInt32KnownNotNumber(GPRReg gpr, GPRReg tempGPR)
 963 {
 964 ASSERT(tempGPR != InvalidGPRReg);
 965 move(gpr, tempGPR);
 966 and64(TrustedImm32(JSValue::BigInt32Tag), tempGPR);
 967 return branch64(NotEqual, tempGPR, TrustedImm32(JSValue::BigInt32Tag));
 968 }
 969#endif // USE(BIGINT32)
 970
 971 // FIXME: rename these to make it clear that they require their input to be a cell.
933972 Jump branchIfObject(GPRReg cellGPR)
934973 {
935974 return branch8(

@@public:
951990 {
952991 return branch8(NotEqual, Address(cellGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(type));
953992 }
954 
 993
 994 // FIXME: rename these to make it clear that they require their input to be a cell.
955995 Jump branchIfString(GPRReg cellGPR) { return branchIfType(cellGPR, StringType); }
956996 Jump branchIfNotString(GPRReg cellGPR) { return branchIfNotType(cellGPR, StringType); }
957997 Jump branchIfSymbol(GPRReg cellGPR) { return branchIfType(cellGPR, SymbolType); }
958998 Jump branchIfNotSymbol(GPRReg cellGPR) { return branchIfNotType(cellGPR, SymbolType); }
959  Jump branchIfBigInt(GPRReg cellGPR) { return branchIfType(cellGPR, BigIntType); }
960  Jump branchIfNotBigInt(GPRReg cellGPR) { return branchIfNotType(cellGPR, BigIntType); }
 999 Jump branchIfHeapBigInt(GPRReg cellGPR) { return branchIfType(cellGPR, HeapBigIntType); }
 1000 Jump branchIfNotHeapBigInt(GPRReg cellGPR) { return branchIfNotType(cellGPR, HeapBigIntType); }
9611001 Jump branchIfFunction(GPRReg cellGPR) { return branchIfType(cellGPR, JSFunctionType); }
9621002 Jump branchIfNotFunction(GPRReg cellGPR) { return branchIfNotType(cellGPR, JSFunctionType); }
9631003

@@public:
13561396
13571397 done.link(this);
13581398 }
 1399#endif // USE(JSVALUE64)
 1400
 1401#if USE(BIGINT32)
 1402 void unboxBigInt32(GPRReg gpr)
 1403 {
 1404 urshift64(trustedImm32ForShift(Imm32(16)), gpr);
 1405 }
 1406
 1407 void boxBigInt32(GPRReg gpr)
 1408 {
 1409 lshift64(trustedImm32ForShift(Imm32(16)), gpr);
 1410 or64(TrustedImm32(JSValue::BigInt32Tag), gpr);
 1411 }
13591412#endif
13601413
13611414#if USE(JSVALUE32_64)

@@public:
17151768 // }
17161769 // } else if (is string) {
17171770 // return string
1718  // } else if (is bigint) {
 1771 // } else if (is heapbigint) {
17191772 // return bigint
17201773 // } else {
17211774 // return symbol

@@public:
17261779 // return object
17271780 // } else if (is boolean) {
17281781 // return boolean
 1782 // } else if (is bigint32) {
 1783 // return bigint
17291784 // } else {
17301785 // return undefined
17311786 // }

@@public:
17571812
17581813 notString.link(this);
17591814
1760  Jump notBigInt = branchIfNotBigInt(cellGPR);
 1815 Jump notHeapBigInt = branchIfNotHeapBigInt(cellGPR);
17611816 functor(TypeofType::BigInt, false);
17621817
1763  notBigInt.link(this);
 1818 notHeapBigInt.link(this);
17641819 functor(TypeofType::Symbol, false);
17651820
17661821 notCell.link(this);

@@public:
17761831 Jump notBoolean = branchIfNotBoolean(regs, tempGPR);
17771832 functor(TypeofType::Boolean, false);
17781833 notBoolean.link(this);
 1834
 1835#if USE(BIGINT32)
 1836 Jump notBigInt32 = branchIfNotBigInt32KnownNotNumber(regs, tempGPR);
 1837 functor(TypeofType::BigInt, false);
 1838 notBigInt32.link(this);
 1839#endif
17791840
17801841 functor(TypeofType::Undefined, true);
17811842 }

Source/JavaScriptCore/jit/JIT.cpp

@@void JIT::privateCompileMainPass()
370370 DEFINE_OP(op_is_undefined_or_null)
371371 DEFINE_OP(op_is_boolean)
372372 DEFINE_OP(op_is_number)
 373 DEFINE_OP(op_is_big_int)
373374 DEFINE_OP(op_is_object)
374375 DEFINE_OP(op_is_cell_with_type)
375376 DEFINE_OP(op_jeq_null)

Source/JavaScriptCore/jit/JIT.h

@@namespace JSC {
528528 void emit_op_is_undefined_or_null(const Instruction*);
529529 void emit_op_is_boolean(const Instruction*);
530530 void emit_op_is_number(const Instruction*);
 531 void emit_op_is_big_int(const Instruction*);
531532 void emit_op_is_object(const Instruction*);
532533 void emit_op_is_cell_with_type(const Instruction*);
533534 void emit_op_jeq_null(const Instruction*);

Source/JavaScriptCore/jit/JITArithmetic.cpp

@@void JIT::emit_op_negate(const Instruction* currentInstruction)
476476 UnaryArithProfile* arithProfile = &currentInstruction->as<OpNegate>().metadata(m_codeBlock).m_arithProfile;
477477 JITNegIC* negateIC = m_codeBlock->addJITNegIC(arithProfile);
478478 m_instructionToMathIC.add(currentInstruction, negateIC);
 479 // FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
479480 emitMathICFast<OpNegate>(negateIC, currentInstruction, operationArithNegateProfiled, operationArithNegate);
480481}
481482

@@void JIT::emitSlow_op_negate(const Instruction* currentInstruction, Vector<SlowC
484485 linkAllSlowCases(iter);
485486
486487 JITNegIC* negIC = bitwise_cast<JITNegIC*>(m_instructionToMathIC.get(currentInstruction));
 488 // FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
487489 emitMathICSlow<OpNegate>(negIC, currentInstruction, operationArithNegateProfiledOptimize, operationArithNegateProfiled, operationArithNegateOptimize);
488490}
489491

Source/JavaScriptCore/jit/JITOpcodes.cpp

11/*
2  * Copyright (C) 2009-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2009-2020 Apple Inc. All rights reserved.
33 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
44 *
55 * Redistribution and use in source and binary forms, with or without

@@void JIT::emit_op_is_number(const Instruction* currentInstruction)
283283 emitPutVirtualRegister(dst);
284284}
285285
 286#if USE(BIGINT32)
 287void JIT::emit_op_is_big_int(const Instruction* currentInstruction)
 288{
 289 auto bytecode = currentInstruction->as<OpIsBigInt>();
 290 VirtualRegister dst = bytecode.m_dst;
 291 VirtualRegister value = bytecode.m_operand;
 292
 293 emitGetVirtualRegister(value, regT0);
 294 Jump isCell = branchIfCell(regT0);
 295
 296 move(TrustedImm64(JSValue::BigInt32Mask), regT1);
 297 and64(regT1, regT0);
 298 compare64(Equal, regT0, TrustedImm32(JSValue::BigInt32Tag), regT0);
 299 boxBoolean(regT0, JSValueRegs { regT0 });
 300 Jump done = jump();
 301
 302 isCell.link(this);
 303 compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(HeapBigIntType), regT0);
 304 boxBoolean(regT0, JSValueRegs { regT0 });
 305
 306 done.link(this);
 307 emitPutVirtualRegister(dst);
 308}
 309#else // if !USE(BIGINT32)
 310NO_RETURN void JIT::emit_op_is_big_int(const Instruction*)
 311{
 312 // If we only have HeapBigInts, then we emit isCellWithType instead of isBigInt.
 313 RELEASE_ASSERT_NOT_REACHED();
 314}
 315#endif
 316
286317void JIT::emit_op_is_cell_with_type(const Instruction* currentInstruction)
287318{
288319 auto bytecode = currentInstruction->as<OpIsCellWithType>();

@@void JIT::compileOpStrictEq(const Instruction* currentInstruction, CompileOpStri
570601 VirtualRegister src2 = bytecode.m_rhs;
571602
572603 emitGetVirtualRegisters(src1, regT0, src2, regT1);
573 
 604
 605#if USE(BIGINT32)
 606 /* At a high level we do (assuming 'type' to be StrictEq):
 607 If (left is Double || right is Double)
 608 goto slowPath;
 609 result = (left == right);
 610 if (result)
 611 goto done;
 612 if (left is Cell || right is Cell)
 613 goto slowPath;
 614 done:
 615 return result;
 616 */
 617
 618 // This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 619 // The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 620 // If it is not a number at all, then 1<<49 will be its only high bit set
 621 // Leaving only doubles above or equal 1<<50.
 622 move(regT0, regT2);
 623 move(regT1, regT3);
 624 move(TrustedImm64(JSValue::LowestOfHighBits), regT5);
 625 add64(regT5, regT2);
 626 add64(regT5, regT3);
 627 lshift64(TrustedImm32(1), regT5);
 628 or64(regT2, regT3);
 629 addSlowCase(branch64(AboveOrEqual, regT3, regT5));
 630
 631 compare64(Equal, regT0, regT1, regT5);
 632 Jump done = branchTest64(NonZero, regT5);
 633
 634 move(regT0, regT2);
 635 // Jump slow if at least one is a cell (to cover strings and BigInts).
 636 and64(regT1, regT2);
 637 // FIXME: we could do something more precise: unless there is a BigInt32, we only need to do the slow path if both are strings
 638 addSlowCase(branchIfCell(regT2));
 639
 640 done.link(this);
 641 if (type == CompileOpStrictEqType::NStrictEq)
 642 xor64(TrustedImm64(1), regT5);
 643 boxBoolean(regT5, JSValueRegs { regT5 });
 644 emitPutVirtualRegister(dst, regT5);
 645#else // if !USE(BIGINT32)
574646 // Jump slow if both are cells (to cover strings).
575647 move(regT0, regT2);
576648 or64(regT1, regT2);
577649 addSlowCase(branchIfCell(regT2));
578 
 650
579651 // Jump slow if either is a double. First test if it's an integer, which is fine, and then test
580652 // if it's a double.
581653 Jump leftOK = branchIfInt32(regT0);

@@void JIT::compileOpStrictEq(const Instruction* currentInstruction, CompileOpStri
592664 boxBoolean(regT0, JSValueRegs { regT0 });
593665
594666 emitPutVirtualRegister(dst);
 667#endif
595668}
596669
597670void JIT::emit_op_stricteq(const Instruction* currentInstruction)

@@void JIT::compileOpStrictEqJump(const Instruction* currentInstruction, CompileOp
614687
615688 emitGetVirtualRegisters(src1, regT0, src2, regT1);
616689
 690#if USE(BIGINT32)
 691 /* At a high level we do (assuming 'type' to be StrictEq):
 692 If (left is Double || right is Double)
 693 goto slowPath;
 694 if (left == right)
 695 goto taken;
 696 if (left is Cell || right is Cell)
 697 goto slowPath;
 698 goto notTaken;
 699 */
 700
 701 // This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 702 // The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 703 // If it is not a number at all, then 1<<49 will be its only high bit set
 704 // Leaving only doubles above or equal 1<<50.
 705 move(regT0, regT2);
 706 move(regT1, regT3);
 707 move(TrustedImm64(JSValue::LowestOfHighBits), regT5);
 708 add64(regT5, regT2);
 709 add64(regT5, regT3);
 710 lshift64(TrustedImm32(1), regT5);
 711 or64(regT2, regT3);
 712 addSlowCase(branch64(AboveOrEqual, regT3, regT5));
 713
 714 Jump areEqual = branch64(Equal, regT0, regT1);
 715 if (type == CompileOpStrictEqType::StrictEq)
 716 addJump(areEqual, target);
 717
 718 move(regT0, regT2);
 719 // Jump slow if at least one is a cell (to cover strings and BigInts).
 720 and64(regT1, regT2);
 721 // FIXME: we could do something more precise: unless there is a BigInt32, we only need to do the slow path if both are strings
 722 addSlowCase(branchIfCell(regT2));
 723
 724 if (type == CompileOpStrictEqType::NStrictEq) {
 725 addJump(jump(), target);
 726 areEqual.link(this);
 727 }
 728#else // if !USE(BIGINT32)
617729 // Jump slow if both are cells (to cover strings).
618730 move(regT0, regT2);
619731 or64(regT1, regT2);

@@void JIT::compileOpStrictEqJump(const Instruction* currentInstruction, CompileOp
627739 Jump rightOK = branchIfInt32(regT1);
628740 addSlowCase(branchIfNumber(regT1));
629741 rightOK.link(this);
630 
631742 if (type == CompileOpStrictEqType::StrictEq)
632743 addJump(branch64(Equal, regT1, regT0), target);
633744 else
634745 addJump(branch64(NotEqual, regT1, regT0), target);
 746#endif
635747}
636748
637749void JIT::emit_op_jstricteq(const Instruction* currentInstruction)

@@void JIT::emit_op_to_numeric(const Instruction* currentInstruction)
686798 emitGetVirtualRegister(srcVReg, regT0);
687799
688800 Jump isNotCell = branchIfNotCell(regT0);
689  addSlowCase(branchIfNotBigInt(regT0));
 801 addSlowCase(branchIfNotHeapBigInt(regT0));
690802 Jump isBigInt = jump();
691803
692804 isNotCell.link(this);

Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

@@void JIT::emit_op_is_number(const Instruction* currentInstruction)
288288 emitStoreBool(dst, regT0);
289289}
290290
 291NO_RETURN void JIT::emit_op_is_big_int(const Instruction*)
 292{
 293 // We emit is_cell_with_type instead, since BigInt32 is not supported on 32-bit platforms.
 294 RELEASE_ASSERT_NOT_REACHED();
 295}
 296
291297void JIT::emit_op_is_cell_with_type(const Instruction* currentInstruction)
292298{
293299 auto bytecode = currentInstruction->as<OpIsCellWithType>();

@@void JIT::emit_op_to_numeric(const Instruction* currentInstruction)
866872 emitLoad(src, regT1, regT0);
867873
868874 Jump isNotCell = branchIfNotCell(regT1);
869  addSlowCase(branchIfNotBigInt(regT0));
 875 addSlowCase(branchIfNotHeapBigInt(regT0));
870876 Jump isBigInt = jump();
871877
872878 isNotCell.link(this);

Source/JavaScriptCore/jit/JITOperations.cpp

@@size_t JIT_OPERATION operationCompareStrictEq(JSGlobalObject* globalObject, Enco
13151315 return JSValue::strictEqual(globalObject, src1, src2);
13161316}
13171317
 1318#if USE(BIGINT32)
 1319size_t JIT_OPERATION operationCompareEqHeapBigIntToInt32(JSGlobalObject* globalObject, JSCell* heapBigInt, int32_t smallInt)
 1320{
 1321 VM& vm = globalObject->vm();
 1322 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
 1323 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
 1324
 1325 ASSERT(heapBigInt->isHeapBigInt());
 1326
 1327 return static_cast<JSBigInt*>(heapBigInt)->equalsToInt32(smallInt);
 1328}
 1329#endif
 1330
13181331EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(JSGlobalObject* globalObject, ArrayAllocationProfile* profile, const JSValue* values, int size)
13191332{
13201333 VM& vm = globalObject->vm();

@@EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(JSGlobalObject*
28382851 return profiledMul(globalObject, encodedOp1, encodedOp2, *arithProfile);
28392852}
28402853
 2854// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
28412855EncodedJSValue JIT_OPERATION operationArithNegate(JSGlobalObject* globalObject, EncodedJSValue encodedOperand)
28422856{
28432857 VM& vm = globalObject->vm();

@@EncodedJSValue JIT_OPERATION operationArithNegate(JSGlobalObject* globalObject,
28502864 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
28512865 RETURN_IF_EXCEPTION(scope, encodedJSValue());
28522866
2853  if (primValue.isBigInt())
2854  return JSValue::encode(JSBigInt::unaryMinus(vm, asBigInt(primValue)));
 2867#if USE(BIGINT32)
 2868 if (primValue.isBigInt32()) {
 2869 int32_t value = primValue.bigInt32AsInt32();
 2870 if (value != INT_MIN)
 2871 return JSValue::encode(JSValue(JSValue::JSBigInt32, -value));
 2872 primValue = JSBigInt::createFrom(vm, value);
 2873 }
 2874#endif
 2875 if (primValue.isHeapBigInt())
 2876 return JSValue::encode(JSBigInt::unaryMinus(vm, primValue.asHeapBigInt()));
28552877
28562878 double number = primValue.toNumber(globalObject);
28572879 RETURN_IF_EXCEPTION(scope, encodedJSValue());

@@EncodedJSValue JIT_OPERATION operationArithNegate(JSGlobalObject* globalObject,
28592881
28602882}
28612883
 2884// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
28622885EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject* globalObject, EncodedJSValue encodedOperand, UnaryArithProfile* arithProfile)
28632886{
28642887 ASSERT(arithProfile);

@@EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject* global
28732896 JSValue primValue = operand.toPrimitive(globalObject);
28742897 RETURN_IF_EXCEPTION(scope, encodedJSValue());
28752898
2876  if (primValue.isBigInt()) {
2877  JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue));
 2899#if USE(BIGINT32)
 2900 if (primValue.isBigInt32()) {
 2901 int32_t value = primValue.bigInt32AsInt32();
 2902 if (value != INT_MIN) {
 2903 auto result = JSValue(JSValue::JSBigInt32, -value);
 2904 arithProfile->observeResult(result);
 2905 return JSValue::encode(result);
 2906 }
 2907 primValue = JSBigInt::createFrom(vm, value);
 2908 }
 2909#endif
 2910 if (primValue.isHeapBigInt()) {
 2911 JSBigInt* result = JSBigInt::unaryMinus(vm, primValue.asHeapBigInt());
28782912 arithProfile->observeResult(result);
2879 
28802913 return JSValue::encode(result);
28812914 }
28822915

@@EncodedJSValue JIT_OPERATION operationArithNegateProfiled(JSGlobalObject* global
28872920 return JSValue::encode(result);
28882921}
28892922
 2923// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
28902924EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(JSGlobalObject* globalObject, EncodedJSValue encodedOperand, JITNegIC* negIC)
28912925{
28922926 VM& vm = globalObject->vm();

@@EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(JSGlobalObject
29072941
29082942 JSValue primValue = operand.toPrimitive(globalObject);
29092943 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2910 
2911  if (primValue.isBigInt()) {
2912  JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue));
 2944
 2945#if USE(BIGINT32)
 2946 if (primValue.isBigInt32()) {
 2947 int32_t value = primValue.bigInt32AsInt32();
 2948 if (value != INT_MIN) {
 2949 auto result = JSValue(JSValue::JSBigInt32, -value);
 2950 arithProfile->observeResult(result);
 2951 return JSValue::encode(result);
 2952 }
 2953 primValue = JSBigInt::createFrom(vm, value);
 2954 }
 2955#endif
 2956 if (primValue.isHeapBigInt()) {
 2957 JSBigInt* result = JSBigInt::unaryMinus(vm, primValue.asHeapBigInt());
29132958 arithProfile->observeResult(result);
29142959 return JSValue::encode(result);
29152960 }

@@EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(JSGlobalObject
29212966 return JSValue::encode(result);
29222967}
29232968
 2969// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
29242970EncodedJSValue JIT_OPERATION operationArithNegateOptimize(JSGlobalObject* globalObject, EncodedJSValue encodedOperand, JITNegIC* negIC)
29252971{
29262972 VM& vm = globalObject->vm();

@@EncodedJSValue JIT_OPERATION operationArithNegateOptimize(JSGlobalObject* global
29402986
29412987 JSValue primValue = operand.toPrimitive(globalObject);
29422988 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2943 
2944  if (primValue.isBigInt())
2945  return JSValue::encode(JSBigInt::unaryMinus(vm, asBigInt(primValue)));
 2989
 2990#if USE(BIGINT32)
 2991 // FIXME: why does this function profile the argument but not the result?
 2992 if (primValue.isBigInt32()) {
 2993 int32_t value = primValue.bigInt32AsInt32();
 2994 if (value != INT_MIN)
 2995 return JSValue::encode(JSValue(JSValue::JSBigInt32, -value));
 2996 primValue = JSBigInt::createFrom(vm, value);
 2997 }
 2998#endif
 2999 if (primValue.isHeapBigInt())
 3000 return JSValue::encode(JSBigInt::unaryMinus(vm, primValue.asHeapBigInt()));
29463001
29473002 double number = primValue.toNumber(globalObject);
29483003 RETURN_IF_EXCEPTION(scope, encodedJSValue());

Source/JavaScriptCore/jit/JITOperations.h

@@size_t JIT_OPERATION operationCompareEq(JSGlobalObject*, EncodedJSValue, Encoded
206206size_t JIT_OPERATION operationCompareStrictEq(JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
207207#if USE(JSVALUE64)
208208EncodedJSValue JIT_OPERATION operationCompareStringEq(JSGlobalObject*, JSCell* left, JSCell* right) WTF_INTERNAL;
 209size_t JIT_OPERATION operationCompareEqHeapBigIntToInt32(JSGlobalObject*, JSCell* heapBigInt, int32_t smallInt) WTF_INTERNAL;
209210#else
210211size_t JIT_OPERATION operationCompareStringEq(JSGlobalObject*, JSCell* left, JSCell* right) WTF_INTERNAL;
211212#endif

Source/JavaScriptCore/llint/LLIntOfflineAsmConfig.h

136136#define OFFLINE_ASM_JSVALUE64 0
137137#endif
138138
 139#if USE(BIGINT32)
 140#define OFFLINE_ASM_BIGINT32 1
 141#else
 142#define OFFLINE_ASM_BIGINT32 0
 143#endif
 144
139145#if CPU(ADDRESS64)
140146#define OFFLINE_ASM_ADDRESS64 1
141147#else

Source/JavaScriptCore/llint/LowLevelInterpreter.asm

@@if JSVALUE64
196196 const ValueNull = constexpr JSValue::ValueNull
197197 const TagNumber = constexpr JSValue::NumberTag
198198 const NotCellMask = constexpr JSValue::NotCellMask
 199 if BIGINT32
 200 const TagBigInt32 = constexpr JSValue::BigInt32Tag
 201 const MaskBigInt32 = constexpr JSValue::BigInt32Mask
 202 end
 203 const LowestOfHighBits = constexpr JSValue::LowestOfHighBits
199204else
200205 const Int32Tag = constexpr JSValue::Int32Tag
201206 const BooleanTag = constexpr JSValue::BooleanTag

@@const JSFunctionType = constexpr JSFunctionType
521526const ArrayType = constexpr ArrayType
522527const DerivedArrayType = constexpr DerivedArrayType
523528const ProxyObjectType = constexpr ProxyObjectType
 529const HeapBigIntType = constexpr HeapBigIntType
524530
525531# The typed array types need to be numbered in a particular order because of the manually written
526532# switch statement in get_by_val and put_by_val.

Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

@@llintOpWithReturn(op_is_number, OpIsNumber, macro (size, get, dispatch, return)
13061306end)
13071307
13081308
 1309# On 32-bit platforms BIGINT32 is not supported, so we generate op_is_cell_with_type instead of op_is_big_int
 1310llintOp(op_is_big_int, OpIsBigInt, macro(unused, unused, unused)
 1311 notSupported()
 1312end)
 1313
 1314
13091315llintOpWithReturn(op_is_cell_with_type, OpIsCellWithType, macro (size, get, dispatch, return)
13101316 get(m_operand, t1)
13111317 loadConstantOrVariable(size, t1, t0, t3)

Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

1 # Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 1# Copyright (C) 2011-2020 Apple Inc. All rights reserved.
22#
33# Redistribution and use in source and binary forms, with or without
44# modification, are permitted provided that the following conditions

@@llintOpWithReturn(op_is_undefined_or_null, OpIsUndefinedOrNull, macro (size, get
844844end)
845845
846846
847 macro strictEqOp(opcodeName, opcodeStruct, equalityOperation)
 847macro strictEqOp(opcodeName, opcodeStruct, createBoolean)
848848 llintOpWithReturn(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, return)
849849 get(m_rhs, t0)
850850 get(m_lhs, t2)
851851 loadConstantOrVariable(size, t0, t1)
852852 loadConstantOrVariable(size, t2, t0)
 853
 854 # At a high level we do
 855 # If (left is Double || right is Double)
 856 # goto slowPath;
 857 # result = (left == right);
 858 # if (result)
 859 # goto done;
 860 # if (left is Cell || right is Cell)
 861 # goto slowPath;
 862 # done:
 863 # return result;
 864
 865 # This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 866 # The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 867 # If it is not a number at all, then 1<<49 will be its only high bit set
 868 # Leaving only doubles above or equal 1<<50.
 869 move t0, t2
 870 move t1, t3
 871 move LowestOfHighBits, t5
 872 addq t5, t2
 873 addq t5, t3
 874 orq t2, t3
 875 lshiftq 1, t5
 876 bqaeq t3, t5, .slow
 877
 878 cqeq t0, t1, t5
 879 btqnz t5, t5, .done #is there a better way of checking t5 != 0 ?
 880
853881 move t0, t2
854  orq t1, t2
 882 # This andq could be an 'or' if not for BigInt32 (since it makes it possible for a Cell to be strictEqual to a non-Cell)
 883 andq t1, t2
855884 btqz t2, notCellMask, .slow
856  bqaeq t0, numberTag, .leftOK
857  btqnz t0, numberTag, .slow
858  .leftOK:
859  bqaeq t1, numberTag, .rightOK
860  btqnz t1, numberTag, .slow
861  .rightOK:
862  equalityOperation(t0, t1, t0)
863  orq ValueFalse, t0
864  return(t0)
 885
 886 .done:
 887 createBoolean(t5)
 888 return(t5)
865889
866890 .slow:
867891 callSlowPath(_slow_path_%opcodeName%)

@@end
871895
872896
873897strictEqOp(stricteq, OpStricteq,
874  macro (left, right, result) cqeq left, right, result end)
 898 macro (operand) xorq ValueFalse, operand end)
875899
876900
877901strictEqOp(nstricteq, OpNstricteq,
878  macro (left, right, result) cqneq left, right, result end)
 902 macro (operand) xorq ValueTrue, operand end)
879903
880904
881 macro strictEqualityJumpOp(opcodeName, opcodeStruct, equalityOperation)
 905macro strictEqualityJumpOp(opcodeName, opcodeStruct, jumpIfEqual, jumpIfNotEqual)
882906 llintOpWithJump(op_%opcodeName%, opcodeStruct, macro (size, get, jump, dispatch)
883907 get(m_lhs, t2)
884908 get(m_rhs, t3)
885909 loadConstantOrVariable(size, t2, t0)
886910 loadConstantOrVariable(size, t3, t1)
 911
 912 # At a high level we do
 913 # If (left is Double || right is Double)
 914 # goto slowPath;
 915 # if (left == right)
 916 # goto jumpTarget;
 917 # if (left is Cell || right is Cell)
 918 # goto slowPath;
 919 # goto otherJumpTarget
 920
 921 # This fragment implements (left is Double || right is Double), with a single branch instead of the 4 that would be naively required if we used branchIfInt32/branchIfNumber
 922 # The trick is that if a JSValue is an Int32, then adding 1<<49 to it will make it overflow, leaving all high bits at 0
 923 # If it is not a number at all, then 1<<49 will be its only high bit set
 924 # Leaving only doubles above or equal 1<<50.
887925 move t0, t2
888  orq t1, t2
 926 move t1, t3
 927 move LowestOfHighBits, t5
 928 addq t5, t2
 929 addq t5, t3
 930 orq t2, t3
 931 lshiftq 1, t5
 932 bqaeq t3, t5, .slow
 933
 934 bqeq t0, t1, .equal
 935
 936 move t0, t2
 937 # This andq could be an 'or' if not for BigInt32 (since it makes it possible for a Cell to be strictEqual to a non-Cell)
 938 andq t1, t2
889939 btqz t2, notCellMask, .slow
890  bqaeq t0, numberTag, .leftOK
891  btqnz t0, numberTag, .slow
892  .leftOK:
893  bqaeq t1, numberTag, .rightOK
894  btqnz t1, numberTag, .slow
895  .rightOK:
896  equalityOperation(t0, t1, .jumpTarget)
897  dispatch()
898940
899  .jumpTarget:
900  jump(m_targetLabel)
 941 jumpIfNotEqual(jump, m_targetLabel, dispatch)
 942
 943 .equal:
 944 jumpIfEqual(jump, m_targetLabel, dispatch)
901945
902946 .slow:
903947 callSlowPath(_llint_slow_path_%opcodeName%)

@@end
907951
908952
909953strictEqualityJumpOp(jstricteq, OpJstricteq,
910  macro (left, right, target) bqeq left, right, target end)
911 
 954 macro (jump, targetLabel, dispatch) jump(targetLabel) end,
 955 macro (jump, targetLabel, dispatch) dispatch() end)
912956
913957strictEqualityJumpOp(jnstricteq, OpJnstricteq,
914  macro (left, right, target) bqneq left, right, target end)
 958 macro (jump, targetLabel, dispatch) dispatch() end,
 959 macro (jump, targetLabel, dispatch) jump(targetLabel) end)
915960
916961macro preOp(opcodeName, opcodeStruct, integerOperation)
917962 llintOpWithMetadata(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, metadata, return)
918963 macro updateArithProfile(type)
919  orh type, %opcodeStruct%::Metadata::m_arithProfile + UnaryArithProfile::m_bits[t1]
 964 orh type, %opcodeStruct%::Metadata::m_arithProfile + UnaryArithProfile::m_bits[t2]
920965 end
921966
922967 get(m_srcDst, t0)
923  loadq [cfr, t0, 8], t3
924  metadata(t1, t2)
925  # Metadata in t1, srcDst in t3
926  bqb t3, numberTag, .slow
927  integerOperation(t3, .slow)
928  orq numberTag, t3
929  storeq t3, [cfr, t0, 8]
 968 loadq [cfr, t0, 8], t1
 969 metadata(t2, t3)
 970 # srcDst in t1, metadata in t2
 971 # FIXME: the next line jumps to the slow path for BigInt32. We could instead have a dedicated path in here for them.
 972 bqb t1, numberTag, .slow
 973 integerOperation(t1, .slow)
 974 orq numberTag, t1
 975 storeq t1, [cfr, t0, 8]
930976 updateArithProfile(ArithProfileInt)
931977 dispatch()
932978

@@macro preOp(opcodeName, opcodeStruct, integerOperation)
934980 callSlowPath(_slow_path_%opcodeName%)
935981 dispatch()
936982 end)
 983
937984end
938985
939986llintOpWithProfile(op_to_number, OpToNumber, macro (size, get, dispatch, return)

@@llintOpWithReturn(op_is_number, OpIsNumber, macro (size, get, dispatch, return)
12791326 return(t1)
12801327end)
12811328
 1329if BIGINT32
 1330 llintOpWithReturn(op_is_big_int, OpIsBigInt, macro(size, get, dispatch, return)
 1331 get(m_operand, t1)
 1332 loadConstantOrVariable(size, t1, t0)
 1333 btqnz t0, notCellMask, .notCellCase
 1334 cbeq JSCell::m_type[t0], HeapBigIntType, t1
 1335 orq ValueFalse, t1
 1336 return(t1)
 1337 .notCellCase:
 1338 andq MaskBigInt32, t0
 1339 cqeq t0, TagBigInt32, t0
 1340 orq ValueFalse, t0
 1341 return(t0)
 1342 end)
 1343else
 1344# if BIGINT32 is not supported we generate op_is_cell_with_type instead of op_is_big_int
 1345 llintOp(op_is_big_int, OpIsBigInt, macro(unused, unused, unused)
 1346 notSupported()
 1347 end)
 1348end
12821349
12831350llintOpWithReturn(op_is_cell_with_type, OpIsCellWithType, macro (size, get, dispatch, return)
12841351 getu(size, OpIsCellWithType, m_type, t0)

Source/JavaScriptCore/parser/ParserArena.cpp

@@const Identifier& IdentifierArena::makeBigIntDecimalIdentifier(VM& vm, const Ide
8383 if (radix == 10)
8484 return identifier;
8585
 86 auto scope = DECLARE_CATCH_SCOPE(vm);
 87 JSValue bigInt = JSBigInt::parseInt(nullptr, vm, identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, JSBigInt::ParseIntSign::Unsigned);
 88 scope.assertNoException();
 89
8690 // FIXME: We are allocating a JSBigInt just to be able to use
8791 // JSBigInt::tryGetString when radix is not 10.
8892 // This creates some GC pressure, but since these identifiers

@@const Identifier& IdentifierArena::makeBigIntDecimalIdentifier(VM& vm, const Ide
9094 // it wont be much problematic, given such cases are very rare.
9195 // There is a lot of optimizations we can apply here when necessary.
9296 // https://bugs.webkit.org/show_bug.cgi?id=207627
93 
94  auto scope = DECLARE_CATCH_SCOPE(vm);
95  JSBigInt* bigInt = JSBigInt::parseInt(nullptr, vm, identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, JSBigInt::ParseIntSign::Unsigned);
96  scope.assertNoException();
97  m_identifiers.append(Identifier::fromString(vm, JSBigInt::tryGetString(vm, bigInt, 10)));
 97 JSBigInt* heapBigInt;
 98#if USE(BIGINT32)
 99 if (bigInt.isBigInt32())
 100 heapBigInt = JSBigInt::createFrom(vm, bigInt.bigInt32AsInt32());
 101 else
 102#endif
 103 heapBigInt = bigInt.asHeapBigInt();
 104
 105 m_identifiers.append(Identifier::fromString(vm, JSBigInt::tryGetString(vm, heapBigInt, 10)));
98106 return m_identifiers.last();
99107}
100108

Source/JavaScriptCore/runtime/ArrayPrototype.cpp

4343#include "Lookup.h"
4444#include "ObjectConstructor.h"
4545#include "ObjectPrototype.h"
46 #include "Operations.h"
4746#include "StringRecursionChecker.h"
4847#include <algorithm>
4948#include <wtf/Assertions.h>

Source/JavaScriptCore/runtime/BigIntConstructor.cpp

11/*
22 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions

@@void BigIntConstructor::finishCreation(VM& vm, BigIntPrototype* bigIntPrototype)
7575
7676// ------------------------------ Functions ---------------------------
7777
78 static bool isSafeInteger(JSValue argument)
79 {
80  if (argument.isInt32())
81  return true;
82 
83  if (!argument.isDouble())
84  return false;
85 
86  double number = argument.asDouble();
87  return trunc(number) == number && std::abs(number) <= maxSafeInteger();
88 }
89 
9078static EncodedJSValue toBigInt(JSGlobalObject* globalObject, JSValue argument)
9179{
9280 ASSERT(argument.isPrimitive());

@@static EncodedJSValue toBigInt(JSGlobalObject* globalObject, JSValue argument)
9482
9583 if (argument.isBigInt())
9684 return JSValue::encode(argument);
97 
 85
 86 if (argument.isBoolean()) {
 87#if USE(BIGINT32)
 88 return JSValue::encode(JSValue(JSValue::JSBigInt32, argument.asBoolean()));
 89#else
 90 return JSValue::encode(JSBigInt::createFrom(vm, argument.asBoolean()));
 91#endif
 92 }
 93
 94 if (argument.isString()) {
 95 return toStringView(globalObject, argument, [&] (StringView view) {
 96 return JSValue::encode(JSBigInt::parseInt(globalObject, view));
 97 });
 98 }
 99
 100 ASSERT(argument.isUndefinedOrNull() || argument.isNumber() || argument.isSymbol());
98101 auto scope = DECLARE_THROW_SCOPE(vm);
99 
100  if (argument.isBoolean())
101  RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(vm, argument.asBoolean())));
102 
103  if (argument.isUndefinedOrNull() || argument.isNumber() || argument.isSymbol())
104  return throwVMTypeError(globalObject, scope, "Invalid argument type in ToBigInt operation"_s);
105 
106  ASSERT(argument.isString());
107 
108  RELEASE_AND_RETURN(scope, toStringView(globalObject, argument, [&] (StringView view) {
109  return JSValue::encode(JSBigInt::parseInt(globalObject, view));
110  }));
 102 return throwVMTypeError(globalObject, scope, "Invalid argument type in ToBigInt operation"_s);
111103}
112104
113105static EncodedJSValue JSC_HOST_CALL callBigIntConstructor(JSGlobalObject* globalObject, CallFrame* callFrame)

@@static EncodedJSValue JSC_HOST_CALL callBigIntConstructor(JSGlobalObject* global
119111 JSValue primitive = value.toPrimitive(globalObject);
120112 RETURN_IF_EXCEPTION(scope, encodedJSValue());
121113
122  if (primitive.isNumber()) {
123  if (!isSafeInteger(primitive))
124  return throwVMError(globalObject, scope, createRangeError(globalObject, "Not safe integer"_s));
125 
126  scope.release();
127  if (primitive.isInt32())
128  return JSValue::encode(JSBigInt::createFrom(vm, primitive.asInt32()));
 114 if (primitive.isInt32()) {
 115#if USE(BIGINT32)
 116 return JSValue::encode(JSValue(JSValue::JSBigInt32, primitive.asInt32()));
 117#else
 118 return JSValue::encode(JSBigInt::createFrom(vm, primitive.asInt32()));
 119#endif
 120 }
129121
130  if (primitive.isUInt32())
131  return JSValue::encode(JSBigInt::createFrom(vm, primitive.asUInt32()));
 122 if (primitive.isDouble()) {
 123 double number = primitive.asDouble();
 124 if (trunc(number) != number || std::abs(number) > maxSafeInteger())
 125 return throwVMError(globalObject, scope, createRangeError(globalObject, "Not a safe integer"_s));
132126
133  return JSValue::encode(JSBigInt::createFrom(vm, static_cast<int64_t>(primitive.asDouble())));
 127 return JSValue::encode(JSBigInt::makeHeapBigIntOrBigInt32(vm, static_cast<int64_t>(primitive.asDouble())));
134128 }
135 
 129
136130 EncodedJSValue result = toBigInt(globalObject, primitive);
137131 RETURN_IF_EXCEPTION(scope, encodedJSValue());
138132 return result;

Source/JavaScriptCore/runtime/BigIntObject.cpp

11/*
22 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>.
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions

@@STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BigIntObject);
3737const ClassInfo BigIntObject::s_info = { "BigInt", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(BigIntObject) };
3838
3939
40 BigIntObject* BigIntObject::create(VM& vm, JSGlobalObject* globalObject, JSBigInt* bigInt)
 40BigIntObject* BigIntObject::create(VM& vm, JSGlobalObject* globalObject, JSValue bigInt)
4141{
4242 BigIntObject* object = new (NotNull, allocateCell<BigIntObject>(vm.heap)) BigIntObject(vm, globalObject->bigIntObjectStructure());
4343 object->finishCreation(vm, bigInt);

@@BigIntObject::BigIntObject(VM& vm, Structure* structure)
4949{
5050}
5151
52 void BigIntObject::finishCreation(VM& vm, JSBigInt* bigInt)
 52void BigIntObject::finishCreation(VM& vm, JSValue bigInt)
5353{
5454 Base::finishCreation(vm);
5555 ASSERT(inherits(vm, info()));

Source/JavaScriptCore/runtime/BigIntObject.h

11/*
22 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>.
3  * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions

2626
2727#pragma once
2828
29 #include "JSBigInt.h"
3029#include "JSWrapperObject.h"
3130
3231namespace JSC {

@@public:
4140 return vm.bigIntObjectSpace<mode>();
4241 }
4342
44  static BigIntObject* create(VM&, JSGlobalObject*, JSBigInt*);
 43 static BigIntObject* create(VM&, JSGlobalObject*, JSValue);
4544
4645 DECLARE_EXPORT_INFO;
4746
48  JSBigInt* internalValue() const { return asBigInt(JSWrapperObject::internalValue()); }
 47 JSValue internalValue() const { return JSWrapperObject::internalValue(); }
4948
5049 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
5150 {

@@public:
5756 static String toStringName(const JSObject*, JSGlobalObject*);
5857
5958protected:
60  JS_EXPORT_PRIVATE void finishCreation(VM&, JSBigInt*);
 59 JS_EXPORT_PRIVATE void finishCreation(VM&, JSValue);
6160 JS_EXPORT_PRIVATE BigIntObject(VM&, Structure*);
6261};
6362static_assert(sizeof(BigIntObject) == sizeof(JSWrapperObject));

Source/JavaScriptCore/runtime/BigIntPrototype.cpp

@@void BigIntPrototype::finishCreation(VM& vm, JSGlobalObject*)
8181
8282static ALWAYS_INLINE JSBigInt* toThisBigIntValue(VM& vm, JSValue thisValue)
8383{
 84#if USE(BIGINT32)
 85 // FIXME: heap-allocating all big ints is inneficient, but re-implementing toString for small BigInts is enough work that I'm deferring it to a later patch.
 86 if (thisValue.isBigInt32())
 87 return JSBigInt::createFrom(vm, thisValue.bigInt32AsInt32());
 88#endif
 89
8490 if (thisValue.isCell()) {
8591 if (JSBigInt* bigInt = jsDynamicCast<JSBigInt*>(vm, thisValue.asCell()))
8692 return bigInt;
87 
88  if (BigIntObject* bigIntObject = jsDynamicCast<BigIntObject*>(vm, thisValue.asCell()))
89  return bigIntObject->internalValue();
 93
 94 if (BigIntObject* bigIntObject = jsDynamicCast<BigIntObject*>(vm, thisValue.asCell())) {
 95 JSValue bigInt = bigIntObject->internalValue();
 96#if USE(BIGINT32)
 97 if (bigInt.isBigInt32())
 98 return JSBigInt::createFrom(vm, bigInt.bigInt32AsInt32());
 99#endif
 100 return bigInt.asHeapBigInt();
 101 }
90102 }
91103
92104 return nullptr;

@@EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToString(JSGlobalObject* globalObjec
116128 return JSValue::encode(jsNontrivialString(vm, resultString));
117129}
118130
 131// FIXME: this function should introduce the right separators for thousands and similar things.
119132EncodedJSValue JSC_HOST_CALL bigIntProtoFuncToLocaleString(JSGlobalObject* globalObject, CallFrame* callFrame)
120133{
121134 VM& vm = globalObject->vm();

Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

6868#include "ThunkGenerators.h"
6969#include "TypeProfilerLog.h"
7070#include <wtf/StringPrintStream.h>
71 #include <wtf/Variant.h>
7271
7372namespace JSC {
7473

@@SLOW_PATH_DECL(slow_path_inc)
469468 BEGIN();
470469 auto bytecode = pc->as<OpInc>();
471470 JSValue argument = GET_C(bytecode.m_srcDst).jsValue();
472  Variant<JSBigInt*, double> resultVariant = argument.toNumeric(globalObject);
 471 JSValue result = jsInc(globalObject, argument);
473472 CHECK_EXCEPTION();
474  JSValue result;
475  if (WTF::holds_alternative<JSBigInt*>(resultVariant))
476  result = JSBigInt::inc(globalObject, WTF::get<JSBigInt*>(resultVariant));
477  else
478  result = jsNumber(WTF::get<double>(resultVariant) + 1);
479473 RETURN_WITH_PROFILING_CUSTOM(bytecode.m_srcDst, result, { });
480474}
481475

@@SLOW_PATH_DECL(slow_path_dec)
484478 BEGIN();
485479 auto bytecode = pc->as<OpDec>();
486480 JSValue argument = GET_C(bytecode.m_srcDst).jsValue();
487  Variant<JSBigInt*, double> resultVariant = argument.toNumeric(globalObject);
 481 JSValue result = jsDec(globalObject, argument);
488482 CHECK_EXCEPTION();
489  JSValue result;
490  if (WTF::holds_alternative<JSBigInt*>(resultVariant))
491  result = JSBigInt::dec(globalObject, WTF::get<JSBigInt*>(resultVariant));
492  else
493  result = jsNumber(WTF::get<double>(resultVariant) - 1);
494483 RETURN_WITH_PROFILING_CUSTOM(bytecode.m_srcDst, result, { });
495484}
496485

@@static void updateArithProfileForUnaryArithOp(OpNegate::Metadata& metadata, JSVa
507496 UnaryArithProfile& profile = metadata.m_arithProfile;
508497 profile.observeArg(operand);
509498 ASSERT(result.isNumber() || result.isBigInt());
510  if (result.isNumber()) {
 499
 500 if (result.isHeapBigInt())
 501 profile.setObservedHeapBigInt();
 502#if USE(BIGINT32)
 503 else if (result.isBigInt32())
 504 profile.setObservedBigInt32();
 505#endif
 506 else {
 507 ASSERT(result.isNumber());
511508 if (!result.isInt32()) {
512509 if (operand.isInt32())
513510 profile.setObservedInt32Overflow();

@@static void updateArithProfileForUnaryArithOp(OpNegate::Metadata& metadata, JSVa
527524 profile.setObservedInt52Overflow();
528525 }
529526 }
530  } else if (result.isBigInt())
531  profile.setObservedBigInt();
532  else
533  profile.setObservedNonNumeric();
 527 }
534528}
535529#else
536530static void updateArithProfileForUnaryArithOp(OpNegate::Metadata&, JSValue, JSValue) { }

@@SLOW_PATH_DECL(slow_path_negate)
545539 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
546540 CHECK_EXCEPTION();
547541
548  if (primValue.isBigInt()) {
549  JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue));
 542#if USE(BIGINT32)
 543 if (primValue.isBigInt32()) {
 544 int32_t value = primValue.bigInt32AsInt32();
 545 if (value != INT_MIN) {
 546 auto result = JSValue(JSValue::JSBigInt32, -value);
 547 RETURN_WITH_PROFILING(result, {
 548 updateArithProfileForUnaryArithOp(metadata, result, operand);
 549 });
 550 } else
 551 primValue = JSBigInt::createFrom(vm, value);
 552 }
 553#endif
 554
 555 if (primValue.isHeapBigInt()) {
 556 JSBigInt* result = JSBigInt::unaryMinus(vm, primValue.asHeapBigInt());
550557 RETURN_WITH_PROFILING(result, {
551558 updateArithProfileForUnaryArithOp(metadata, result, operand);
552559 });

@@static void updateArithProfileForBinaryArithOp(JSGlobalObject*, CodeBlock* codeB
584591 profile.setObservedInt52Overflow();
585592 }
586593 }
587  } else if (result.isBigInt())
588  profile.setObservedBigInt();
 594 } else if (result.isHeapBigInt())
 595 profile.setObservedHeapBigInt();
 596#if USE(BIGINT32)
 597 else if (result.isBigInt32())
 598 profile.setObservedBigInt32();
 599#endif
589600 else
590601 profile.setObservedNonNumeric();
591602}

@@SLOW_PATH_DECL(slow_path_to_numeric)
607618 BEGIN();
608619 auto bytecode = pc->as<OpToNumeric>();
609620 JSValue argument = GET_C(bytecode.m_operand).jsValue();
610  Variant<JSBigInt*, double> resultVariant = argument.toNumeric(globalObject);
 621 JSValue result = argument.toNumeric(globalObject);
611622 CHECK_EXCEPTION();
612  JSValue result;
613  if (WTF::holds_alternative<JSBigInt*>(resultVariant))
614  result = WTF::get<JSBigInt*>(resultVariant);
615  else
616  result = jsNumber(WTF::get<double>(resultVariant));
617623 RETURN_PROFILED(result);
618624}
619625

@@SLOW_PATH_DECL(slow_path_add)
649655}
650656
651657// The following arithmetic and bitwise operations need to be sure to run
652 // toNumber() on their operands in order. (A call to toNumber() is idempotent
 658// toNumeric/toBigIntOrInt32() on their operands in order. (A call to these is idempotent
653659// if an exception is already set on the CallFrame.)
654660
655661SLOW_PATH_DECL(slow_path_mul)

@@SLOW_PATH_DECL(slow_path_sub)
671677 auto bytecode = pc->as<OpSub>();
672678 JSValue left = GET_C(bytecode.m_lhs).jsValue();
673679 JSValue right = GET_C(bytecode.m_rhs).jsValue();
674  auto leftNumeric = left.toNumeric(globalObject);
 680 JSValue result = jsSub(globalObject, left, right);
675681 CHECK_EXCEPTION();
676  auto rightNumeric = right.toNumeric(globalObject);
677  CHECK_EXCEPTION();
678 
679  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
680  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
681  JSBigInt* result = JSBigInt::sub(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
682  CHECK_EXCEPTION();
683  RETURN_WITH_PROFILING(result, {
684  updateArithProfileForBinaryArithOp(globalObject, codeBlock, pc, result, left, right);
685  });
686  }
687 
688  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in subtraction."));
689  }
690 
691  JSValue result = jsNumber(WTF::get<double>(leftNumeric) - WTF::get<double>(rightNumeric));
692682 RETURN_WITH_PROFILING(result, {
693683 updateArithProfileForBinaryArithOp(globalObject, codeBlock, pc, result, left, right);
694684 });

@@SLOW_PATH_DECL(slow_path_div)
700690 auto bytecode = pc->as<OpDiv>();
701691 JSValue left = GET_C(bytecode.m_lhs).jsValue();
702692 JSValue right = GET_C(bytecode.m_rhs).jsValue();
703  auto leftNumeric = left.toNumeric(globalObject);
 693 JSValue result = jsDiv(globalObject, left, right);
704694 CHECK_EXCEPTION();
705  auto rightNumeric = right.toNumeric(globalObject);
706  CHECK_EXCEPTION();
707 
708  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
709  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
710  JSBigInt* result = JSBigInt::divide(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
711  CHECK_EXCEPTION();
712  RETURN_WITH_PROFILING(result, {
713  updateArithProfileForBinaryArithOp(globalObject, codeBlock, pc, result, left, right);
714  });
715  }
716 
717  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in division."));
718  }
719 
720  double a = WTF::get<double>(leftNumeric);
721  double b = WTF::get<double>(rightNumeric);
722  JSValue result = jsNumber(a / b);
723695 RETURN_WITH_PROFILING(result, {
724696 updateArithProfileForBinaryArithOp(globalObject, codeBlock, pc, result, left, right);
725697 });

@@SLOW_PATH_DECL(slow_path_mod)
731703 auto bytecode = pc->as<OpMod>();
732704 JSValue left = GET_C(bytecode.m_lhs).jsValue();
733705 JSValue right = GET_C(bytecode.m_rhs).jsValue();
734  auto leftNumeric = left.toNumeric(globalObject);
735  CHECK_EXCEPTION();
736  auto rightNumeric = right.toNumeric(globalObject);
 706 JSValue result = jsRemainder(globalObject, left, right);
737707 CHECK_EXCEPTION();
738 
739  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
740  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
741  JSBigInt* result = JSBigInt::remainder(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
742  CHECK_EXCEPTION();
743  RETURN(result);
744  }
745 
746  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in remainder operation."));
747  }
748 
749  double a = WTF::get<double>(leftNumeric);
750  double b = WTF::get<double>(rightNumeric);
751  RETURN(jsNumber(jsMod(a, b)));
 708 RETURN(result);
752709}
753710
754711SLOW_PATH_DECL(slow_path_pow)

@@SLOW_PATH_DECL(slow_path_pow)
757714 auto bytecode = pc->as<OpPow>();
758715 JSValue left = GET_C(bytecode.m_lhs).jsValue();
759716 JSValue right = GET_C(bytecode.m_rhs).jsValue();
760  auto leftNumeric = left.toNumeric(globalObject);
761  CHECK_EXCEPTION();
762  auto rightNumeric = right.toNumeric(globalObject);
 717 JSValue result = jsPow(globalObject, left, right);
763718 CHECK_EXCEPTION();
764 
765  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
766  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
767  JSBigInt* result = JSBigInt::exponentiate(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
768  CHECK_EXCEPTION();
769  RETURN(result);
770  }
771 
772  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in exponentiation operation."));
773  }
774 
775  double a = WTF::get<double>(leftNumeric);
776  double b = WTF::get<double>(rightNumeric);
777 
778  RETURN(jsNumber(operationMathPow(a, b)));
 719 RETURN(result);
779720}
780721
781722SLOW_PATH_DECL(slow_path_lshift)

@@SLOW_PATH_DECL(slow_path_lshift)
784725 auto bytecode = pc->as<OpLshift>();
785726 JSValue left = GET_C(bytecode.m_lhs).jsValue();
786727 JSValue right = GET_C(bytecode.m_rhs).jsValue();
787  auto leftNumeric = left.toBigIntOrInt32(globalObject);
788  CHECK_EXCEPTION();
789  auto rightNumeric = right.toBigIntOrInt32(globalObject);
790  CHECK_EXCEPTION();
791728
792  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
793  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
794  JSBigInt* result = JSBigInt::leftShift(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
795  CHECK_EXCEPTION();
796  RETURN_PROFILED(result);
797  }
798 
799  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in left shift operation."));
800  }
801 
802  RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) << (WTF::get<int32_t>(rightNumeric) & 31)));
 729 JSValue result = jsLShift(globalObject, left, right);
 730 CHECK_EXCEPTION();
 731 RETURN_PROFILED(result);
803732}
804733
805734SLOW_PATH_DECL(slow_path_rshift)

@@SLOW_PATH_DECL(slow_path_rshift)
808737 auto bytecode = pc->as<OpRshift>();
809738 JSValue left = GET_C(bytecode.m_lhs).jsValue();
810739 JSValue right = GET_C(bytecode.m_rhs).jsValue();
811  auto leftNumeric = left.toBigIntOrInt32(globalObject);
812  CHECK_EXCEPTION();
813  auto rightNumeric = right.toBigIntOrInt32(globalObject);
814  CHECK_EXCEPTION();
815 
816  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
817  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
818  JSBigInt* result = JSBigInt::signedRightShift(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
819  CHECK_EXCEPTION();
820  RETURN_PROFILED(result);
821  }
822740
823  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in signed right shift operation."_s));
824  }
825 
826  RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) >> (WTF::get<int32_t>(rightNumeric) & 31)));
 741 JSValue result = jsRShift(globalObject, left, right);
 742 CHECK_EXCEPTION();
 743 RETURN_PROFILED(result);
827744}
828745
829746SLOW_PATH_DECL(slow_path_urshift)

@@SLOW_PATH_DECL(slow_path_bitnot)
849766{
850767 BEGIN();
851768 auto bytecode = pc->as<OpBitnot>();
852  auto operandNumeric = GET_C(bytecode.m_operand).jsValue().toBigIntOrInt32(globalObject);
853  CHECK_EXCEPTION();
854 
855  if (WTF::holds_alternative<JSBigInt*>(operandNumeric)) {
856  JSBigInt* result = JSBigInt::bitwiseNot(globalObject, WTF::get<JSBigInt*>(operandNumeric));
857  CHECK_EXCEPTION();
858  RETURN_PROFILED(result);
859  }
 769 auto operand = GET_C(bytecode.m_operand).jsValue();
860770
861  RETURN_PROFILED(jsNumber(~WTF::get<int32_t>(operandNumeric)));
 771 auto result = jsBitwiseNot(globalObject, operand);
 772 CHECK_EXCEPTION();
 773 RETURN_PROFILED(result);
862774}
863775
864776SLOW_PATH_DECL(slow_path_bitand)
865777{
866778 BEGIN();
867779 auto bytecode = pc->as<OpBitand>();
868  auto leftNumeric = GET_C(bytecode.m_lhs).jsValue().toBigIntOrInt32(globalObject);
869  CHECK_EXCEPTION();
870  auto rightNumeric = GET_C(bytecode.m_rhs).jsValue().toBigIntOrInt32(globalObject);
871  CHECK_EXCEPTION();
872  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
873  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
874  JSBigInt* result = JSBigInt::bitwiseAnd(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
875  CHECK_EXCEPTION();
876  RETURN_PROFILED(result);
877  }
878 
879  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in bitwise 'and' operation."));
880  }
 780 auto left = GET_C(bytecode.m_lhs).jsValue();
 781 auto right = GET_C(bytecode.m_rhs).jsValue();
881782
882  RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) & WTF::get<int32_t>(rightNumeric)));
 783 JSValue result = jsBitwiseAnd(globalObject, left, right);
 784 CHECK_EXCEPTION();
 785 RETURN_PROFILED(result);
883786}
884787
885788SLOW_PATH_DECL(slow_path_bitor)
886789{
887790 BEGIN();
888791 auto bytecode = pc->as<OpBitor>();
889  auto leftNumeric = GET_C(bytecode.m_lhs).jsValue().toBigIntOrInt32(globalObject);
890  CHECK_EXCEPTION();
891  auto rightNumeric = GET_C(bytecode.m_rhs).jsValue().toBigIntOrInt32(globalObject);
892  CHECK_EXCEPTION();
893  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
894  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
895  JSBigInt* result = JSBigInt::bitwiseOr(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
896  CHECK_EXCEPTION();
897  RETURN_PROFILED(result);
898  }
 792 auto left = GET_C(bytecode.m_lhs).jsValue();
 793 auto right = GET_C(bytecode.m_rhs).jsValue();
899794
900  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in bitwise 'or' operation."));
901  }
902 
903  RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) | WTF::get<int32_t>(rightNumeric)));
 795 JSValue result = jsBitwiseOr(globalObject, left, right);
 796 CHECK_EXCEPTION();
 797 RETURN_PROFILED(result);
904798}
905799
906800SLOW_PATH_DECL(slow_path_bitxor)
907801{
908802 BEGIN();
909803 auto bytecode = pc->as<OpBitxor>();
910  auto leftNumeric = GET_C(bytecode.m_lhs).jsValue().toBigIntOrInt32(globalObject);
911  CHECK_EXCEPTION();
912  auto rightNumeric = GET_C(bytecode.m_rhs).jsValue().toBigIntOrInt32(globalObject);
913  CHECK_EXCEPTION();
914  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
915  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
916  JSBigInt* result = JSBigInt::bitwiseXor(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
917  CHECK_EXCEPTION();
918  RETURN_PROFILED(result);
919  }
920 
921  THROW(createTypeError(globalObject, "Invalid mix of BigInt and other type in bitwise 'xor' operation."));
922  }
 804 auto left = GET_C(bytecode.m_lhs).jsValue();
 805 auto right = GET_C(bytecode.m_rhs).jsValue();
923806
924  RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) ^ WTF::get<int32_t>(rightNumeric)));
 807 JSValue result = jsBitwiseXor(globalObject, left, right);
 808 CHECK_EXCEPTION();
 809 RETURN_PROFILED(result);
925810}
926811
927812SLOW_PATH_DECL(slow_path_typeof)

Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp

@@static EncodedJSValue JSC_HOST_CALL IntlNumberFormatFuncFormat(JSGlobalObject* g
8787 auto scope = DECLARE_THROW_SCOPE(vm);
8888 auto* numberFormat = jsCast<IntlNumberFormat*>(callFrame->thisValue());
8989
90  auto variant = callFrame->argument(0).toNumeric(globalObject);
 90 JSValue bigIntOrNumber = callFrame->argument(0).toNumeric(globalObject);
9191 RETURN_IF_EXCEPTION(scope, encodedJSValue());
9292
93  RELEASE_AND_RETURN(scope, JSValue::encode(switchOn(variant, [&](auto&& value) {
94  return numberFormat->format(globalObject, value);
95  })));
 93 scope.release();
 94 if (bigIntOrNumber.isNumber()) {
 95 double value = bigIntOrNumber.asNumber();
 96 return JSValue::encode(numberFormat->format(globalObject, value));
 97 }
 98
 99#if USE(BIGINT32)
 100 if (bigIntOrNumber.isBigInt32()) {
 101 JSBigInt* value = JSBigInt::createFrom(vm, bigIntOrNumber.bigInt32AsInt32());
 102 return JSValue::encode(numberFormat->format(globalObject, value));
 103 }
 104#endif
 105
 106 ASSERT(bigIntOrNumber.isHeapBigInt());
 107 JSBigInt* value = bigIntOrNumber.asHeapBigInt();
 108 return JSValue::encode(numberFormat->format(globalObject, value));
96109}
97110
98111EncodedJSValue JSC_HOST_CALL IntlNumberFormatPrototypeGetterFormat(JSGlobalObject* globalObject, CallFrame* callFrame)

Source/JavaScriptCore/runtime/JSBigInt.cpp

11/*
22 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>
3  * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
 3 * Copyright (C) 2017-2020 Apple Inc. All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions

@@void JSBigInt::initialize(InitializationType initType)
8080
8181Structure* JSBigInt::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
8282{
83  return Structure::create(vm, globalObject, prototype, TypeInfo(BigIntType, StructureFlags), info());
 83 return Structure::create(vm, globalObject, prototype, TypeInfo(HeapBigIntType, StructureFlags), info());
8484}
8585
8686JSBigInt* JSBigInt::createZero(VM& vm)

@@JSBigInt* JSBigInt::createFrom(VM& vm, int64_t value)
142142{
143143 if (!value)
144144 return createZero(vm);
145 
146  if (sizeof(Digit) == 8) {
 145
 146 // This path is not just an optimization: because we do not call rightTrim at the end of this function,
 147 // it would be a bug to create a BigInt with length=2 in this case.
 148 if (sizeof(Digit) == 8 || (value <= INT_MAX && value >= INT_MIN)) {
147149 JSBigInt* bigInt = createWithLengthUnchecked(vm, 1);
148150 if (value < 0) {
149151 bigInt->setDigit(0, static_cast<Digit>(static_cast<uint64_t>(-(value + 1)) + 1));

@@JSValue JSBigInt::toPrimitive(JSGlobalObject*, PreferredPrimitiveType) const
188190 return const_cast<JSBigInt*>(this);
189191}
190192
191 Optional<uint8_t> JSBigInt::singleDigitValueForString()
192 {
193  if (isZero())
194  return 0;
195 
196  if (length() == 1 && !sign()) {
197  Digit rDigit = digit(0);
198  if (rDigit <= 9)
199  return static_cast<uint8_t>(rDigit);
200  }
201  return { };
202 }
203 
204 JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, StringView s, ErrorParseMode parserMode)
 193JSValue JSBigInt::parseInt(JSGlobalObject* globalObject, StringView s, ErrorParseMode parserMode)
205194{
206195 if (s.is8Bit())
207196 return parseInt(globalObject, s.characters8(), s.length(), parserMode);
208197 return parseInt(globalObject, s.characters16(), s.length(), parserMode);
209198}
210199
211 JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, StringView s, uint8_t radix, ErrorParseMode parserMode, ParseIntSign sign)
 200JSValue JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, StringView s, uint8_t radix, ErrorParseMode parserMode, ParseIntSign sign)
212201{
213202 if (s.is8Bit())
214203 return parseInt(globalObject, vm, s.characters8(), s.length(), 0, radix, parserMode, sign, ParseIntMode::DisallowEmptyString);
215204 return parseInt(globalObject, vm, s.characters16(), s.length(), 0, radix, parserMode, sign, ParseIntMode::DisallowEmptyString);
216205}
217206
218 JSBigInt* JSBigInt::stringToBigInt(JSGlobalObject* globalObject, StringView s)
 207JSValue JSBigInt::stringToBigInt(JSGlobalObject* globalObject, StringView s)
219208{
220209 return parseInt(globalObject, s, ErrorParseMode::IgnoreExceptions);
221210}

@@JSBigInt* JSBigInt::remainder(JSGlobalObject* globalObject, JSBigInt* x, JSBigIn
454443
455444JSBigInt* JSBigInt::inc(JSGlobalObject* globalObject, JSBigInt* x)
456445{
457  // FIXME: we can probably do something a fair bit more efficient here
458  VM& vm = globalObject->vm();
459  return add(globalObject, x, vm.bigIntConstantOne.get());
 446 if (!x->sign())
 447 return absoluteAddOne(globalObject, x, SignOption::Unsigned);
 448 JSBigInt* result = absoluteSubOne(globalObject, x, x->length());
 449 result->setSign(true);
 450 return result;
460451}
461452
462453JSBigInt* JSBigInt::dec(JSGlobalObject* globalObject, JSBigInt* x)
463454{
464  // FIXME: we can probably do something a fair bit more efficient here
465  VM& vm = globalObject->vm();
466  return sub(globalObject, x, vm.bigIntConstantOne.get());
 455 if (x->isZero()) {
 456 JSBigInt* result = createFrom(globalObject->vm(), 1);
 457 result->setSign(true);
 458 return result;
 459 }
 460 if (!x->sign())
 461 return absoluteSubOne(globalObject, x, x->length());
 462 return absoluteAddOne(globalObject, x, SignOption::Signed);
467463}
468464
469465JSBigInt* JSBigInt::add(JSGlobalObject* globalObject, JSBigInt* x, JSBigInt* y)

@@JSBigInt* JSBigInt::bitwiseAnd(JSGlobalObject* globalObject, JSBigInt* x, JSBigI
532528 if (x->sign())
533529 std::swap(x, y);
534530
535  // x & (-y) == x & ~(y-1) == x & ~(y-1)
 531 // x & (-y) == x & ~(y-1)
536532 JSBigInt* y1 = absoluteSubOne(globalObject, y, y->length());
537533 RETURN_IF_EXCEPTION(scope, nullptr);
538534 return absoluteAndNot(vm, x, y1);

@@String JSBigInt::toStringBasePowerOfTwo(VM& vm, JSGlobalObject* globalObject, JS
16441640String JSBigInt::toStringGeneric(VM& vm, JSGlobalObject* globalObject, JSBigInt* x, unsigned radix)
16451641{
16461642 // FIXME: [JSC] Revisit usage of Vector into JSBigInt::toString
1647  // https://bugs.webkit.org/show_bug.cgi?id=18067
 1643 // https://bugs.webkit.org/show_bug.cgi?id=180671
16481644 Vector<LChar> resultString;
16491645
16501646 ASSERT(radix >= 2 && radix <= 36);

@@bool JSBigInt::getPrimitiveNumber(JSGlobalObject* globalObject, double& number,
18021798}
18031799
18041800template <typename CharType>
1805 JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, CharType* data, unsigned length, ErrorParseMode errorParseMode)
 1801JSValue JSBigInt::parseInt(JSGlobalObject* globalObject, CharType* data, unsigned length, ErrorParseMode errorParseMode)
18061802{
18071803 VM& vm = globalObject->vm();
18081804

@@JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, CharType* data, unsi
18101806 while (p < length && isStrWhiteSpace(data[p]))
18111807 ++p;
18121808
1813  // Check Radix from frist characters
 1809 // Check Radix from first characters
18141810 if (static_cast<unsigned>(p) + 1 < static_cast<unsigned>(length) && data[p] == '0') {
18151811 if (isASCIIAlphaCaselessEqual(data[p + 1], 'b'))
18161812 return parseInt(globalObject, vm, data, length, p + 2, 2, errorParseMode, ParseIntSign::Unsigned, ParseIntMode::DisallowEmptyString);

@@JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, CharType* data, unsi
18241820
18251821 ParseIntSign sign = ParseIntSign::Unsigned;
18261822 if (p < length) {
1827  if (data[p] == '+')
1828  ++p;
1829  else if (data[p] == '-') {
 1823 if (data[p] == '-') {
18301824 sign = ParseIntSign::Signed;
18311825 ++p;
1832  }
 1826 } else if (data[p] == '+')
 1827 ++p;
18331828 }
18341829
1835  JSBigInt* result = parseInt(globalObject, vm, data, length, p, 10, errorParseMode, sign);
1836 
1837  if (result && !result->isZero())
1838  result->setSign(sign == ParseIntSign::Signed);
1839 
1840  return result;
 1830 return parseInt(globalObject, vm, data, length, p, 10, errorParseMode, sign);
18411831}
18421832
18431833template <typename CharType>
1844 JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode errorParseMode, ParseIntSign sign, ParseIntMode parseMode)
 1834JSValue JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode errorParseMode, ParseIntSign sign, ParseIntMode parseMode)
18451835{
18461836 ASSERT(length >= 0);
18471837 unsigned p = startIndex;

@@JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, CharType* dat
18521842 ASSERT(globalObject);
18531843 if (errorParseMode == ErrorParseMode::ThrowExceptions)
18541844 throwVMError(globalObject, scope, createSyntaxError(globalObject, "Failed to parse String to BigInt"));
1855  return nullptr;
 1845 return JSValue();
18561846 }
18571847
18581848 // Skipping leading zeros

@@JSBigInt* JSBigInt::parseInt(JSGlobalObject* globalObject, VM& vm, CharType* dat
18661856
18671857 length = endIndex + 1;
18681858
1869  if (p == length)
 1859 if (p == length) {
 1860#if USE(BIGINT32)
 1861 return JSValue(JSValue::JSBigInt32, 0);
 1862#else
18701863 return createZero(vm);
1871 
1872  unsigned limit0 = '0' + (radix < 10 ? radix : 10);
1873  unsigned limita = 'a' + (radix - 10);
1874  unsigned limitA = 'A' + (radix - 10);
1875 
1876  JSBigInt* result = allocateFor(globalObject, vm, radix, length - p);
1877  RETURN_IF_EXCEPTION(scope, nullptr);
1878  // result can still be null if we don't have access to global object, as allocateFor cannot throw an exception in that case.
1879  if (!result)
1880  return nullptr;
1881 
1882  result->initialize(InitializationType::WithZero);
1883 
1884  for (unsigned i = p; i < length; i++, p++) {
1885  uint32_t digit;
1886  if (data[i] >= '0' && data[i] < limit0)
1887  digit = data[i] - '0';
1888  else if (data[i] >= 'a' && data[i] < limita)
1889  digit = data[i] - 'a' + 10;
1890  else if (data[i] >= 'A' && data[i] < limitA)
1891  digit = data[i] - 'A' + 10;
1892  else
1893  break;
1894 
1895  result->inplaceMultiplyAdd(static_cast<Digit>(radix), static_cast<Digit>(digit));
 1864#endif
18961865 }
18971866
1898  result->setSign(sign == ParseIntSign::Signed ? true : false);
1899  if (p == length)
1900  return result->rightTrim(vm);
 1867 // The idea is to pick the largest number such that radix ** lengthLimitForBigInt32 <= INT32_MAX
 1868 unsigned lengthLimitForBigInt32;
 1869 switch (radix) {
 1870 case 2:
 1871 lengthLimitForBigInt32 = 30;
 1872 break;
 1873 case 8:
 1874 lengthLimitForBigInt32 = 10;
 1875 break;
 1876 case 10:
 1877 lengthLimitForBigInt32 = 9;
 1878 break;
 1879 case 16:
 1880 lengthLimitForBigInt32 = 7;
 1881 break;
 1882 default:
 1883 lengthLimitForBigInt32 = 1;
 1884 break;
 1885 }
 1886
 1887 JSBigInt* heapResult = nullptr;
19011888
1902  ASSERT(globalObject);
1903  if (errorParseMode == ErrorParseMode::ThrowExceptions)
1904  throwVMError(globalObject, scope, createSyntaxError(globalObject, "Failed to parse String to BigInt"));
 1889 unsigned limit0 = '0' + (radix < 10 ? radix : 10);
 1890 unsigned limita = 'a' + (static_cast<int32_t>(radix) - 10);
 1891 unsigned limitA = 'A' + (static_cast<int32_t>(radix) - 10);
 1892 unsigned initialLength = length - p;
 1893 while (p < length) {
 1894 int32_t digit = 0;
 1895 Checked<int32_t, CrashOnOverflow> multiplier = 1;
 1896 for (unsigned i = 0; i < lengthLimitForBigInt32 && p < length ; ++i, ++p) {
 1897 digit *= radix;
 1898 multiplier *= radix;
 1899 if (data[p] >= '0' && data[p] < limit0)
 1900 digit += data[p] - '0';
 1901 else if (data[p] >= 'a' && data[p] < limita)
 1902 digit += data[p] - 'a' + 10;
 1903 else if (data[p] >= 'A' && data[p] < limitA)
 1904 digit += data[p] - 'A' + 10;
 1905 else {
 1906 if (errorParseMode == ErrorParseMode::ThrowExceptions) {
 1907 ASSERT(globalObject);
 1908 throwVMError(globalObject, scope, createSyntaxError(globalObject, "Failed to parse String to BigInt"));
 1909 }
 1910 return JSValue();
 1911 }
 1912 }
 1913 ASSERT(digit < multiplier.unsafeGet());
 1914
 1915 if (!heapResult) {
 1916 if (p == length) {
 1917 if (sign == ParseIntSign::Signed)
 1918 digit *= -1;
 1919#if USE(BIGINT32)
 1920 return JSValue(JSValue::JSBigInt32, digit);
 1921#else
 1922 return createFrom(vm, static_cast<int64_t>(digit));
 1923#endif
 1924 }
 1925 heapResult = allocateFor(globalObject, vm, radix, initialLength);
 1926 RETURN_IF_EXCEPTION(scope, JSValue());
 1927 // result can still be null if we don't have access to global object, as allocateFor cannot throw an exception in that case.
 1928 if (!heapResult)
 1929 return JSValue();
 1930 heapResult->initialize(InitializationType::WithZero);
 1931 }
 1932 heapResult->inplaceMultiplyAdd(static_cast<Digit>(multiplier.unsafeGet()), static_cast<Digit>(digit));
 1933 }
19051934
1906  return nullptr;
 1935 heapResult->setSign(sign == ParseIntSign::Signed);
 1936 return heapResult->rightTrim(vm);
19071937}
19081938
19091939inline JSBigInt::Digit JSBigInt::digit(unsigned n)

@@bool JSBigInt::equalsToNumber(JSValue numValue)
19271957{
19281958 ASSERT(numValue.isNumber());
19291959
1930  if (numValue.isInt32()) {
1931  int value = numValue.asInt32();
1932  if (!value)
1933  return this->isZero();
1934 
1935  return (this->length() == 1) && (this->sign() == (value < 0)) && (this->digit(0) == static_cast<Digit>(std::abs(static_cast<int64_t>(value))));
1936  }
 1960 if (numValue.isInt32())
 1961 return equalsToInt32(numValue.asInt32());
19371962
19381963 double value = numValue.asDouble();
19391964 return compareToDouble(this, value) == ComparisonResult::Equal;
19401965}
19411966
 1967bool JSBigInt::equalsToInt32(int32_t value)
 1968{
 1969 if (!value)
 1970 return this->isZero();
 1971 return (this->length() == 1) && (this->sign() == (value < 0)) && (this->digit(0) == static_cast<Digit>(std::abs(static_cast<int64_t>(value))));
 1972}
 1973
19421974JSBigInt::ComparisonResult JSBigInt::compareToDouble(JSBigInt* x, double y)
19431975{
19441976 // This algorithm expect that the double format is IEEE 754

Source/JavaScriptCore/runtime/JSBigInt.h

11/*
22 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com>
3  * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 * Copyright (C) 2019-2020 Apple Inc. All rights reserved.
44 *
55 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions

@@public:
8282
8383 unsigned length() const { return m_length; }
8484
 85 static JSValue makeHeapBigIntOrBigInt32(VM& vm, int64_t value)
 86 {
 87#if USE(BIGINT32)
 88 if (value <= INT_MAX && value >= INT_MIN)
 89 return JSValue(JSValue::JSBigInt32, static_cast<int32_t>(value));
 90#endif
 91
 92 auto ptr = JSBigInt::createFrom(vm, value);
 93 return JSValue(static_cast<JSCell*>(ptr));
 94 }
 95
8596 enum class ErrorParseMode {
8697 ThrowExceptions,
8798 IgnoreExceptions

@@public:
90101 enum class ParseIntMode { DisallowEmptyString, AllowEmptyString };
91102 enum class ParseIntSign { Unsigned, Signed };
92103
93  static JSBigInt* parseInt(JSGlobalObject*, VM&, StringView, uint8_t radix, ErrorParseMode = ErrorParseMode::ThrowExceptions, ParseIntSign = ParseIntSign::Unsigned);
94  static JSBigInt* parseInt(JSGlobalObject*, StringView, ErrorParseMode = ErrorParseMode::ThrowExceptions);
95  static JSBigInt* stringToBigInt(JSGlobalObject*, StringView);
 104 static JSValue parseInt(JSGlobalObject*, VM&, StringView, uint8_t radix, ErrorParseMode = ErrorParseMode::ThrowExceptions, ParseIntSign = ParseIntSign::Unsigned);
 105 static JSValue parseInt(JSGlobalObject*, StringView, ErrorParseMode = ErrorParseMode::ThrowExceptions);
 106 static JSValue stringToBigInt(JSGlobalObject*, StringView);
96107
97108 static String tryGetString(VM&, JSBigInt*, unsigned radix);
98109
99  Optional<uint8_t> singleDigitValueForString();
100110 String toString(JSGlobalObject*, unsigned radix);
101111
102112 enum class ComparisonMode {

@@public:
113123
114124 JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*);
115125 bool equalsToNumber(JSValue);
 126 JS_EXPORT_PRIVATE bool equalsToInt32(int32_t);
116127 static ComparisonResult compare(JSBigInt* x, JSBigInt* y);
117128
118129 bool getPrimitiveNumber(JSGlobalObject*, double& number, JSValue& result) const;

@@private:
222233 }
223234
224235 template <typename CharType>
225  static JSBigInt* parseInt(JSGlobalObject*, CharType* data, unsigned length, ErrorParseMode);
 236 static JSValue parseInt(JSGlobalObject*, CharType* data, unsigned length, ErrorParseMode);
226237
227238 template <typename CharType>
228  static JSBigInt* parseInt(JSGlobalObject*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode, ParseIntSign = ParseIntSign::Signed, ParseIntMode = ParseIntMode::AllowEmptyString);
 239 static JSValue parseInt(JSGlobalObject*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode, ParseIntSign = ParseIntSign::Signed, ParseIntMode = ParseIntMode::AllowEmptyString);
229240
230241 static JSBigInt* allocateFor(JSGlobalObject*, VM&, unsigned radix, unsigned charcount);
231242

@@private:
258269 CagedUniquePtr<Gigacage::Primitive, Digit> m_data;
259270};
260271
261 inline JSBigInt* asBigInt(JSValue value)
 272inline JSBigInt* asHeapBigInt(JSValue value)
262273{
263  ASSERT(value.asCell()->isBigInt());
 274 ASSERT(value.asCell()->isHeapBigInt());
264275 return jsCast<JSBigInt*>(value.asCell());
265276}
266277

Source/JavaScriptCore/runtime/JSCJSValue.cpp

2323#include "config.h"
2424#include "JSCJSValue.h"
2525
 26#include "BigIntObject.h"
2627#include "BooleanConstructor.h"
2728#include "BooleanPrototype.h"
2829#include "CustomGetterSetter.h"

@@double JSValue::toNumberSlowCase(JSGlobalObject* globalObject) const
7172 ASSERT(!isInt32() && !isDouble());
7273 if (isCell())
7374 return asCell()->toNumber(globalObject);
 75#if USE(BIGINT32)
 76 if (isBigInt32()) {
 77 VM& vm = globalObject->vm();
 78 auto scope = DECLARE_THROW_SCOPE(vm);
 79 throwTypeError(globalObject, scope, "Conversion from 'BigInt' to 'number' is not allowed."_s);
 80 return 0.0;
 81 }
 82#endif
7483 if (isTrue())
7584 return 1.0;
7685 return isUndefined() ? PNaN : 0; // null and false both convert to 0.

@@JSObject* JSValue::toObjectSlowCase(JSGlobalObject* globalObject) const
101110 return constructNumber(globalObject, asValue());
102111 if (isTrue() || isFalse())
103112 return constructBooleanFromImmediateBoolean(globalObject, asValue());
 113#if USE(BIGINT32)
 114 if (isBigInt32())
 115 return BigIntObject::create(vm, globalObject, *this);
 116#endif
104117
105118 ASSERT(isUndefinedOrNull());
106119 throwException(globalObject, scope, createNotAnObjectError(globalObject, *this));

@@JSValue JSValue::toThisSlowCase(JSGlobalObject* globalObject, ECMAMode ecmaMode)
118131 return constructNumber(globalObject, asValue());
119132 if (isTrue() || isFalse())
120133 return constructBooleanFromImmediateBoolean(globalObject, asValue());
 134#if USE(BIGINT32)
 135 if (isBigInt32()) {
 136 JSCell* heapBigInt = static_cast<JSCell*>(JSBigInt::createFrom(globalObject->vm(), bigInt32AsInt32()));
 137 return heapBigInt->toObject(globalObject);
 138 }
 139#endif
 140
121141 ASSERT(isUndefinedOrNull());
122142 return globalObject->globalThis();
123143}

@@JSObject* JSValue::synthesizePrototype(JSGlobalObject* globalObject) const
130150 if (isCell()) {
131151 if (isString())
132152 return globalObject->stringPrototype();
133  if (isBigInt())
 153 if (isHeapBigInt())
134154 return globalObject->bigIntPrototype();
135155 ASSERT(isSymbol());
136156 return globalObject->symbolPrototype();

@@JSObject* JSValue::synthesizePrototype(JSGlobalObject* globalObject) const
140160 return globalObject->numberPrototype();
141161 if (isBoolean())
142162 return globalObject->booleanPrototype();
 163#if USE(BIGINT32)
 164 if (isBigInt32())
 165 return globalObject->bigIntPrototype();
 166#endif
143167
144168 ASSERT(isUndefinedOrNull());
145169 throwException(globalObject, scope, createNotAnObjectError(globalObject, *this));

@@void JSValue::dumpInContextAssumingStructure(
286310 out.print("Symbol: ", RawPointer(asCell()));
287311 else if (structure->classInfo()->isSubClassOf(Structure::info()))
288312 out.print("Structure: ", inContext(*jsCast<Structure*>(asCell()), context));
 313 else if (isHeapBigInt())
 314 out.print("BigInt[heap-allocated]: addr=", RawPointer(asCell()));
289315 else if (structure->classInfo()->isSubClassOf(JSObject::info())) {
290316 out.print("Object: ", RawPointer(asCell()));
291317 out.print(" with butterfly ", RawPointer(asObject(asCell())->butterfly()));

@@void JSValue::dumpInContextAssumingStructure(
305331 out.print("Null");
306332 else if (isUndefined())
307333 out.print("Undefined");
 334#if USE(BIGINT32)
 335 else if (isBigInt32())
 336 out.printf("BigInt[inline]: %d", bigInt32AsInt32());
 337#endif
308338 else
309339 out.print("INVALID");
310340}

@@void JSValue::dumpForBacktrace(PrintStream& out) const
347377 out.print("Null");
348378 else if (isUndefined())
349379 out.print("Undefined");
 380#if USE(BIGINT32)
 381 else if (isBigInt32())
 382 out.printf("BigInt[inline]: %d", bigInt32AsInt32());
 383#endif
350384 else
351385 out.print("INVALID");
352386}

@@JSString* JSValue::toStringSlowCase(JSGlobalObject* globalObject, bool returnEmp
384418 return vm.smallStrings.nullString();
385419 if (isUndefined())
386420 return vm.smallStrings.undefinedString();
387  if (isSymbol()) {
388  throwTypeError(globalObject, scope, "Cannot convert a symbol to a string"_s);
389  return errorValue();
 421#if USE(BIGINT32)
 422 if (isBigInt32()) {
 423 auto integer = bigInt32AsInt32();
 424 if (static_cast<unsigned>(integer) <= 9)
 425 return vm.smallStrings.singleCharacterString(integer + '0');
 426 return jsNontrivialString(vm, vm.numericStrings.add(integer));
390427 }
391  if (isBigInt()) {
392  JSBigInt* bigInt = asBigInt(*this);
393  if (auto digit = bigInt->singleDigitValueForString())
394  return vm.smallStrings.singleCharacterString(*digit + '0');
395  JSString* returnString = jsNontrivialString(vm, bigInt->toString(globalObject, 10));
 428#endif
 429 if (isHeapBigInt()) {
 430 JSBigInt* bigInt = asHeapBigInt();
 431 // FIXME: we should rather have two cases here: one-character string vs jsNonTrivialString for everything else.
 432 JSString* returnString = JSString::create(vm, bigInt->toString(globalObject, 10).releaseImpl().releaseNonNull());
396433 RETURN_IF_EXCEPTION(scope, errorValue());
397434 return returnString;
398435 }
 436 if (isSymbol()) {
 437 throwTypeError(globalObject, scope, "Cannot convert a symbol to a string"_s);
 438 return errorValue();
 439 }
399440
400441 ASSERT(isCell());
401442 JSValue value = asCell()->toPrimitive(globalObject, PreferString);

Source/JavaScriptCore/runtime/JSCJSValue.h

@@public:
177177 enum JSTrueTag { JSTrue };
178178 enum JSFalseTag { JSFalse };
179179 enum JSCellTag { JSCellType };
 180#if USE(BIGINT32)
 181 enum JSBigInt32Tag { JSBigInt32 };
 182#endif
180183 enum EncodeAsDoubleTag { EncodeAsDouble };
181184
182185 JSValue();

@@public:
186189 JSValue(JSFalseTag);
187190 JSValue(JSCell* ptr);
188191 JSValue(const JSCell* ptr);
 192#if USE(BIGINT32)
 193 JSValue(JSBigInt32Tag, int32_t);
 194#endif
189195
190196 // Numbers
191197 JSValue(EncodeAsDoubleTag, double);

@@public:
219225 double asDouble() const;
220226 bool asBoolean() const;
221227 double asNumber() const;
 228#if USE(BIGINT32)
 229 int32_t bigInt32AsInt32() const; // must only be called on a BigInt32
 230#endif
222231
223232 int32_t asInt32ForArithmetic() const; // Boolean becomes an int, but otherwise like asInt32().
224233

@@public:
238247 bool isNumber() const;
239248 bool isString() const;
240249 bool isBigInt() const;
 250 bool isHeapBigInt() const;
 251 bool isBigInt32() const;
241252 bool isSymbol() const;
242253 bool isPrimitive() const;
243254 bool isGetterSetter() const;

@@public:
246257 bool inherits(VM&, const ClassInfo*) const;
247258 template<typename Target> bool inherits(VM&) const;
248259 const ClassInfo* classInfoOrNull(VM&) const;
249 
 260
250261 // Extracting the value.
251262 bool getString(JSGlobalObject*, WTF::String&) const;
252263 WTF::String getString(JSGlobalObject*) const; // null string if not a string

@@public:
265276 // toNumber conversion is expected to be side effect free if an exception has
266277 // been set in the CallFrame already.
267278 double toNumber(JSGlobalObject*) const;
268 
269  Variant<JSBigInt*, double> toNumeric(JSGlobalObject*) const;
270  Variant<JSBigInt*, int32_t> toBigIntOrInt32(JSGlobalObject*) const;
 279
 280 JSValue toNumeric(JSGlobalObject*) const;
 281 JSValue toBigIntOrInt32(JSGlobalObject*) const;
 282 JSBigInt* asHeapBigInt() const;
271283
272284 // toNumber conversion if it can be done without side effects.
273285 Optional<double> toNumberFromPrimitive() const;

@@public:
316328 static bool equalSlowCase(JSGlobalObject*, JSValue v1, JSValue v2);
317329 static bool equalSlowCaseInline(JSGlobalObject*, JSValue v1, JSValue v2);
318330 static bool strictEqual(JSGlobalObject*, JSValue v1, JSValue v2);
319  static bool strictEqualSlowCase(JSGlobalObject*, JSValue v1, JSValue v2);
320  static bool strictEqualSlowCaseInline(JSGlobalObject*, JSValue v1, JSValue v2);
 331 static bool strictEqualForCells(JSGlobalObject*, JSCell* v1, JSCell* v2);
321332 static TriState pureStrictEqual(JSValue v1, JSValue v2);
322333
323334 bool isCell() const;

@@public:
415426 * These values have the following properties:
416427 * - Bit 1 (OtherTag) is set for all four values, allowing real pointers to be
417428 * quickly distinguished from all immediate values, including these invalid pointers.
418  * - With bit 3 is masked out (UndefinedTag) Undefined and Null share the
 429 * - With bit 3 masked out (UndefinedTag), Undefined and Null share the
419430 * same value, allowing null & undefined to be quickly detected.
420431 *
421432 * No valid JSValue will have the bit pattern 0x0, this is used to represent array
422433 * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
 434 *
 435 * When USE(BIGINT32), we have a special representation for BigInts that are small (32-bit at most):
 436 * 0000:XXXX:XXXX:0012
 437 * This representation works because of the following things:
 438 * - It cannot be confused with a Double or Integer thanks to the top bits
 439 * - It cannot be confused with a pointer to a Cell, thanks to bit 1 which is set to true
 440 * - It cannot be confused with a pointer to wasm thanks to bit 0 which is set to false
 441 * - It cannot be confused with true/false because bit 2 is set to false
 442 * - It cannot be confused for null/undefined because bit 4 is set to true
423443 */
424444
425445 // This value is 2^49, used to encode doubles such that the encoded value will begin

@@public:
429449 // If all bits in the mask are set, this indicates an integer number,
430450 // if any but not all are set this value is a double precision number.
431451 static constexpr int64_t NumberTag = 0xfffe000000000000ll;
 452 // The following constant is used for a trick in the implementation of strictEq, to detect if either of the arguments is a double
 453 static constexpr int64_t LowestOfHighBits = 1ULL << 49;
 454 static_assert(LowestOfHighBits & NumberTag);
 455 static_assert(!((LowestOfHighBits>>1) & NumberTag));
432456
433457 // All non-numeric (bool, null, undefined) immediates have bit 2 set.
434458 static constexpr int32_t OtherTag = 0x2;
435459 static constexpr int32_t BoolTag = 0x4;
436460 static constexpr int32_t UndefinedTag = 0x8;
 461#if USE(BIGINT32)
 462 static constexpr int32_t BigInt32Tag = 0x12;
 463 static constexpr int64_t BigInt32Mask = NumberTag | BigInt32Tag;
 464#endif
437465 // Combined integer value for non-numeric immediates.
438466 static constexpr int32_t ValueFalse = OtherTag | BoolTag | false;
439467 static constexpr int32_t ValueTrue = OtherTag | BoolTag | true;

Source/JavaScriptCore/runtime/JSCJSValueInlines.h

11/*
2  * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions

3838#include "JSProxy.h"
3939#include "JSStringInlines.h"
4040#include "MathCommon.h"
41 #include <wtf/Variant.h>
4241#include <wtf/text/StringImpl.h>
4342
4443namespace JSC {

@@ALWAYS_INLINE JSCell* JSValue::asCell() const
329328 return reinterpret_cast<JSCell*>(u.asBits.payload);
330329}
331330
 331ALWAYS_INLINE JSBigInt* JSValue::asHeapBigInt() const
 332{
 333 ASSERT(isHeapBigInt());
 334 return reinterpret_cast<JSBigInt*>(u.asBits.payload);
 335}
 336
332337ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
333338{
334339 ASSERT(!isImpureNaN(d));

@@ALWAYS_INLINE JSCell* JSValue::asCell() const
522527 return u.ptr;
523528}
524529
 530ALWAYS_INLINE JSBigInt* JSValue::asHeapBigInt() const
 531{
 532 ASSERT(isHeapBigInt());
 533 return static_cast<JSBigInt*>(u.ptr);
 534}
 535
525536#endif // USE(JSVALUE64)
526537
 538#if USE(BIGINT32)
 539inline JSValue::JSValue(JSBigInt32Tag, int32_t value)
 540{
 541 // The & ~NumberTag part is for negative numbers, otherwise they get sign-extended.
 542 u.asInt64 = ((static_cast<int64_t>(value) << 16) & ~NumberTag) | BigInt32Tag;
 543}
 544#endif // USE(BIGINT32)
 545
527546inline int64_t tryConvertToInt52(double number)
528547{
529548 if (number != number)

@@inline bool JSValue::isString() const
610629
611630inline bool JSValue::isBigInt() const
612631{
613  return isCell() && asCell()->isBigInt();
 632 return isBigInt32() || isHeapBigInt();
 633}
 634
 635inline bool JSValue::isHeapBigInt() const
 636{
 637 return isCell() && asCell()->isHeapBigInt();
 638}
 639
 640inline bool JSValue::isBigInt32() const
 641{
 642#if USE(BIGINT32)
 643 return (u.asInt64 & BigInt32Mask) == BigInt32Tag;
 644#else
 645 return false;
 646#endif
614647}
615648
 649#if USE(BIGINT32)
 650inline int32_t JSValue::bigInt32AsInt32() const
 651{
 652 ASSERT(isBigInt32());
 653 return static_cast<int32_t>(u.asInt64 >> 16);
 654}
 655#endif // USE(BIGINT32)
 656
616657inline bool JSValue::isSymbol() const
617658{
618659 return isCell() && asCell()->isSymbol();

@@inline bool JSValue::isSymbol() const
620661
621662inline bool JSValue::isPrimitive() const
622663{
623  return !isCell() || asCell()->isString() || asCell()->isSymbol() || asCell()->isBigInt();
 664 return !isCell() || asCell()->isString() || asCell()->isSymbol() || asCell()->isHeapBigInt();
624665}
625666
626667inline bool JSValue::isGetterSetter() const

@@inline bool JSValue::getPrimitiveNumber(JSGlobalObject* globalObject, double& nu
760801 value = *this;
761802 return true;
762803 }
763  ASSERT(isUndefined());
764  number = PNaN;
 804 if (isUndefined()) {
 805 number = PNaN;
 806 value = *this;
 807 return true;
 808 }
 809
 810 ASSERT(isBigInt32());
 811 VM& vm = globalObject->vm();
 812 auto scope = DECLARE_THROW_SCOPE(vm);
 813 throwTypeError(globalObject, scope, "Conversion from 'BigInt' to 'number' is not allowed."_s);
 814 number = 0.0;
765815 value = *this;
766816 return true;
767817}

@@ALWAYS_INLINE double JSValue::toNumber(JSGlobalObject* globalObject) const
775825 return toNumberSlowCase(globalObject);
776826}
777827
778 ALWAYS_INLINE Variant<JSBigInt*, double> JSValue::toNumeric(JSGlobalObject* globalObject) const
 828ALWAYS_INLINE JSValue JSValue::toNumeric(JSGlobalObject* globalObject) const
779829{
780  if (isInt32())
781  return asInt32();
782  if (isDouble())
783  return asDouble();
784  if (isBigInt())
785  return asBigInt(*this);
 830 if (isInt32() || isDouble() || isBigInt())
 831 return *this;
786832
787833 VM& vm = getVM(globalObject);
788834 auto scope = DECLARE_THROW_SCOPE(vm);
 835
789836 JSValue primValue = this->toPrimitive(globalObject, PreferNumber);
790  RETURN_IF_EXCEPTION(scope, 0);
791  if (primValue.isBigInt())
792  return asBigInt(primValue);
 837 RETURN_IF_EXCEPTION(scope, { });
 838
 839 if (primValue.isDouble() || primValue.isBigInt())
 840 return primValue;
 841
793842 double value = primValue.toNumber(globalObject);
794  RETURN_IF_EXCEPTION(scope, 0);
795  return value;
 843 RETURN_IF_EXCEPTION(scope, { });
 844
 845 return jsNumber(value);
796846}
797847
798 ALWAYS_INLINE Variant<JSBigInt*, int32_t> JSValue::toBigIntOrInt32(JSGlobalObject* globalObject) const
 848ALWAYS_INLINE JSValue JSValue::toBigIntOrInt32(JSGlobalObject* globalObject) const
799849{
800  if (isInt32())
801  return asInt32();
 850 if (isInt32() || isBigInt())
 851 return *this;
802852 if (isDouble() && canBeInt32(asDouble()))
803  return static_cast<int32_t>(asDouble());
804  if (isBigInt())
805  return asBigInt(*this);
 853 return jsNumber(static_cast<int32_t>(asDouble()));
806854
807855 VM& vm = getVM(globalObject);
808856 auto scope = DECLARE_THROW_SCOPE(vm);
 857
809858 JSValue primValue = this->toPrimitive(globalObject, PreferNumber);
810  RETURN_IF_EXCEPTION(scope, 0);
811  if (primValue.isBigInt())
812  return asBigInt(primValue);
 859 RETURN_IF_EXCEPTION(scope, { });
 860
 861 if (primValue.isInt32() || primValue.isBigInt())
 862 return primValue;
 863
813864 int32_t value = primValue.toInt32(globalObject);
814  RETURN_IF_EXCEPTION(scope, 0);
815  return value;
 865 RETURN_IF_EXCEPTION(scope, { });
 866 return jsNumber(value);
816867}
817868
818869inline JSObject* JSValue::toObject(JSGlobalObject* globalObject) const

@@ALWAYS_INLINE bool JSValue::equalSlowCaseInline(JSGlobalObject* globalObject, JS
10321083 VM& vm = getVM(globalObject);
10331084 auto scope = DECLARE_THROW_SCOPE(vm);
10341085 do {
1035  if (v1.isNumber() && v2.isNumber())
1036  return v1.asNumber() == v2.asNumber();
1037 
1038  bool s1 = v1.isString();
1039  bool s2 = v2.isString();
1040  if (s1 && s2)
1041  RELEASE_AND_RETURN(scope, asString(v1)->equal(globalObject, asString(v2)));
1042 
1043  if (v1.isBigInt() && s2) {
1044  String v2String = asString(v2)->value(globalObject);
1045  RETURN_IF_EXCEPTION(scope, false);
1046  JSBigInt* n = JSBigInt::stringToBigInt(globalObject, v2String);
1047  RETURN_IF_EXCEPTION(scope, false);
1048  if (!n)
1049  return false;
1050 
1051  v2 = JSValue(n);
1052  continue;
 1086 if (v1.isNumber()) {
 1087 if (v2.isNumber())
 1088 return v1.asNumber() == v2.asNumber();
 1089 // Guaranteeing that if we have a number it is v2 makes some of the cases below simpler.
 1090 std::swap(v1, v2);
10531091 }
10541092
1055  if (s1 && v2.isBigInt()) {
1056  String v1String = asString(v1)->value(globalObject);
1057  RETURN_IF_EXCEPTION(scope, false);
1058  JSBigInt* n = JSBigInt::stringToBigInt(globalObject, v1String);
1059  RETURN_IF_EXCEPTION(scope, false);
1060  if (!n)
1061  return false;
1062 
1063  v1 = JSValue(n);
1064  continue;
1065  }
 1093 // This deals with Booleans, BigInt32, Objects, and is a shortcut for a few more types.
 1094 // It has to come here and not before, because it is NOT true that NaN == NaN
 1095 if (v1 == v2)
 1096 return true;
10661097
10671098 if (v1.isUndefinedOrNull()) {
10681099 if (v2.isUndefinedOrNull())

@@ALWAYS_INLINE bool JSValue::equalSlowCaseInline(JSGlobalObject* globalObject, JS
10801111
10811112 if (v1.isObject()) {
10821113 if (v2.isObject())
1083  return v1 == v2;
 1114 return false; // v1 == v2 is already dealt with previously
10841115 JSValue p1 = v1.toPrimitive(globalObject);
10851116 RETURN_IF_EXCEPTION(scope, false);
10861117 v1 = p1;

@@ALWAYS_INLINE bool JSValue::equalSlowCaseInline(JSGlobalObject* globalObject, JS
11021133 bool sym2 = v2.isSymbol();
11031134 if (sym1 || sym2) {
11041135 if (sym1 && sym2)
1105  return asSymbol(v1) == asSymbol(v2);
 1136 return false; // v1 == v2 is already dealt with previously
11061137 return false;
11071138 }
11081139
 1140 bool s1 = v1.isString();
 1141 bool s2 = v2.isString();
 1142 if (s1) {
 1143 if (s2)
 1144 RELEASE_AND_RETURN(scope, asString(v1)->equal(globalObject, asString(v2)));
 1145 std::swap(v1, v2);
 1146 // We are guaranteed to enter the next case, so losing the invariant of only v2 being a number is fine
 1147 }
11091148 if (s1 || s2) {
1110  double d1 = v1.toNumber(globalObject);
1111  RETURN_IF_EXCEPTION(scope, false);
1112  double d2 = v2.toNumber(globalObject);
1113  RETURN_IF_EXCEPTION(scope, false);
1114  return d1 == d2;
 1149 // We are guaranteed that the string is v2 (thanks to the swap above)
 1150 if (v1.isBigInt()) {
 1151 String v2String = asString(v2)->value(globalObject);
 1152 RETURN_IF_EXCEPTION(scope, false);
 1153 v2 = JSBigInt::stringToBigInt(globalObject, v2String);
 1154 RETURN_IF_EXCEPTION(scope, false);
 1155 if (!v2)
 1156 return false;
 1157 if (v1 == v2)
 1158 return true; // For BigInt32
 1159 // We fallthrough to the generic code for comparing BigInts (which is only missing the BigInt32/BigInt32 case, hence the check above)
 1160 } else {
 1161 ASSERT(v1.isNumber() || v1.isBoolean());
 1162 double d1 = v1.toNumber(globalObject);
 1163 RETURN_IF_EXCEPTION(scope, false);
 1164 double d2 = v2.toNumber(globalObject);
 1165 RETURN_IF_EXCEPTION(scope, false);
 1166 return d1 == d2;
 1167 }
11151168 }
11161169
11171170 if (v1.isBoolean()) {
11181171 if (v2.isNumber())
11191172 return static_cast<double>(v1.asBoolean()) == v2.asNumber();
1120  else if (v2.isBigInt()) {
1121  v1 = JSValue(v1.toNumber(globalObject));
1122  continue;
1123  }
 1173 v1 = JSValue(v1.toNumber(globalObject));
 1174 // We fallthrough to the BigInt/Number comparison below
 1175 // We just need one more swap to repair the rule that only v2 is allowed to be a number in these comparisons
 1176 std::swap(v1, v2);
11241177 } else if (v2.isBoolean()) {
1125  if (v1.isNumber())
1126  return v1.asNumber() == static_cast<double>(v2.asBoolean());
1127  else if (v1.isBigInt()) {
1128  v2 = JSValue(v2.toNumber(globalObject));
1129  continue;
1130  }
 1178 v2 = JSValue(v2.toNumber(globalObject));
 1179 // We fallthrough to the BigInt/Number comparison below
11311180 }
1132 
1133  if (v1.isBigInt() && v2.isBigInt())
1134  return JSBigInt::equals(asBigInt(v1), asBigInt(v2));
1135 
1136  if (v1.isBigInt() && v2.isNumber())
1137  return asBigInt(v1)->equalsToNumber(v2);
11381181
1139  if (v2.isBigInt() && v1.isNumber())
1140  return asBigInt(v2)->equalsToNumber(v1);
 1182#if USE(BIGINT32)
 1183 if (v1.isBigInt32()) {
 1184 if (v2.isInt32())
 1185 return v1.bigInt32AsInt32() == v2.asInt32();
 1186 if (v2.isDouble())
 1187 return static_cast<double>(v1.bigInt32AsInt32()) == v2.asDouble();
 1188 std::swap(v1, v2);
 1189 }
 1190#endif // USE(BIGINT32)
 1191
 1192 if (v1.isHeapBigInt()) {
 1193 if (v2.isHeapBigInt())
 1194 return JSBigInt::equals(v1.asHeapBigInt(), v2.asHeapBigInt());
 1195#if USE(BIGINT32)
 1196 if (v2.isBigInt32())
 1197 return v1.asHeapBigInt()->equalsToInt32(v2.bigInt32AsInt32());
 1198#endif // USE(BIGINT32)
 1199 if (v2.isNumber())
 1200 return v1.asHeapBigInt()->equalsToNumber(v2);
 1201 }
11411202
1142  return v1 == v2;
 1203 return false;
11431204 } while (true);
11441205}
11451206
11461207// ECMA 11.9.3
1147 ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 1208ALWAYS_INLINE bool JSValue::strictEqualForCells(JSGlobalObject* globalObject, JSCell* v1, JSCell* v2)
11481209{
1149  ASSERT(v1.isCell() && v2.isCell());
1150 
1151  if (v1.asCell()->isString() && v2.asCell()->isString())
 1210 if (v1->isString() && v2->isString())
11521211 return asString(v1)->equal(globalObject, asString(v2));
1153  if (v1.isBigInt() && v2.isBigInt())
1154  return JSBigInt::equals(asBigInt(v1), asBigInt(v2));
 1212 if (v1->isHeapBigInt() && v2->isHeapBigInt())
 1213 return JSBigInt::equals(static_cast<JSBigInt*>(v1), static_cast<JSBigInt*>(v2));
11551214 return v1 == v2;
11561215}
11571216

@@inline bool JSValue::strictEqual(JSGlobalObject* globalObject, JSValue v1, JSVal
11631222 if (v1.isNumber() && v2.isNumber())
11641223 return v1.asNumber() == v2.asNumber();
11651224
1166  if (!v1.isCell() || !v2.isCell())
1167  return v1 == v2;
 1225#if USE(BIGINT32)
 1226 if (v1.isHeapBigInt() && v2.isBigInt32())
 1227 return v1.asHeapBigInt()->equalsToInt32(v2.bigInt32AsInt32());
 1228 if (v1.isBigInt32() && v2.isHeapBigInt())
 1229 return v2.asHeapBigInt()->equalsToInt32(v1.bigInt32AsInt32());
 1230#endif
 1231
 1232 if (v1.isCell() && v2.isCell())
 1233 return strictEqualForCells(globalObject, v1.asCell(), v2.asCell());
11681234
1169  return strictEqualSlowCaseInline(globalObject, v1, v2);
 1235 return v1 == v2;
11701236}
11711237
11721238inline int32_t JSValue::asInt32ForArithmetic() const

@@inline TriState JSValue::pureStrictEqual(JSValue v1, JSValue v2)
11841250 if (v1.isNumber() && v2.isNumber())
11851251 return triState(v1.asNumber() == v2.asNumber());
11861252
1187  if (!v1.isCell() || !v2.isCell())
1188  return triState(v1 == v2);
1189 
1190  if (v1.asCell()->isString() && v2.asCell()->isString()) {
1191  const StringImpl* v1String = asString(v1)->tryGetValueImpl();
1192  const StringImpl* v2String = asString(v2)->tryGetValueImpl();
1193  if (!v1String || !v2String)
1194  return MixedTriState;
1195  return triState(WTF::equal(*v1String, *v2String));
 1253#if USE(BIGINT32)
 1254 if (v1.isHeapBigInt() && v2.isBigInt32())
 1255 return triState(v1.asHeapBigInt()->equalsToInt32(v2.bigInt32AsInt32()));
 1256 if (v1.isBigInt32() && v2.isHeapBigInt())
 1257 return triState(v2.asHeapBigInt()->equalsToInt32(v1.bigInt32AsInt32()));
 1258#endif
 1259
 1260 if (v1.isCell() && v2.isCell()) {
 1261 if (v1.asCell()->isString() && v2.asCell()->isString()) {
 1262 const StringImpl* v1String = asString(v1)->tryGetValueImpl();
 1263 const StringImpl* v2String = asString(v2)->tryGetValueImpl();
 1264 if (!v1String || !v2String)
 1265 return MixedTriState;
 1266 return triState(WTF::equal(*v1String, *v2String));
 1267 }
 1268 if (v1.asCell()->isHeapBigInt() && v2.asCell()->isHeapBigInt())
 1269 return triState(JSBigInt::equals(v1.asHeapBigInt(), v2.asHeapBigInt()));
11961270 }
11971271
11981272 return triState(v1 == v2);

@@inline TriState JSValue::pureToBoolean() const
12061280 return isNotZeroAndOrdered(asDouble()) ? TrueTriState : FalseTriState; // false for NaN
12071281 if (isCell())
12081282 return asCell()->pureToBoolean();
 1283#if USE(BIGINT32)
 1284 if (isBigInt32())
 1285 return bigInt32AsInt32() ? TrueTriState : FalseTriState;
 1286#endif
12091287 return isTrue() ? TrueTriState : FalseTriState;
12101288}
12111289

Source/JavaScriptCore/runtime/JSCell.cpp

@@ConstructType JSCell::getConstructData(JSCell*, ConstructData& constructData)
113113
114114bool JSCell::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName identifier, JSValue value, PutPropertySlot& slot)
115115{
116  if (cell->isString() || cell->isSymbol() || cell->isBigInt())
 116 if (cell->isString() || cell->isSymbol() || cell->isHeapBigInt())
117117 return JSValue(cell).putToPrimitive(globalObject, identifier, value, slot);
118118
119119 JSObject* thisObject = cell->toObject(globalObject);

@@bool JSCell::put(JSCell* cell, JSGlobalObject* globalObject, PropertyName identi
123123bool JSCell::putByIndex(JSCell* cell, JSGlobalObject* globalObject, unsigned identifier, JSValue value, bool shouldThrow)
124124{
125125 VM& vm = globalObject->vm();
126  if (cell->isString() || cell->isSymbol() || cell->isBigInt()) {
 126 if (cell->isString() || cell->isSymbol() || cell->isHeapBigInt()) {
127127 PutPropertySlot slot(cell, shouldThrow);
128128 return JSValue(cell).putToPrimitive(globalObject, Identifier::from(vm, identifier), value, slot);
129129 }

@@JSValue JSCell::toPrimitive(JSGlobalObject* globalObject, PreferredPrimitiveType
163163 return static_cast<const JSString*>(this)->toPrimitive(globalObject, preferredType);
164164 if (isSymbol())
165165 return static_cast<const Symbol*>(this)->toPrimitive(globalObject, preferredType);
166  if (isBigInt())
 166 if (isHeapBigInt())
167167 return static_cast<const JSBigInt*>(this)->toPrimitive(globalObject, preferredType);
168168 return static_cast<const JSObject*>(this)->toPrimitive(globalObject, preferredType);
169169}

@@bool JSCell::getPrimitiveNumber(JSGlobalObject* globalObject, double& number, JS
174174 return static_cast<const JSString*>(this)->getPrimitiveNumber(globalObject, number, value);
175175 if (isSymbol())
176176 return static_cast<const Symbol*>(this)->getPrimitiveNumber(globalObject, number, value);
177  if (isBigInt())
 177 if (isHeapBigInt())
178178 return static_cast<const JSBigInt*>(this)->getPrimitiveNumber(globalObject, number, value);
179179 return static_cast<const JSObject*>(this)->getPrimitiveNumber(globalObject, number, value);
180180}

@@double JSCell::toNumber(JSGlobalObject* globalObject) const
185185 return static_cast<const JSString*>(this)->toNumber(globalObject);
186186 if (isSymbol())
187187 return static_cast<const Symbol*>(this)->toNumber(globalObject);
188  if (isBigInt())
 188 if (isHeapBigInt())
189189 return static_cast<const JSBigInt*>(this)->toNumber(globalObject);
190190 return static_cast<const JSObject*>(this)->toNumber(globalObject);
191191}

@@JSObject* JSCell::toObjectSlow(JSGlobalObject* globalObject) const
196196 ASSERT(!isObject());
197197 if (isString())
198198 return static_cast<const JSString*>(this)->toObject(globalObject);
199  if (isBigInt())
 199 if (isHeapBigInt())
200200 return static_cast<const JSBigInt*>(this)->toObject(globalObject);
201201 ASSERT(isSymbol());
202202 return static_cast<const Symbol*>(this)->toObject(globalObject);

Source/JavaScriptCore/runtime/JSCell.h

@@protected:
101101public:
102102 // Querying the type.
103103 bool isString() const;
104  bool isBigInt() const;
 104 bool isHeapBigInt() const;
105105 bool isSymbol() const;
106106 bool isObject() const;
107107 bool isGetterSetter() const;

Source/JavaScriptCore/runtime/JSCellInlines.h

@@inline bool JSCell::isString() const
204204 return m_type == StringType;
205205}
206206
207 inline bool JSCell::isBigInt() const
 207inline bool JSCell::isHeapBigInt() const
208208{
209  return m_type == BigIntType;
 209 return m_type == HeapBigIntType;
210210}
211211
212212inline bool JSCell::isSymbol() const

@@inline bool JSCell::toBoolean(JSGlobalObject* globalObject) const
340340{
341341 if (isString())
342342 return static_cast<const JSString*>(this)->toBoolean();
343  if (isBigInt())
 343 if (isHeapBigInt())
344344 return static_cast<const JSBigInt*>(this)->toBoolean();
345345 return !structure(getVM(globalObject))->masqueradesAsUndefined(globalObject);
346346}

@@inline TriState JSCell::pureToBoolean() const
349349{
350350 if (isString())
351351 return static_cast<const JSString*>(this)->toBoolean() ? TrueTriState : FalseTriState;
352  if (isBigInt())
 352 if (isHeapBigInt())
353353 return static_cast<const JSBigInt*>(this)->toBoolean() ? TrueTriState : FalseTriState;
354354 if (isSymbol())
355355 return TrueTriState;

Source/JavaScriptCore/runtime/JSString.h

@@inline bool JSValue::toBoolean(JSGlobalObject* globalObject) const
10381038 return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN
10391039 if (isCell())
10401040 return asCell()->toBoolean(globalObject);
 1041#if USE(BIGINT32)
 1042 if (isBigInt32())
 1043 return !!bigInt32AsInt32();
 1044#endif
10411045 return isTrue(); // false, null, and undefined all convert to false.
10421046}
10431047

Source/JavaScriptCore/runtime/JSType.cpp

@@void printInternal(PrintStream& out, JSC::JSType type)
4343 CASE(CellType)
4444 CASE(StringType)
4545 CASE(SymbolType)
46  CASE(BigIntType)
 46 CASE(HeapBigIntType)
4747 CASE(CustomGetterSetterType)
4848 CASE(APIValueWrapperType)
4949 CASE(NativeExecutableType)

Source/JavaScriptCore/runtime/JSType.h

@@enum JSType : uint8_t {
2626 // The CellType value must come before any JSType that is a JSCell.
2727 CellType,
2828 StringType,
29  BigIntType,
30  LastMaybeFalsyCellPrimitive = BigIntType,
 29 HeapBigIntType,
 30 LastMaybeFalsyCellPrimitive = HeapBigIntType,
3131 SymbolType,
3232
3333 GetterSetterType,

Source/JavaScriptCore/runtime/JSTypeInfo.h

@@private:
134134 bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
135135 bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
136136
137  uint8_t m_type;
 137 JSType m_type;
138138 uint8_t m_flags;
139139 uint16_t m_flags2;
140140};

Source/JavaScriptCore/runtime/ObjectInitializationScope.cpp

2626#include "config.h"
2727#include "ObjectInitializationScope.h"
2828
29 #include "JSCInlines.h"
3029#include "JSObject.h"
31 #include "Operations.h"
 30#include "Scribble.h"
3231
3332namespace JSC {
3433

Source/JavaScriptCore/runtime/Operations.cpp

11/*
22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
 3 * Copyright (C) 2008-2020 Apple Inc. All Rights Reserved.
44 *
55 * This library is free software; you can redistribute it and/or
66 * modify it under the terms of the GNU Library General Public

@@bool JSValue::equalSlowCase(JSGlobalObject* globalObject, JSValue v1, JSValue v2
3636 return equalSlowCaseInline(globalObject, v1, v2);
3737}
3838
39 bool JSValue::strictEqualSlowCase(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
40 {
41  return strictEqualSlowCaseInline(globalObject, v1, v2);
42 }
43 
4439NEVER_INLINE JSValue jsAddSlowCase(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
4540{
4641 // exception for the Date exception in defaultValue()

@@NEVER_INLINE JSValue jsAddSlowCase(JSGlobalObject* globalObject, JSValue v1, JSV
7368 RELEASE_AND_RETURN(scope, jsString(globalObject, p1String, asString(p2)));
7469 }
7570
76  auto leftNumeric = p1.toNumeric(globalObject);
77  RETURN_IF_EXCEPTION(scope, { });
78  auto rightNumeric = p2.toNumeric(globalObject);
79  RETURN_IF_EXCEPTION(scope, { });
80 
81  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
82  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
83  scope.release();
84  return JSBigInt::add(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
85  }
86 
87  return throwTypeError(globalObject, scope, "Invalid mix of BigInt and other type in addition."_s);
88  }
89 
90  return jsNumber(WTF::get<double>(leftNumeric) + WTF::get<double>(rightNumeric));
 71 auto doubleOp = [] (double left, double right) -> double {
 72 return left + right;
 73 };
 74 auto bigInt32Op = [] (int32_t left, int32_t right) -> JSValue {
 75#if USE(BIGINT32)
 76 Checked<int32_t, RecordOverflow> result = left;
 77 result += right;
 78 if (UNLIKELY(result.hasOverflowed()))
 79 return JSValue();
 80 return JSValue(JSValue::JSBigInt32, result.unsafeGet());
 81#else
 82 UNUSED_PARAM(left);
 83 UNUSED_PARAM(right);
 84 RELEASE_ASSERT_NOT_REACHED();
 85#endif
 86 };
 87 RELEASE_AND_RETURN(scope, arithmeticBinaryOp(globalObject, p1, p2, JSBigInt::add, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in addition."_s));
9188}
9289
9390JSValue jsTypeStringForValue(VM& vm, JSGlobalObject* globalObject, JSValue v)

@@bool jsIsObjectTypeOrNull(JSGlobalObject* globalObject, JSValue v)
128125 return v.isNull();
129126
130127 JSType type = v.asCell()->type();
131  if (type == StringType || type == SymbolType || type == BigIntType)
 128 if (type == StringType || type == SymbolType || type == HeapBigIntType)
132129 return false;
133130 if (type >= ObjectType) {
134131 if (asObject(v)->structure(vm)->masqueradesAsUndefined(globalObject))

Source/JavaScriptCore/runtime/Operations.h

11/*
22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3  * Copyright (C) 2002-2019 Apple Inc. All rights reserved.
 3 * Copyright (C) 2002-2020 Apple Inc. All rights reserved.
44 *
55 * This library is free software; you can redistribute it and/or
66 * modify it under the terms of the GNU Library General Public

2525#include "ExceptionHelpers.h"
2626#include "JSBigInt.h"
2727#include "JSCJSValueInlines.h"
28 #include <wtf/Variant.h>
2928
3029namespace JSC {
3130

@@ALWAYS_INLINE JSValue jsStringFromRegisterArray(JSGlobalObject* globalObject, Re
239238 return ropeBuilder.release();
240239}
241240
 241ALWAYS_INLINE JSBigInt::ComparisonResult compareBigIntToOtherPrimitive(JSGlobalObject* globalObject, JSBigInt* v1, JSValue primValue)
 242{
 243 ASSERT(primValue.isPrimitive());
 244 ASSERT(!primValue.isBigInt());
 245
 246 VM& vm = globalObject->vm();
 247 auto scope = DECLARE_THROW_SCOPE(vm);
 248
 249 if (primValue.isString()) {
 250 JSValue bigIntValue = JSBigInt::stringToBigInt(globalObject, asString(primValue)->value(globalObject));
 251 RETURN_IF_EXCEPTION(scope, JSBigInt::ComparisonResult::Undefined);
 252 if (!bigIntValue)
 253 return JSBigInt::ComparisonResult::Undefined;
 254
 255 if (bigIntValue.isHeapBigInt())
 256 return JSBigInt::compare(v1, bigIntValue.asHeapBigInt());
 257
 258 ASSERT(bigIntValue.isBigInt32());
 259#if USE(BIGINT32)
 260 // FIXME: use something less hacky, e.g. some kind of JSBigInt::compareToInt32
 261 return JSBigInt::compareToDouble(v1, static_cast<double>(bigIntValue.bigInt32AsInt32()));
 262#endif
 263 }
 264
 265 double numberValue = primValue.toNumber(globalObject);
 266 RETURN_IF_EXCEPTION(scope, JSBigInt::ComparisonResult::Undefined);
 267 return JSBigInt::compareToDouble(v1, numberValue);
 268}
 269
242270ALWAYS_INLINE bool bigIntCompareResult(JSBigInt::ComparisonResult comparisonResult, JSBigInt::ComparisonMode comparisonMode)
243271{
244272 if (comparisonMode == JSBigInt::ComparisonMode::LessThan)

@@ALWAYS_INLINE bool bigIntCompare(JSGlobalObject* globalObject, JSValue v1, JSVal
255283
256284 VM& vm = globalObject->vm();
257285 auto scope = DECLARE_THROW_SCOPE(vm);
258 
259  if (v1.isBigInt() && v2.isBigInt())
260  return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), asBigInt(v2)), comparisonMode);
261 
262  if (v1.isBigInt()) {
263  JSValue primValue = v2;
264  if (primValue.isString()) {
265  JSBigInt* bigIntValue = JSBigInt::stringToBigInt(globalObject, asString(primValue)->value(globalObject));
266  RETURN_IF_EXCEPTION(scope, false);
267  if (!bigIntValue)
268  return false;
269 
270  return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), bigIntValue), comparisonMode);
271  }
272286
273  if (primValue.isBigInt())
274  return bigIntCompareResult(JSBigInt::compare(asBigInt(v1), asBigInt(primValue)), comparisonMode);
275 
276  double numberValue = primValue.toNumber(globalObject);
277  RETURN_IF_EXCEPTION(scope, false);
278  return bigIntCompareResult(JSBigInt::compareToDouble(asBigInt(v1), numberValue), comparisonMode);
 287#if USE(BIGINT32)
 288 if (v1.isBigInt32() && v2.isBigInt32()) {
 289 if (comparisonMode == JSBigInt::ComparisonMode::LessThan)
 290 return v1.bigInt32AsInt32() < v2.bigInt32AsInt32();
 291 ASSERT(comparisonMode == JSBigInt::ComparisonMode::LessThanOrEqual);
 292 return v1.bigInt32AsInt32() <= v2.bigInt32AsInt32();
279293 }
280 
281  JSValue primValue = v1;
282  if (primValue.isString()) {
283  JSBigInt* bigIntValue = JSBigInt::stringToBigInt(globalObject, asString(primValue)->value(globalObject));
 294#endif
 295
 296 JSBigInt* v1HeapBigInt = nullptr;
 297 JSBigInt* v2HeapBigInt = nullptr;
 298 // FIXME: have some fast-ish path for a comparison between a small and a large big-int
 299 if (v1.isHeapBigInt())
 300 v1HeapBigInt = v1.asHeapBigInt();
 301#if USE(BIGINT32)
 302 else if (v1.isBigInt32())
 303 v1HeapBigInt = JSBigInt::createFrom(vm, v1.bigInt32AsInt32());
 304#endif
 305
 306 if (v2.isHeapBigInt())
 307 v2HeapBigInt = v2.asHeapBigInt();
 308#if USE(BIGINT32)
 309 else if (v2.isBigInt32())
 310 v2HeapBigInt = JSBigInt::createFrom(vm, v2.bigInt32AsInt32());
 311#endif
 312
 313 if (v1HeapBigInt && v2HeapBigInt)
 314 return bigIntCompareResult(JSBigInt::compare(v1HeapBigInt, v2HeapBigInt), comparisonMode);
 315
 316 if (v1HeapBigInt) {
 317 auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v1HeapBigInt, v2);
284318 RETURN_IF_EXCEPTION(scope, false);
285  if (!bigIntValue)
286  return false;
287 
288  return bigIntCompareResult(JSBigInt::compare(bigIntValue, asBigInt(v2)), comparisonMode);
 319 return bigIntCompareResult(comparisonResult, comparisonMode);
289320 }
290 
291  if (primValue.isBigInt())
292  return bigIntCompareResult(JSBigInt::compare(asBigInt(primValue), asBigInt(v2)), comparisonMode);
293 
294  double numberValue = primValue.toNumber(globalObject);
295  RETURN_IF_EXCEPTION(scope, false);
296321
 322 auto comparisonResult = compareBigIntToOtherPrimitive(globalObject, v2HeapBigInt, v1);
 323 RETURN_IF_EXCEPTION(scope, false);
297324 // Here we check inverted because BigInt is the v2
298  JSBigInt::ComparisonResult comparisonResult = JSBigInt::compareToDouble(asBigInt(v2), numberValue);
299325 if (comparisonMode == JSBigInt::ComparisonMode::LessThan)
300326 return comparisonResult == JSBigInt::ComparisonResult::GreaterThan;
301 
302327 return comparisonResult == JSBigInt::ComparisonResult::GreaterThan || comparisonResult == JSBigInt::ComparisonResult::Equal;
303328}
304329

@@ALWAYS_INLINE bool jsLess(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
357382 }
358383 RETURN_IF_EXCEPTION(scope, false);
359384
360  if (wasNotString1 | wasNotString2) {
 385 if (wasNotString1 || wasNotString2) {
361386 if (p1.isBigInt() || p2.isBigInt())
362387 RELEASE_AND_RETURN(scope, bigIntCompare(globalObject, p1, p2, JSBigInt::ComparisonMode::LessThan));
363388

@@ALWAYS_INLINE bool jsLessEq(JSGlobalObject* globalObject, JSValue v1, JSValue v2
407432 }
408433 RETURN_IF_EXCEPTION(scope, false);
409434
410  if (wasNotString1 | wasNotString2) {
 435 if (wasNotString1 || wasNotString2) {
411436 if (p1.isBigInt() || p2.isBigInt())
412437 RELEASE_AND_RETURN(scope, bigIntCompare(globalObject, p1, p2, JSBigInt::ComparisonMode::LessThanOrEqual));
413438

@@ALWAYS_INLINE JSValue jsAdd(JSGlobalObject* globalObject, JSValue v1, JSValue v2
452477 return jsAddNonNumber(globalObject, v1, v2);
453478}
454479
455 ALWAYS_INLINE JSValue jsSub(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 480// BigInt32Op expects its operands unboxed, and returns its result unboxed as well
 481template<typename HeapBigIntOperation, typename DoubleOperation, typename BigInt32Op>
 482ALWAYS_INLINE JSValue arithmeticBinaryOp(JSGlobalObject* globalObject, JSValue v1, JSValue v2, HeapBigIntOperation&& heapBigIntOp, DoubleOperation&& doubleOp, BigInt32Op&& bigInt32Op, const char* errorMessage)
456483{
457  VM& vm = getVM(globalObject);
 484 VM& vm = globalObject->vm();
458485 auto scope = DECLARE_THROW_SCOPE(vm);
459486
460  auto leftNumeric = v1.toNumeric(globalObject);
 487 JSValue leftNumeric = v1.toNumeric(globalObject);
461488 RETURN_IF_EXCEPTION(scope, { });
462  auto rightNumeric = v2.toNumeric(globalObject);
 489 JSValue rightNumeric = v2.toNumeric(globalObject);
463490 RETURN_IF_EXCEPTION(scope, { });
464491
465  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
466  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
467  scope.release();
468  return JSBigInt::sub(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
 492 if (leftNumeric.isNumber() && rightNumeric.isNumber())
 493 return jsNumber(doubleOp(leftNumeric.asNumber(), rightNumeric.asNumber()));
 494
 495#if USE(BIGINT32)
 496 if (leftNumeric.isBigInt32()) {
 497 if (rightNumeric.isBigInt32()) {
 498 if (JSValue result = bigInt32Op(leftNumeric.bigInt32AsInt32(), rightNumeric.bigInt32AsInt32()))
 499 return result;
 500 JSBigInt* leftHeapBigInt = JSBigInt::createFrom(vm, leftNumeric.bigInt32AsInt32());
 501 JSBigInt* rightHeapBigInt = JSBigInt::createFrom(vm, rightNumeric.bigInt32AsInt32());
 502 RELEASE_AND_RETURN(scope, heapBigIntOp(globalObject, leftHeapBigInt, rightHeapBigInt));
469503 }
470 
471  return throwTypeError(globalObject, scope, "Invalid mix of BigInt and other type in subtraction."_s);
 504 if (rightNumeric.isHeapBigInt()) {
 505 JSBigInt* leftHeapBigInt = JSBigInt::createFrom(vm, leftNumeric.bigInt32AsInt32());
 506 RELEASE_AND_RETURN(scope, heapBigIntOp(globalObject, leftHeapBigInt, rightNumeric.asHeapBigInt()));
 507 }
 508 } else if (leftNumeric.isHeapBigInt()) {
 509 if (rightNumeric.isBigInt32()) {
 510 JSBigInt* rightHeapBigInt = JSBigInt::createFrom(vm, rightNumeric.bigInt32AsInt32());
 511 RELEASE_AND_RETURN(scope, heapBigIntOp(globalObject, leftNumeric.asHeapBigInt(), rightHeapBigInt));
 512 } else if (rightNumeric.isHeapBigInt())
 513 RELEASE_AND_RETURN(scope, heapBigIntOp(globalObject, leftNumeric.asHeapBigInt(), rightNumeric.asHeapBigInt()));
472514 }
 515#else
 516 UNUSED_PARAM(bigInt32Op);
 517 if (leftNumeric.isHeapBigInt() && rightNumeric.isHeapBigInt())
 518 RELEASE_AND_RETURN(scope, heapBigIntOp(globalObject, leftNumeric.asHeapBigInt(), rightNumeric.asHeapBigInt()));
 519#endif
 520
 521 return throwTypeError(globalObject, scope, errorMessage);
 522}
473523
474  return jsNumber(WTF::get<double>(leftNumeric) - WTF::get<double>(rightNumeric));
 524ALWAYS_INLINE JSValue jsSub(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 525{
 526 auto doubleOp = [] (double left, double right) -> double {
 527 return left - right;
 528 };
 529 auto bigInt32Op = [] (int32_t left, int32_t right) -> JSValue {
 530#if USE(BIGINT32)
 531 Checked<int32_t, RecordOverflow> result = left;
 532 result -= right;
 533 if (UNLIKELY(result.hasOverflowed()))
 534 return JSValue();
 535 return JSValue(JSValue::JSBigInt32, result.unsafeGet());
 536#else
 537 UNUSED_PARAM(left);
 538 UNUSED_PARAM(right);
 539 RELEASE_ASSERT_NOT_REACHED();
 540#endif
 541 };
 542
 543 return arithmeticBinaryOp(globalObject, v1, v2, JSBigInt::sub, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in subtraction."_s);
475544}
476545
477546ALWAYS_INLINE JSValue jsMul(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 547{
 548 auto doubleOp = [] (double left, double right) -> double {
 549 return left * right;
 550 };
 551 auto bigInt32Op = [] (int32_t left, int32_t right) -> JSValue {
 552#if USE(BIGINT32)
 553 Checked<int32_t, RecordOverflow> result = left;
 554 result *= right;
 555 if (result.hasOverflowed())
 556 return JSValue();
 557 return JSValue(JSValue::JSBigInt32, result.unsafeGet());
 558#else
 559 UNUSED_PARAM(left);
 560 UNUSED_PARAM(right);
 561 RELEASE_ASSERT_NOT_REACHED();
 562#endif
 563 };
 564
 565 return arithmeticBinaryOp(globalObject, v1, v2, JSBigInt::multiply, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in multiplication."_s);
 566}
 567
 568ALWAYS_INLINE JSValue jsDiv(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 569{
 570 auto doubleOp = [] (double left, double right) -> double {
 571 return left / right;
 572 };
 573 auto bigInt32Op = [] (int32_t left, int32_t right) -> JSValue {
 574#if USE(BIGINT32)
 575 if (!right)
 576 return JSValue();
 577 return JSValue(JSValue::JSBigInt32, left / right);
 578#else
 579 UNUSED_PARAM(left);
 580 UNUSED_PARAM(right);
 581 RELEASE_ASSERT_NOT_REACHED();
 582#endif
 583 };
 584
 585 return arithmeticBinaryOp(globalObject, v1, v2, JSBigInt::divide, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in division."_s);
 586}
 587
 588ALWAYS_INLINE JSValue jsRemainder(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 589{
 590 auto doubleOp = [] (double left, double right) -> double {
 591 return jsMod(left, right);
 592 };
 593 auto bigInt32Op = [] (int32_t, int32_t) -> JSValue {
 594 // FIXME: do something more clever here.
 595 return JSValue();
 596 };
 597
 598 return arithmeticBinaryOp(globalObject, v1, v2, JSBigInt::remainder, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in remainder."_s);
 599}
 600
 601ALWAYS_INLINE JSValue jsPow(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 602{
 603 auto doubleOp = [] (double left, double right) -> double {
 604 return operationMathPow(left, right);
 605 };
 606 auto bigInt32Op = [] (int32_t, int32_t) -> JSValue {
 607 // Exponentiation on integers is both somewhat slow in the best case, and very likely to overflow.
 608 // So don't bother trying to avoid a heap allocation in that case.
 609 return JSValue();
 610 };
 611
 612 return arithmeticBinaryOp(globalObject, v1, v2, JSBigInt::exponentiate, doubleOp, bigInt32Op, "Invalid mix of BigInt and other type in exponentiation."_s);
 613}
 614
 615ALWAYS_INLINE JSValue jsInc(JSGlobalObject* globalObject, JSValue v)
 616{
 617 VM& vm = globalObject->vm();
 618 auto scope = DECLARE_THROW_SCOPE(vm);
 619
 620 auto operandNumeric = v.toNumeric(globalObject);
 621 RETURN_IF_EXCEPTION(scope, { });
 622
 623 if (operandNumeric.isNumber())
 624 return jsNumber(operandNumeric.asNumber() + 1);
 625
 626#if USE(BIGINT32)
 627 if (operandNumeric.isBigInt32()) {
 628 int64_t newValue = static_cast<int64_t>(operandNumeric.bigInt32AsInt32()) + 1;
 629 // FIXME: the following next few lines might benefit from being made into a helper function
 630 if (newValue > INT_MAX)
 631 return JSBigInt::createFrom(vm, newValue);
 632 return JSValue(JSValue::JSBigInt32, static_cast<int32_t>(newValue));
 633 }
 634#endif
 635
 636 ASSERT(operandNumeric.isHeapBigInt());
 637 RELEASE_AND_RETURN(scope, JSBigInt::inc(globalObject, operandNumeric.asHeapBigInt()));
 638}
 639
 640ALWAYS_INLINE JSValue jsDec(JSGlobalObject* globalObject, JSValue v)
 641{
 642 VM& vm = globalObject->vm();
 643 auto scope = DECLARE_THROW_SCOPE(vm);
 644
 645 auto operandNumeric = v.toNumeric(globalObject);
 646 RETURN_IF_EXCEPTION(scope, { });
 647
 648 if (operandNumeric.isNumber())
 649 return jsNumber(operandNumeric.asNumber() - 1);
 650
 651#if USE(BIGINT32)
 652 if (operandNumeric.isBigInt32()) {
 653 int64_t newValue = static_cast<int64_t>(operandNumeric.bigInt32AsInt32()) - 1;
 654 // FIXME: the following next few lines might benefit from being made into a helper function
 655 if (newValue < INT_MIN)
 656 return JSBigInt::createFrom(vm, newValue);
 657 return JSValue(JSValue::JSBigInt32, static_cast<int32_t>(newValue));
 658 }
 659#endif
 660
 661 ASSERT(operandNumeric.isHeapBigInt());
 662 RELEASE_AND_RETURN(scope, JSBigInt::dec(globalObject, operandNumeric.asHeapBigInt()));
 663}
 664
 665ALWAYS_INLINE JSValue jsBitwiseNot(JSGlobalObject* globalObject, JSValue v)
 666{
 667 VM& vm = globalObject->vm();
 668 auto scope = DECLARE_THROW_SCOPE(vm);
 669
 670 auto operandNumeric = v.toBigIntOrInt32(globalObject);
 671 RETURN_IF_EXCEPTION(scope, { });
 672
 673 if (operandNumeric.isInt32())
 674 return jsNumber(~operandNumeric.asInt32());
 675
 676#if USE(BIGINT32)
 677 if (operandNumeric.isBigInt32())
 678 return JSValue(JSValue::JSBigInt32, ~operandNumeric.bigInt32AsInt32());
 679#endif
 680
 681 ASSERT(operandNumeric.isHeapBigInt());
 682 RELEASE_AND_RETURN(scope, JSBigInt::bitwiseNot(globalObject, operandNumeric.asHeapBigInt()));
 683}
 684
 685ALWAYS_INLINE JSValue shift(JSGlobalObject* globalObject, JSValue v1, JSValue v2, bool isLeft)
478686{
479687 VM& vm = globalObject->vm();
480688 auto scope = DECLARE_THROW_SCOPE(vm);
481689
482  Variant<JSBigInt*, double> leftNumeric = v1.toNumeric(globalObject);
 690 auto leftNumeric = v1.toBigIntOrInt32(globalObject);
483691 RETURN_IF_EXCEPTION(scope, { });
484  Variant<JSBigInt*, double> rightNumeric = v2.toNumeric(globalObject);
 692 auto rightNumeric = v2.toBigIntOrInt32(globalObject);
485693 RETURN_IF_EXCEPTION(scope, { });
486694
487  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
488  if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
489  scope.release();
490  return JSBigInt::multiply(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
 695 if (leftNumeric.isInt32() && rightNumeric.isInt32()) {
 696 int32_t leftInt32 = leftNumeric.asInt32();
 697 int32_t rightInt32 = rightNumeric.asInt32() & 31;
 698 int32_t result = isLeft ? (leftInt32 << rightInt32) : (leftInt32 >> rightInt32);
 699 return jsNumber(result);
 700 }
 701
 702#if USE(BIGINT32)
 703 if (leftNumeric.isBigInt32() && rightNumeric.isBigInt32()) {
 704 int32_t leftInt32 = leftNumeric.bigInt32AsInt32();
 705 int32_t rightInt32 = rightNumeric.bigInt32AsInt32();
 706 if (rightInt32 < 0) {
 707 isLeft = !isLeft;
 708 rightInt32 = -rightInt32;
491709 }
492710
493  throwTypeError(globalObject, scope, "Invalid mix of BigInt and other type in multiplication."_s);
494  return { };
 711 // This std::min is a bit hacky, but required because in C++ it is undefined behavior to do a shift where the right operand is greater or equal to the bit-width of the left operand.
 712 if (!isLeft)
 713 return JSValue(JSValue::JSBigInt32, leftInt32 >> std::min(rightInt32, 31));
 714
 715 // In the case of a left shift we can overflow. I deal with this by allocating HeapBigInts.
 716 // FIXME: it might be possible to do something smarter, trying to do the left shift and detecting somehow if it overflowed.
 717 JSBigInt* leftHeapBigInt = JSBigInt::createFrom(vm, leftInt32);
 718 JSBigInt* rightHeapBigInt = JSBigInt::createFrom(vm, rightInt32);
 719 if (isLeft)
 720 RELEASE_AND_RETURN(scope, JSBigInt::leftShift(globalObject, leftHeapBigInt, rightHeapBigInt));
 721 RELEASE_AND_RETURN(scope, JSBigInt::signedRightShift(globalObject, leftHeapBigInt, rightHeapBigInt));
495722 }
 723#endif
 724
 725 if (!(leftNumeric.isBigInt() && rightNumeric.isBigInt())) {
 726 auto errorMessage = isLeft ? "Invalid mix of BigInt and other type in left shift operation." : "Invalid mix of BigInt and other type in signed right shift operation.";
 727 return throwTypeError(globalObject, scope, errorMessage);
 728 }
 729
 730 // FIXME: we should have a case for left is HeapBigInt and right is BigInt32, it seems fairly likely to occur frequently.
 731#if USE(BIGINT32)
 732 JSBigInt* leftHeapBigInt = leftNumeric.isBigInt32() ? JSBigInt::createFrom(vm, leftNumeric.bigInt32AsInt32()) : leftNumeric.asHeapBigInt();
 733 JSBigInt* rightHeapBigInt = rightNumeric.isBigInt32() ? JSBigInt::createFrom(vm, rightNumeric.bigInt32AsInt32()) : rightNumeric.asHeapBigInt();
 734#else
 735 JSBigInt* leftHeapBigInt = leftNumeric.asHeapBigInt();
 736 JSBigInt* rightHeapBigInt = rightNumeric.asHeapBigInt();
 737#endif
 738
 739 if (isLeft)
 740 RELEASE_AND_RETURN(scope, JSBigInt::leftShift(globalObject, leftHeapBigInt, rightHeapBigInt));
 741 RELEASE_AND_RETURN(scope, JSBigInt::signedRightShift(globalObject, leftHeapBigInt, rightHeapBigInt));
 742}
 743
 744ALWAYS_INLINE JSValue jsLShift(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 745{
 746 bool isLeft = true;
 747 return shift(globalObject, v1, v2, isLeft);
 748}
496749
497  double leftValue = WTF::get<double>(leftNumeric);
498  double rightValue = WTF::get<double>(rightNumeric);
499  return jsNumber(leftValue * rightValue);
 750ALWAYS_INLINE JSValue jsRShift(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 751{
 752 bool isLeft = false;
 753 return shift(globalObject, v1, v2, isLeft);
500754}
501755
502 inline bool scribbleFreeCells()
 756template<typename HeapBigIntOperation, typename Int32Operation>
 757ALWAYS_INLINE JSValue bitwiseBinaryOp(JSGlobalObject* globalObject, JSValue v1, JSValue v2, HeapBigIntOperation&& bigIntOp, Int32Operation&& int32Op, const char* errorMessage)
503758{
504  return ASSERT_ENABLED || Options::scribbleFreeCells();
 759 VM& vm = globalObject->vm();
 760 auto scope = DECLARE_THROW_SCOPE(vm);
 761
 762 auto leftNumeric = v1.toBigIntOrInt32(globalObject);
 763 RETURN_IF_EXCEPTION(scope, { });
 764 auto rightNumeric = v2.toBigIntOrInt32(globalObject);
 765 RETURN_IF_EXCEPTION(scope, { });
 766
 767 if (leftNumeric.isInt32() && rightNumeric.isInt32())
 768 return jsNumber(int32Op(leftNumeric.asInt32(), rightNumeric.asInt32()));
 769
 770#if USE(BIGINT32)
 771 if (leftNumeric.isBigInt32() && rightNumeric.isBigInt32())
 772 return JSValue(JSValue::JSBigInt32, int32Op(leftNumeric.bigInt32AsInt32(), rightNumeric.bigInt32AsInt32()));
 773 // FIXME: add fast path for BigInt32 / HeapBigInt, and for HeapBigInt / BigInt32
 774 // In many cases these could be made more efficient than heap-allocating the small big-int and going through the generic path.
 775 // But it is quite tricky, not least because HeapBigInt use a sign bit whereas BigInt32 use 2-complement representation.
 776#endif
 777
 778 if (!(leftNumeric.isBigInt() && rightNumeric.isBigInt()))
 779 return throwTypeError(globalObject, scope, errorMessage);
 780
 781#if USE(BIGINT32)
 782 JSBigInt* leftHeapBigInt = leftNumeric.isBigInt32() ? JSBigInt::createFrom(vm, leftNumeric.bigInt32AsInt32()) : leftNumeric.asHeapBigInt();
 783 JSBigInt* rightHeapBigInt = rightNumeric.isBigInt32() ? JSBigInt::createFrom(vm, rightNumeric.bigInt32AsInt32()) : rightNumeric.asHeapBigInt();
 784#else
 785 JSBigInt* leftHeapBigInt = leftNumeric.asHeapBigInt();
 786 JSBigInt* rightHeapBigInt = rightNumeric.asHeapBigInt();
 787#endif
 788
 789 RELEASE_AND_RETURN(scope, bigIntOp(globalObject, leftHeapBigInt, rightHeapBigInt));
505790}
506791
507 #define SCRIBBLE_WORD static_cast<intptr_t>(0xbadbeef0)
 792ALWAYS_INLINE JSValue jsBitwiseAnd(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
 793{
 794 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
 795 return left & right;
 796 };
 797
 798 // FIXME: currently, for pairs of BigInt32, we unbox them, do the "and" and re-box them.
 799 // We could do it directly on the JSValue.
 800 return bitwiseBinaryOp(globalObject, v1, v2, JSBigInt::bitwiseAnd, int32Op, "Invalid mix of BigInt and other type in bitwise 'and' operation."_s);
 801}
508802
509 inline bool isScribbledValue(JSValue value)
 803ALWAYS_INLINE JSValue jsBitwiseOr(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
510804{
511  return JSValue::encode(value) == JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
 805 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
 806 return left | right;
 807 };
 808
 809 // FIXME: currently, for pairs of BigInt32, we unbox them, do the "or" and re-box them.
 810 // We could do it directly on the JSValue.
 811 return bitwiseBinaryOp(globalObject, v1, v2, JSBigInt::bitwiseOr, int32Op, "Invalid mix of BigInt and other type in bitwise 'or' operation."_s);
512812}
513813
514 inline void scribble(void* base, size_t size)
 814ALWAYS_INLINE JSValue jsBitwiseXor(JSGlobalObject* globalObject, JSValue v1, JSValue v2)
515815{
516  for (size_t i = size / sizeof(EncodedJSValue); i--;) {
517  // Use a 16-byte aligned value to ensure that it passes the cell check.
518  static_cast<EncodedJSValue*>(base)[i] = JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
519  }
 816 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
 817 return left ^ right;
 818 };
 819
 820 // FIXME: currently, for pairs of BigInt32, we unbox them, do the "xor" and re-box them.
 821 // We could do it directly on the JSValue, and just remember to do an or with 0x12 at the end to restore the tag
 822 return bitwiseBinaryOp(globalObject, v1, v2, JSBigInt::bitwiseXor, int32Op, "Invalid mix of BigInt and other type in bitwise 'xor' operation."_s);
520823}
521824
522825ALWAYS_INLINE EncodedJSValue getByValWithIndex(JSGlobalObject* globalObject, JSCell* base, uint32_t index)

Source/JavaScriptCore/runtime/Scribble.h

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#include "JSCJSValue.h"
 29#include "JSCell.h"
 30#include "Options.h"
 31
 32namespace JSC {
 33
 34inline bool scribbleFreeCells()
 35{
 36 return ASSERT_ENABLED || Options::scribbleFreeCells();
 37}
 38
 39#define SCRIBBLE_WORD static_cast<intptr_t>(0xbadbeef0)
 40
 41inline bool isScribbledValue(JSValue value)
 42{
 43 return JSValue::encode(value) == JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
 44}
 45
 46inline void scribble(void* base, size_t size)
 47{
 48 for (size_t i = size / sizeof(EncodedJSValue); i--;) {
 49 // Use a 16-byte aligned value to ensure that it passes the cell check.
 50 static_cast<EncodedJSValue*>(base)[i] = JSValue::encode(bitwise_cast<JSCell*>(SCRIBBLE_WORD));
 51 }
 52}
 53
 54}

Source/JavaScriptCore/runtime/StructureInlines.h

@@ALWAYS_INLINE JSValue prototypeForLookupPrimitiveImpl(JSGlobalObject* globalObje
279279 if (structure->typeInfo().type() == StringType)
280280 return globalObject->stringPrototype();
281281
282  if (structure->typeInfo().type() == BigIntType)
 282 if (structure->typeInfo().type() == HeapBigIntType)
283283 return globalObject->bigIntPrototype();
284284
285285 ASSERT(structure->typeInfo().type() == SymbolType);

Source/JavaScriptCore/runtime/VM.cpp

@@VM::VM(VMType vmType, HeapType heapType)
492492 sentinelMapBucket();
493493 sentinelSetBucket();
494494 }
495  bigIntConstantOne.set(*this, JSBigInt::createFrom(*this, 1));
 495 heapBigIntConstantOne.set(*this, JSBigInt::createFrom(*this, 1));
496496
497497 Thread::current().setCurrentAtomStringTable(existingEntryAtomStringTable);
498498

Source/JavaScriptCore/runtime/VM.h

@@public:
724724 AtomStringTable* atomStringTable() const { return m_atomStringTable; }
725725 WTF::SymbolRegistry& symbolRegistry() { return m_symbolRegistry; }
726726
727  Strong<JSBigInt> bigIntConstantOne;
 727 Strong<JSBigInt> heapBigIntConstantOne;
728728
729729 JSCell* sentinelSetBucket()
730730 {

Source/JavaScriptCore/tools/JSDollarVM.cpp

@@static EncodedJSValue JSC_HOST_CALL functionCallWithStackSize(JSGlobalObject* gl
22052205 uint8_t* vmStackEnd = vmStackStart - originalMaxPerThreadStackUsage;
22062206 ptrdiff_t sizeDiff = vmStackEnd - end;
22072207 RELEASE_ASSERT(sizeDiff >= 0);
2208  RELEASE_ASSERT(sizeDiff < UINT_MAX);
 2208 RELEASE_ASSERT(static_cast<uint64_t>(sizeDiff) < UINT_MAX);
22092209
22102210 Options::maxPerThreadStackUsage() = originalMaxPerThreadStackUsage + sizeDiff;
22112211 helper.updateVMStackLimits();

Source/WTF/ChangeLog

 12020-04-06 Robin Morisset <rmorisset@apple.com>
 2
 3 Support an inlined representation in JSValue of small BigInts ("BigInt32")
 4 https://bugs.webkit.org/show_bug.cgi?id=206182
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Add a USE(BIGINT32) flag.
 9
 10 * wtf/PlatformUse.h:
 11
1122020-04-16 Daniel Bates <dabates@apple.com>
213
314 Clean up VectorCocoa createNSArray overloads and add documentation for createNSArray taking a map function

Source/WTF/wtf/PlatformUse.h

139139#endif
140140#endif /* !defined(USE_JSVALUE64) && !defined(USE_JSVALUE32_64) */
141141
 142#if USE(JSVALUE64)
 143#define USE_BIGINT32 1
 144#endif
 145
142146/* FIXME: This name should be more specific if it is only for use with CallFrame* */
143147/* Use __builtin_frame_address(1) to get CallFrame* */
144148#if COMPILER(GCC_COMPATIBLE) && (CPU(ARM64) || CPU(X86_64))

Tools/Scripts/run-jsc-stress-tests

@@def runBigIntEnabled(*optionalTestSpecificOptions)
702702 run("big-int-enabled", "--useBigInt=true" , *(FTL_OPTIONS + optionalTestSpecificOptions))
703703end
704704
 705def runBigIntEnabledNoJIT(*optionalTestSpecificOptions)
 706 run("big-int-enabled-nojit", "--useBigInt=true", "--useJIT=false", *optionalTestSpecificOptions)
 707end
 708
 709def runBigIntEnabledBaseline(*optionalTestSpecificOptions)
 710 run("big-int-enabled-baseline", "--useBigInt=true", "--useDFGJIT=0", *optionalTestSpecificOptions)
 711end
 712
705713def runFTLNoCJIT(*optionalTestSpecificOptions)
706714 run("misc-ftl-no-cjit", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
707715end