WebKit Bugzilla
Attachment 340791 Details for
Bug 185379
: [ESNext][BigInt] Implement support for "<" and ">" relational operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
big-int-less.diff (text/plain), 29.15 KB, created by
Caio Lima
on 2018-05-19 19:58:03 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-05-19 19:58:03 PDT
Size:
29.15 KB
patch
obsolete
>diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 72f9954..b8c2d32 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,19 @@ >+2018-05-14 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "<" and ">" relational operation >+ https://bugs.webkit.org/show_bug.cgi?id=185379 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/big-int-greater-than-general.js: Added. >+ * stress/big-int-greater-than-jit.js: Added. >+ * stress/big-int-greater-than-order-of-evaluation.js: Added. >+ * stress/big-int-greater-than-wrapped-values.js: Added. >+ * stress/big-int-less-than-general.js: Added. >+ * stress/big-int-less-than-jit.js: Added. >+ * stress/big-int-less-than-order-of-evaluation.js: Added. >+ * stress/big-int-less-than-wrapped-values.js: Added. >+ > 2018-05-19 Yusuke Suzuki <utatane.tea@gmail.com> > > [JSC] JSC should have consistent InById IC >diff --git a/JSTests/stress/big-int-greater-than-general.js b/JSTests/stress/big-int-greater-than-general.js >new file mode 100644 >index 0000000..fbdec33 >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-general.js >@@ -0,0 +1,45 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// Copyright (C) 2018 Igalia, S.L. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(0n > 0n, false, "0n > 0n"); >+assert(1n > 1n, false, "1n > 1n"); >+assert(BigInt("-1") > BigInt("-1"), false, "-1n > -1n"); >+assert(0n > BigInt("-0"), false, "0n > -0n"); >+assert(BigInt("-0") > 0n, false, "-0n > 0n"); >+assert(0n > 1n, false, "0n > 1n"); >+assert(1n > 0n, true, "1n > 0n"); >+assert(0n > BigInt("-1"), true, "0n > -1n"); >+assert(BigInt("-1") > 0n, false, "-1n > 0n"); >+assert(1n > BigInt("-1"), true, "1n > -1n"); >+assert(BigInt("-1") > 1n, false, "-1n > 1n"); >+assert(0x1fffffffffffff01n > 0x1fffffffffffff02n, false, "0x1fffffffffffff01n > 0x1fffffffffffff02n"); >+assert(0x1fffffffffffff02n > 0x1fffffffffffff01n, true, "0x1fffffffffffff02n > 0x1fffffffffffff01n"); >+assert(BigInt("-2305843009213693697") > BigInt("-2305843009213693698"), true, "-2305843009213693697n > -2305843009213693698n"); >+assert(BigInt("-2305843009213693698") > BigInt("-2305843009213693697"), false, "-2305843009213693698n > -2305843009213693697n"); >+assert(0x10000000000000000n > 0n, true, "0x10000000000000000n > 0n"); >+assert(0n > 0x10000000000000000n, false, "0n > 0x10000000000000000n"); >+assert(0x10000000000000000n > 1n, true, "0x10000000000000000n > 1n"); >+assert(1n > 0x10000000000000000n, false, "1n > 0x10000000000000000n"); >+assert(0x10000000000000000n > BigInt("-1"), true, "0x10000000000000000n > -1n"); >+assert(BigInt("-1") > 0x10000000000000000n, false, "-1n > 0x10000000000000000n"); >+assert(0x10000000000000001n > 0n, true, "0x10000000000000001n > 0n"); >+assert(0n > 0x10000000000000001n, false, "0n > 0x10000000000000001n"); >+assert(BigInt("-18446744073709551616") > 0n, false, "-18446744073709551616n > 0n"); >+assert(0n > BigInt("-18446744073709551616"), true, "0n > -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") > 1n, false, "-18446744073709551616n > 1n"); >+assert(1n > BigInt("-18446744073709551616"), true, "1n > -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") > BigInt("-1"), false, "-18446744073709551616n > -1n"); >+assert(BigInt("-1") > BigInt("-18446744073709551616"), true, "-1n > -18446744073709551616n"); >+assert(BigInt("-18446744073709551617") > 0n, false, "-18446744073709551617n > 0n"); >+assert(0n > BigInt("-18446744073709551617"), true, "0n > -18446744073709551617n"); >+assert(0x10000000000000000n > 0x100000000n, true, "0x10000000000000000n > 0x100000000n"); >+assert(0x100000000n > 0x10000000000000000n, false, "0x100000000n > 0x10000000000000000n"); >+ >diff --git a/JSTests/stress/big-int-greater-than-jit.js b/JSTests/stress/big-int-greater-than-jit.js >new file mode 100644 >index 0000000..f03ada2 >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-jit.js >@@ -0,0 +1,24 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+function greaterThanTest(a, b) { >+ return a > b; >+} >+noInline(greaterThanTest); >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanTest(3n, 4) === false); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanTest(3n, 4n) === false); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(greaterThanTest(3n, "4") === false); >+} >+ >diff --git a/JSTests/stress/big-int-greater-than-order-of-evaluation.js b/JSTests/stress/big-int-greater-than-order-of-evaluation.js >new file mode 100644 >index 0000000..b961ba5 >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-order-of-evaluation.js >@@ -0,0 +1,55 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ throw new Error("Calling @toPrimitive"); >+ } >+} >+ >+try { >+ o > Symbol(2); >+ assert(true, false, "") >+} catch(e) { >+ assert(e.message, "Calling @toPrimitive", "Bad Exception when object is left operand"); >+} >+ >+try { >+ Symbol(2) > o; >+ assert(true, false, "") >+} catch(e) { >+ assert(e instanceof TypeError, true, "Bad Exception when Symbol is left operand"); >+} >+ >+o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ }, >+ >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ throw new Error("Should never call valueOf"); >+ } >+} >+ >+assert(o > 3n, false, "ToPrimitive(2n) > 3n"); >+ >+o = { >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+assert(o > 3n, false, "valueOf(2n) > 3n"); >+ >diff --git a/JSTests/stress/big-int-greater-than-wrapped-values.js b/JSTests/stress/big-int-greater-than-wrapped-values.js >new file mode 100644 >index 0000000..4f45f1f >--- /dev/null >+++ b/JSTests/stress/big-int-greater-than-wrapped-values.js >@@ -0,0 +1,63 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(Object(2n) > 1n, true, "Object(2n) > 1n"); >+assert(1n > Object(2n), false, "1n > Object(2n)"); >+assert(Object(2n) > Object(1n), true, "Object(2n) > Object(1n)"); >+assert(Object(1n) > Object(2n), false, "Object(1n) > Object(2n)"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ } >+} >+ >+let o2 = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ } >+} >+ >+assert(o > 1n, true, "ToPrimitive(2n) > 1n"); >+assert(1n > o, false, "1n > ToPrimitive(2n)"); >+assert(o > o2, true, "ToPrimitive(2n) > ToPrimitive(1n)"); >+assert(o2 > o, false, "ToPrimitive(1n) > ToPrimitive(2n)"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ valueOf: function() { >+ return 1n; >+ } >+} >+ >+assert(o > 1n, true, "valueOf(2n) > 1n"); >+assert(1n > o, false, "1n > valueOf(2n)"); >+assert(o > o2, true, "valueOf(2n) > valueOf(1n)"); >+assert(o2 > o, false, "valueOf(1n) > valueOf(2n)"); >+ >+o = { >+ toString: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ toString: function() { >+ return 1n; >+ } >+} >+ >+assert(o > 1n, true, "toString(2n) > 1n"); >+assert(1n > o, false, "1n > ToPrimitive(2n)"); >+assert(o > o2, true, "toString(2n) < toString(1n)"); >+assert(o2 > o, false, "toString(1n) < toString(2n)"); >+ >diff --git a/JSTests/stress/big-int-less-than-general.js b/JSTests/stress/big-int-less-than-general.js >new file mode 100644 >index 0000000..ca75c2a >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-general.js >@@ -0,0 +1,133 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// Copyright (C) 2017 Robin Templeton. All rights reserved. >+// Copyright (C) 2018 Igalia, S.L. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(0n < 0n, false, "0n < 0n"); >+assert(1n < 1n, false, "1n < 1n"); >+assert(BigInt("-1") < BigInt("-1"), false, "-1n < -1n"); >+assert(0n < BigInt("-0"), false, "0n < -0n"); >+assert(BigInt("-0") < 0n, false, "-0n < 0n"); >+assert(0n < 1n, true, "0n < 1n"); >+assert(1n < 0n, false, "1n < 0n"); >+assert(0n < BigInt("-1"), false, "0n < -1n"); >+assert(BigInt("-1") < 0n, true, "-1n < 0n"); >+assert(1n < BigInt("-1"), false, "1n < -1n"); >+assert(BigInt("-1") < 1n, true, "-1n < 1n"); >+assert(0x1fffffffffffff01n < 0x1fffffffffffff02n, true, "0x1fffffffffffff01n < 0x1fffffffffffff02n"); >+assert(0x1fffffffffffff02n < 0x1fffffffffffff01n, false, "0x1fffffffffffff02n < 0x1fffffffffffff01n"); >+assert(BigInt("-2305843009213693697") < BigInt("-2305843009213693698"), false, "-2305843009213693697n < -2305843009213693698n"); >+assert(BigInt("-2305843009213693698") < BigInt("-2305843009213693697"), true, "-2305843009213693698n < -2305843009213693697n"); >+assert(0x10000000000000000n < 0n, false, "0x10000000000000000n < 0n"); >+assert(0n < 0x10000000000000000n, true, "0n < 0x10000000000000000n"); >+assert(0x10000000000000000n < 1n, false, "0x10000000000000000n < 1n"); >+assert(1n < 0x10000000000000000n, true, "1n < 0x10000000000000000n"); >+assert(0x10000000000000000n < BigInt("-1"), false, "0x10000000000000000n < -1n"); >+assert(BigInt("-1") < 0x10000000000000000n, true, "-1n < 0x10000000000000000n"); >+assert(0x10000000000000001n < 0n, false, "0x10000000000000001n < 0n"); >+assert(0n < 0x10000000000000001n, true, "0n < 0x10000000000000001n"); >+assert(BigInt("-18446744073709551616") < 0n, true, "-18446744073709551616n < 0n"); >+assert(0n < BigInt("-18446744073709551616"), false, "0n < -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") < 1n, true, "-18446744073709551616n < 1n"); >+assert(1n < BigInt("-18446744073709551616"), false, "1n < -18446744073709551616n"); >+assert(BigInt("-18446744073709551616") < BigInt("-1"), true, "-18446744073709551616n < -1n"); >+assert(BigInt("-1") < BigInt("-18446744073709551616"), false, "-1n < -18446744073709551616n"); >+assert(BigInt("-18446744073709551617") < 0n, true, "-18446744073709551617n < 0n"); >+assert(0n < BigInt("-18446744073709551617"), false, "0n < -18446744073709551617n"); >+assert(0x10000000000000000n < 0x100000000n, false, "0x10000000000000000n < 0x100000000n"); >+assert(0x100000000n < 0x10000000000000000n, true, "0x100000000n < 0x10000000000000000n"); >+ >+// BigInt - String >+ >+assert(0n < "0", false, "0n < '0'"); assert("0" < 0n, false, "'0' < 0n"); >+assert(0n < "1", true, "0n < '1'"); >+assert("0" < 1n, true, "'0' < 1n"); >+assert(1n < "0", false, "1n < '0'"); >+assert("1" < 0n, false, "'1' < 0n"); >+assert(0n < "", false, "0n < ''"); >+assert("" < 0n, false, "'' < 0n"); >+assert(0n < "1", true, "0n < '1'"); >+assert("" < 1n, true, "'' < 1n"); >+assert(1n < "", false, "1n < ''"); >+assert("1" < 0n, false, "'1' < 0n"); >+assert(1n < "1", false, "1n < '1'"); >+assert("1" < 1n, false, "'1' < 1n"); >+assert(1n < "-1", false, "1n < '-1'"); >+assert("1" < BigInt("-1"), false, "'1' < -1n"); >+assert(BigInt("-1") < "1", true, "-1n < '1'"); >+assert("-1" < 1n, true, "'-1' < 1n"); >+assert(BigInt("-1") < "-1", false, "-1n < '-1'"); >+assert("-1" < BigInt("-1"), false, "'-1' < -1n"); >+assert(9007199254740993n < "9007199254740992", false, "9007199254740993n < '9007199254740992'"); >+assert("9007199254740993" < 9007199254740992n, false, "'9007199254740993' < 9007199254740992n"); >+assert(BigInt("-9007199254740992") < "-9007199254740993", false, "-9007199254740992n < '-9007199254740993'"); >+assert("-9007199254740992" < BigInt("-9007199254740992"), false, "'-9007199254740992' < -9007199254740993n"); >+ >+// BigInt - Number >+ >+assert(0n < 0, false, "0n < 0"); >+assert(0 < 0n, false, "0 < 0n"); >+assert(0n < -0, false, "0n < -0"); >+assert(-0 < 0n, false, "-0 < 0n"); >+assert(0n < 0.000000000001, true, "0n < 0.000000000001"); >+assert(0.000000000001 < 0n, false, "0.000000000001 < 0n"); >+assert(0n < 1, true, "0n < 1"); >+assert(1 < 0n, false, "1 < 0n"); >+assert(1n < 0, false, "1n < 0"); >+assert(0 < 1n, true, "0 < 1n"); >+assert(1n < 0.999999999999, false, "1n < 0.999999999999"); >+assert(0.999999999999 < 1n, true, "0.999999999999 < 1n"); >+assert(1n < 1, false, "1n < 1"); >+assert(1 < 1n, false, "1 < 1n"); >+assert(0n < Number.MIN_VALUE, true, "0n < Number.MIN_VALUE"); >+assert(Number.MIN_VALUE < 0n, false, "Number.MIN_VALUE < 0n"); >+assert(0n < -Number.MIN_VALUE, false, "0n < -Number.MIN_VALUE"); >+assert(-Number.MIN_VALUE < 0n, true, "-Number.MIN_VALUE < 0n"); >+assert(BigInt("-10") < Number.MIN_VALUE, true, "-10n < Number.MIN_VALUE"); >+assert(Number.MIN_VALUE < BigInt("-10"), false, "Number.MIN_VALUE < -10n"); >+assert(1n < Number.MAX_VALUE, true, "1n < Number.MAX_VALUE"); >+assert(Number.MAX_VALUE < 1n, false, "Number.MAX_VALUE < 1n"); >+assert(1n < -Number.MAX_VALUE, false, "1n < -Number.MAX_VALUE"); >+assert(-Number.MAX_VALUE < 1n, true, "-Number.MAX_VALUE < 1n"); >+assert(0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn < Number.MAX_VALUE, true, "0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn < Number.MAX_VALUE"); >+assert(Number.MAX_VALUE < 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn, false, "Number.MAX_VALUE < 0xfffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn"); >+assert(0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n < Number.MAX_VALUE, false, "0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n < Number.MAX_VALUE"); >+assert(Number.MAX_VALUE < 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n, true, "Number.MAX_VALUE < 0xfffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001n"); >+assert(1n < Infinity, true, "1n < Infinity"); >+assert(Infinity < 1n, false, "Infinity < 1n"); >+assert(BigInt("-1") < Infinity, true, "-1n < Infinity"); >+assert(Infinity < BigInt("-1"), false, "Infinity < -1n"); >+assert(1n < -Infinity, false, "1n < -Infinity"); >+assert(-Infinity < 1n, true, "-Infinity < 1n"); >+assert(BigInt("-1") < -Infinity, false, "-1n < -Infinity"); >+assert(-Infinity < BigInt("-1"), true, "-Infinity < -1n"); >+assert(0n < NaN, false, "0n < NaN"); >+assert(NaN < 0n, false, "NaN < 0n"); >+ >+// BigInt - Boolean >+ >+assert(false < 1n, true, "false < 1n"); >+assert(1n < false, false, "1n < false"); >+assert(false < 0n, false, "false < 0n"); >+assert(0n < false, false, "0n < false"); >+assert(true < 1n, false, "true < 1n"); >+assert(1n < true, false, "1n < true"); >+assert(true < 2n, true, "true < 2n"); >+assert(2n < true, false, "2n < true"); >+ >+// BigInt - Symbol >+ >+try { >+ 1n < Symbol("1"); >+ assert(false, true, "Comparison with Symbol shoud throw TypeError, but executed without exception"); >+} catch(e) { >+ assert(e instanceof TypeError, true, "Comparison with Symbol shoud throw TypeError, but throwed something else"); >+} >+ >diff --git a/JSTests/stress/big-int-less-than-jit.js b/JSTests/stress/big-int-less-than-jit.js >new file mode 100644 >index 0000000..0e80add >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-jit.js >@@ -0,0 +1,24 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+function lessThanTest(a, b) { >+ return a < b; >+} >+noInline(lessThanTest); >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanTest(3n, 4) === true); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanTest(3n, 4n) === true); >+} >+ >+for (let i = 0; i < 100000; i++) { >+ assert(lessThanTest(3n, "4") === true); >+} >+ >diff --git a/JSTests/stress/big-int-less-than-order-of-evaluation.js b/JSTests/stress/big-int-less-than-order-of-evaluation.js >new file mode 100644 >index 0000000..b7efe43 >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-order-of-evaluation.js >@@ -0,0 +1,55 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ throw new Error("Calling @toPrimitive"); >+ } >+} >+ >+try { >+ o < Symbol(2); >+ assert(true, false, "") >+} catch(e) { >+ assert(e.message, "Calling @toPrimitive", "Bad Exception when object is left operand"); >+} >+ >+try { >+ Symbol(2) < o; >+ assert(true, false, "") >+} catch(e) { >+ assert(e instanceof TypeError, true, "Bad Exception when Symbol is left operand"); >+} >+ >+o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ }, >+ >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ throw new Error("Should never call valueOf"); >+ } >+} >+ >+assert(o < 3n, true, "ToPrimitive(2n) < 3n"); >+ >+o = { >+ toString: function() { >+ throw new Error("Should never call toString"); >+ }, >+ >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+assert(o < 3n, true, "valueOf(2n) < 3n"); >+ >diff --git a/JSTests/stress/big-int-less-than-wrapped-values.js b/JSTests/stress/big-int-less-than-wrapped-values.js >new file mode 100644 >index 0000000..67a2e0b >--- /dev/null >+++ b/JSTests/stress/big-int-less-than-wrapped-values.js >@@ -0,0 +1,63 @@ >+//@ runBigIntEnabled >+ >+function assert(v, e, m) { >+ if (v !== e) >+ throw new Error(m); >+} >+ >+assert(Object(2n) < 1n, false, "Object(2n) < 1n"); >+assert(1n < Object(2n), true, "1n < Object(2n)"); >+assert(Object(2n) < Object(1n), false, "Object(2n) < Object(1n)"); >+assert(Object(1n) < Object(2n), true, "Object(1n) < Object(2n)"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ } >+} >+ >+let o2 = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ } >+} >+ >+assert(o < 1n, false, "ToPrimitive(2n) < 1n"); >+assert(1n < o, true, "1n < ToPrimitive(2n)"); >+assert(o < o2, false, "ToPrimitive(2n) < ToPrimitive(1n)"); >+assert(o2 < o, true, "ToPrimitive(1n) < ToPrimitive(2n)"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ valueOf: function() { >+ return 1n; >+ } >+} >+ >+assert(o < 1n, false, "ToPrimitive(2n) < 1n"); >+assert(1n < o, true, "1n < ToPrimitive(2n)"); >+assert(o < o2, false, "ToPrimitive(2n) < ToPrimitive(1n)"); >+assert(o2 < o, true, "ToPrimitive(1n) < ToPrimitive(2n)"); >+ >+o = { >+ toString: function() { >+ return 2n; >+ } >+} >+ >+o2 = { >+ toString: function() { >+ return 1n; >+ } >+} >+ >+assert(o < 1n, false, "ToPrimitive(2n) < 1n"); >+assert(1n < o, true, "1n < ToPrimitive(2n)"); >+assert(o < o2, false, "ToPrimitive(2n) < ToPrimitive(1n)"); >+assert(o2 < o, true, "ToPrimitive(1n) < ToPrimitive(2n)"); >+ >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 8228176..d425c37 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,32 @@ >+2018-05-14 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "<" and ">" relational operation >+ https://bugs.webkit.org/show_bug.cgi?id=185379 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch is changing the ``jsLess``` operation to follow the >+ semantics of Abstract Relational Comparison[1] that supports BigInt. >+ For that, we create 2 new helper functions ```bigIntCompareLess``` and >+ ```toPrimitiveNumeric``` that considers BigInt as a valid type to be >+ compared. >+ >+ [1] - https://tc39.github.io/proposal-bigint/#sec-abstract-relational-comparison >+ >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::unequalSign): >+ (JSC::JSBigInt::absoluteGreater): >+ (JSC::JSBigInt::absoluteLess): >+ (JSC::JSBigInt::compare): >+ (JSC::JSBigInt::absoluteCompare): >+ * runtime/JSBigInt.h: >+ * runtime/JSCJSValueInlines.h: >+ (JSC::JSValue::isPrimitive const): >+ * runtime/Operations.h: >+ (JSC::bigIntCompareLess): >+ (JSC::toPrimitiveNumeric): >+ (JSC::jsLess): >+ > 2018-05-18 Filip Pizlo <fpizlo@apple.com> > > DFG should inline InstanceOf ICs >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp >index 460775d..29d2809 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp >+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp >@@ -575,6 +575,40 @@ bool JSBigInt::equals(JSBigInt* x, JSBigInt* y) > return true; > } > >+// Produces comparison result for {leftNegative} == sign(x) != sign(y). >+JSBigInt::ComparisonResult JSBigInt::unequalSign(bool leftNegative) >+{ >+ return leftNegative ? ComparisonResult::LessThan : ComparisonResult::GreaterThan; >+} >+ >+// Produces result for |x| > |y|, with {bothNegative} == sign(x) == sign(y); >+JSBigInt::ComparisonResult JSBigInt::absoluteGreater(bool bothNegative) >+{ >+ return bothNegative ? ComparisonResult::LessThan : ComparisonResult::GreaterThan; >+} >+ >+// Produces result for |x| < |y|, with {bothNegative} == sign(x) == sign(y). >+JSBigInt::ComparisonResult JSBigInt::absoluteLess(bool bothNegative) >+{ >+ return bothNegative ? ComparisonResult::GreaterThan : ComparisonResult::LessThan; >+} >+ >+JSBigInt::ComparisonResult JSBigInt::compare(JSBigInt* x, JSBigInt* y) >+{ >+ bool xSign = x->sign(); >+ >+ if (xSign != y->sign()) >+ return unequalSign(xSign); >+ >+ int result = absoluteCompare(x, y); >+ if (result > 0) >+ return absoluteGreater(xSign); >+ if (result < 0) >+ return absoluteLess(xSign); >+ >+ return ComparisonResult::Equal; >+} >+ > inline JSBigInt::ComparisonResult JSBigInt::absoluteCompare(JSBigInt* x, JSBigInt* y) > { > ASSERT(!x->length() || x->digit(0)); >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index 67650fc..b487fc4 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -84,8 +84,16 @@ public: > std::optional<uint8_t> singleDigitValueForString(); > String toString(ExecState*, unsigned radix); > >+ enum ComparisonResult { >+ Equal, >+ Undefined, >+ GreaterThan, >+ LessThan >+ }; >+ > JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*); > bool equalsToNumber(JSValue); >+ static ComparisonResult compare(JSBigInt* x, JSBigInt* y); > > bool getPrimitiveNumber(ExecState*, double& number, JSValue& result) const; > double toNumber(ExecState*) const; >@@ -94,18 +102,13 @@ public: > > static JSBigInt* multiply(ExecState*, JSBigInt* x, JSBigInt* y); > >+ ComparisonResult static compareToDouble(JSBigInt* x, double y); >+ > static JSBigInt* divide(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* unaryMinus(VM&, JSBigInt* x); > > private: > >- enum class ComparisonResult { >- Equal, >- Undefined, >- GreaterThan, >- LessThan >- }; >- > using Digit = uintptr_t; > static constexpr const unsigned bitsPerByte = 8; > static constexpr const unsigned digitBits = sizeof(Digit) * bitsPerByte; >@@ -121,6 +124,10 @@ private: > > static uint64_t calculateMaximumCharactersRequired(unsigned length, unsigned radix, Digit lastDigit, bool sign); > >+ static ComparisonResult unequalSign(bool leftNegative); >+ static ComparisonResult absoluteGreater(bool bothNegative); >+ static ComparisonResult absoluteLess(bool bothNegative); >+ > static ComparisonResult absoluteCompare(JSBigInt* x, JSBigInt* y); > static void absoluteDivWithDigitDivisor(VM&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder); > static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result); >@@ -150,8 +157,6 @@ private: > > bool isZero(); > >- ComparisonResult static compareToDouble(JSBigInt* x, double y); >- > template <typename CharType> > static JSBigInt* parseInt(ExecState*, CharType* data, unsigned length, ErrorParseMode); > >diff --git a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >index 55b1218..3c7f70d 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >@@ -592,7 +592,7 @@ inline bool JSValue::isSymbol() const > > inline bool JSValue::isPrimitive() const > { >- return !isCell() || asCell()->isString() || asCell()->isSymbol(); >+ return !isCell() || asCell()->isString() || asCell()->isSymbol() || asCell()->isBigInt(); > } > > inline bool JSValue::isGetterSetter() const >diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h >index 495590b..fa25bd8 100644 >--- a/Source/JavaScriptCore/runtime/Operations.h >+++ b/Source/JavaScriptCore/runtime/Operations.h >@@ -157,6 +157,57 @@ ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue) > return ropeBuilder.release(); > } > >+ALWAYS_INLINE bool bigIntCompareLess(CallFrame* callFrame, JSValue v1, JSValue v2) >+{ >+ ASSERT(v1.isBigInt() || v2.isBigInt()); >+ ASSERT(v1.isPrimitive() && v2.isPrimitive()); >+ >+ VM& vm = callFrame->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ if (v1.isBigInt() && v2.isBigInt()) >+ return JSBigInt::compare(asBigInt(v1), asBigInt(v2)) == JSBigInt::LessThan; >+ >+ if (v1.isBigInt()) { >+ JSValue primValue = v2; >+ if (primValue.isString()) >+ return JSBigInt::compare(asBigInt(v1), JSBigInt::stringToBigInt(callFrame, asString(primValue)->value(callFrame))) == JSBigInt::LessThan; >+ >+ if (primValue.isBigInt()) >+ return JSBigInt::compare(asBigInt(v1), asBigInt(primValue)) == JSBigInt::LessThan; >+ >+ double numberValue = primValue.toNumber(callFrame); >+ RETURN_IF_EXCEPTION(scope, false); >+ return JSBigInt::compareToDouble(asBigInt(v1), numberValue) == JSBigInt::LessThan; >+ } >+ >+ JSValue primValue = v1; >+ if (primValue.isString()) >+ return JSBigInt::compare(JSBigInt::stringToBigInt(callFrame, asString(primValue)->value(callFrame)), asBigInt(v2)) == JSBigInt::LessThan; >+ >+ if (primValue.isBigInt()) >+ return JSBigInt::compare(asBigInt(primValue), asBigInt(v2)) == JSBigInt::LessThan; >+ >+ double numberValue = primValue.toNumber(callFrame); >+ RETURN_IF_EXCEPTION(scope, false); >+ return JSBigInt::compareToDouble(asBigInt(v2), numberValue) == JSBigInt::GreaterThan; >+} >+ >+ALWAYS_INLINE bool toPrimitiveNumeric(CallFrame* callFrame, JSValue v, JSValue& p, double& n) >+{ >+ VM& vm = callFrame->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ p = v.toPrimitive(callFrame, PreferNumber); >+ RETURN_IF_EXCEPTION(scope, false); >+ if (p.isBigInt()) >+ return true; >+ >+ n = p.toNumber(callFrame); >+ RETURN_IF_EXCEPTION(scope, false); >+ return !p.isString(); >+} >+ > // See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct > // evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value > // true, for leftFirst, for '>' pass the value false (and reverse operand order). >@@ -182,18 +233,22 @@ ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) > bool wasNotString1; > bool wasNotString2; > if (leftFirst) { >- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); >+ wasNotString1 = toPrimitiveNumeric(callFrame, v1, p1, n1); > RETURN_IF_EXCEPTION(scope, false); >- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); >+ wasNotString2 = toPrimitiveNumeric(callFrame, v2, p2, n2); > } else { >- wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); >+ wasNotString2 = toPrimitiveNumeric(callFrame, v2, p2, n2); > RETURN_IF_EXCEPTION(scope, false); >- wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); >+ wasNotString1 = toPrimitiveNumeric(callFrame, v1, p1, n1); > } > RETURN_IF_EXCEPTION(scope, false); > >- if (wasNotString1 | wasNotString2) >+ if (wasNotString1 | wasNotString2) { >+ if (p1.isBigInt() || p2.isBigInt()) >+ return bigIntCompareLess(callFrame, p1, p2); >+ > return n1 < n2; >+ } > return codePointCompareLessThan(asString(p1)->value(callFrame), asString(p2)->value(callFrame)); > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185379
:
339724
|
339808
|
340317
|
340392
|
340467
|
340791
|
340792
|
340794
|
340809
|
340818
|
341164
|
341178
|
341504
|
341508