WebKit Bugzilla
Attachment 341869 Details for
Bug 186228
: [ESNext][BigInt] Implement support for "&"
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186228-20180603154453.patch (text/plain), 30.89 KB, created by
Caio Lima
on 2018-06-03 11:44:55 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-06-03 11:44:55 PDT
Size:
30.89 KB
patch
obsolete
>Subversion Revision: 232449 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 637d7de2652e32a85652afbd8fa1bbb413d21149..78af675462adac58ed0690f4cd2a049ca2f3144f 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,31 @@ >+2018-06-03 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "&" >+ https://bugs.webkit.org/show_bug.cgi?id=186228 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch introduces support of BigInt into bitwise "&" operator into >+ LLInt and Baseline. DFG and FTL support is broken because we are not >+ changing the type prediction phase right now. We plan to support DFG >+ and FTL on separeted patches. >+ >+ * dfg/DFGOperations.cpp: >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::bitwiseAnd): >+ (JSC::JSBigInt::absoluteBitwiseOp): >+ (JSC::JSBigInt::absoluteAnd): >+ (JSC::JSBigInt::absoluteOr): >+ (JSC::JSBigInt::absoluteAndNot): >+ (JSC::JSBigInt::absoluteAddOne): >+ (JSC::JSBigInt::absoluteSubOne): >+ * runtime/JSBigInt.h: >+ * runtime/JSCJSValue.h: >+ * runtime/JSCJSValueInlines.h: >+ (JSC::JSValue::toBigIntOrInt32 const): >+ > 2018-06-02 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for addition operations >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index 26de11188561b5cd1bb900381a6f412c48a87fc6..b6e77d5868c469fd969f5ed13fbce94b3251cab2 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -346,11 +346,22 @@ EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValu > JSValue op1 = JSValue::decode(encodedOp1); > JSValue op2 = JSValue::decode(encodedOp2); > >- int32_t a = op1.toInt32(exec); >+ auto leftNumeric = op1.toBigIntOrInt32(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); >- scope.release(); >- int32_t b = op2.toInt32(exec); >- return JSValue::encode(jsNumber(a & b)); >+ auto rightNumeric = op2.toBigIntOrInt32(exec); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ >+ if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { >+ if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { >+ JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ return JSValue::encode(result); >+ } >+ >+ return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in bitwise and operation."); >+ } >+ >+ return JSValue::encode(jsNumber(WTF::get<int32_t>(leftNumeric) & WTF::get<int32_t>(rightNumeric))); > } > > EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) >@@ -470,7 +481,7 @@ EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue e > return JSValue::encode(result); > } > >- return throwVMTypeError(exec, scope, "Invalid operand in BigInt operation."); >+ return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in division operation."); > } > > scope.release(); >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index 1dafc63caff78ebafa37f06a2b5d6748dde3fee3..d534a95ff17824fbabbfd8ae7a1f0cb809a33b87 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -646,11 +646,21 @@ SLOW_PATH_DECL(slow_path_unsigned) > SLOW_PATH_DECL(slow_path_bitand) > { > BEGIN(); >- int32_t a = OP_C(2).jsValue().toInt32(exec); >- if (UNLIKELY(throwScope.exception())) >- RETURN(JSValue()); >- int32_t b = OP_C(3).jsValue().toInt32(exec); >- RETURN(jsNumber(a & b)); >+ auto leftNumeric = OP_C(2).jsValue().toBigIntOrInt32(exec); >+ CHECK_EXCEPTION(); >+ auto rightNumeric = OP_C(3).jsValue().toBigIntOrInt32(exec); >+ CHECK_EXCEPTION(); >+ if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) { >+ if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) { >+ JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); >+ CHECK_EXCEPTION(); >+ RETURN(result); >+ } >+ >+ THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise and operation.")); >+ } >+ >+ RETURN(jsNumber(WTF::get<int32_t>(leftNumeric) & WTF::get<int32_t>(rightNumeric))); > } > > SLOW_PATH_DECL(slow_path_bitor) >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp >index 0fde648ea4877c1f3692e86fa8b4f1306f74686c..2915a2a4c5f68737b975e05b3eceaaaf2cdf649e 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp >+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp >@@ -381,6 +381,32 @@ JSBigInt* JSBigInt::sub(VM& vm, JSBigInt* x, JSBigInt* y) > return absoluteSub(vm, y, x, !xSign); > } > >+JSBigInt* JSBigInt::bitwiseAnd(ExecState* exec, JSBigInt* x, JSBigInt* y) >+{ >+ VM& vm = exec->vm(); >+ if (!x->sign() && !y->sign()) >+ return absoluteAnd(exec, x, y); >+ >+ if (x->sign() && y->sign()) { >+ int resultLength = std::max(x->length(), y->length()) + 1; >+ // (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) >+ // == -(((x-1) | (y-1)) + 1) >+ JSBigInt* result = absoluteSubOne(vm, x, resultLength); >+ JSBigInt* y1 = absoluteSubOne(vm, y, y->length()); >+ result = absoluteOr(exec, result, y1); >+ >+ return absoluteAddOne(vm, result, true); >+ } >+ >+ ASSERT(x->sign() != y->sign()); >+ // Assume that x is the positive BigInt. >+ if (x->sign()) >+ std::swap(x, y); >+ >+ // x & (-y) == x & ~(y-1) == x & ~(y-1) >+ return absoluteAndNot(exec, x, absoluteSubOne(vm, y, y->length())); >+} >+ > #if USE(JSVALUE32_64) > #define HAVE_TWO_DIGIT 1 > typedef uint64_t TwoDigit; >@@ -993,6 +1019,134 @@ JSBigInt* JSBigInt::absoluteLeftShiftAlwaysCopy(VM& vm, JSBigInt* x, unsigned sh > return result; > } > >+// Helper for Absolute{And,AndNot,Or,Xor}. >+// Performs the given binary {op} on digit pairs of {x} and {y}; when the >+// end of the shorter of the two is reached, {extraDigits} configures how >+// remaining digits in the longer input (if {symmetric} == Symmetric, in >+// {x} otherwise) are handled: copied to the result or ignored. >+// Example: >+// y: [ y2 ][ y1 ][ y0 ] >+// x: [ x3 ][ x2 ][ x1 ][ x0 ] >+// | | | | >+// (Copy) (op) (op) (op) >+// | | | | >+// v v v v >+// result: [ 0 ][ x3 ][ r2 ][ r1 ][ r0 ] >+inline JSBigInt* JSBigInt::absoluteBitwiseOp(ExecState* exec, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling extraDigits, SymmetricOp symmetric, std::function<Digit(Digit, Digit)> op) >+{ >+ VM& vm = exec->vm(); >+ >+ unsigned xLength = x->length(); >+ unsigned yLength = y->length(); >+ unsigned numPairs = yLength; >+ if (xLength < yLength) { >+ numPairs = xLength; >+ if (symmetric == SymmetricOp::Symmetric) { >+ std::swap(x, y); >+ std::swap(xLength, yLength); >+ } >+ } >+ >+ ASSERT(numPairs == std::min(xLength, yLength)); >+ unsigned resultLength = extraDigits == ExtraDigitsHandling::Copy ? xLength : numPairs; >+ JSBigInt* result = createWithLength(vm, resultLength); >+ >+ unsigned i = 0; >+ for (; i < numPairs; i++) >+ result->setDigit(i, op(x->digit(i), y->digit(i))); >+ >+ if (extraDigits == ExtraDigitsHandling::Copy) { >+ for (; i < xLength; i++) >+ result->setDigit(i, x->digit(i)); >+ } >+ >+ for (; i < resultLength; i++) >+ result->setDigit(i, 0); >+ >+ return result->rightTrim(vm); >+} >+ >+JSBigInt* JSBigInt::absoluteAnd(ExecState* exec, JSBigInt* x, JSBigInt* y) >+{ >+ auto digitOperation = [](Digit a, Digit b) { >+ return a & b; >+ }; >+ >+ return absoluteBitwiseOp(exec, x, y, ExtraDigitsHandling::Skip, SymmetricOp::Symmetric, digitOperation); >+} >+ >+JSBigInt* JSBigInt::absoluteOr(ExecState* exec, JSBigInt* x, JSBigInt* y) >+{ >+ auto digitOperation = [](Digit a, Digit b) { >+ return a | b; >+ }; >+ >+ return absoluteBitwiseOp(exec, x, y, ExtraDigitsHandling::Copy, SymmetricOp::Symmetric, digitOperation); >+} >+ >+JSBigInt* JSBigInt::absoluteAndNot(ExecState* exec, JSBigInt* x, JSBigInt* y) >+{ >+ auto digitOperation = [](Digit a, Digit b) { >+ return a & ~b; >+ }; >+ >+ return absoluteBitwiseOp(exec, x, y, ExtraDigitsHandling::Copy, SymmetricOp::NotSymmetric, digitOperation); >+} >+ >+JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, bool sign) >+{ >+ unsigned inputLength = x->length(); >+ // The addition will overflow into a new digit if all existing digits are >+ // at maximum. >+ bool willOverflow = true; >+ for (unsigned i = 0; i < inputLength; i++) { >+ if (std::numeric_limits<Digit>::max() != x->digit(i)) { >+ willOverflow = false; >+ break; >+ } >+ } >+ >+ unsigned resultLength = inputLength + willOverflow; >+ JSBigInt* result = createWithLength(vm, resultLength); >+ >+ Digit carry = 1; >+ for (unsigned i = 0; i < inputLength; i++) { >+ Digit newCarry = 0; >+ result->setDigit(i, digitAdd(x->digit(i), carry, newCarry)); >+ carry = newCarry; >+ } >+ >+ if (resultLength > inputLength) >+ result->setDigit(inputLength, carry); >+ else >+ ASSERT(!carry); >+ >+ result->setSign(sign); >+ return result->rightTrim(vm); >+} >+ >+// Like the above, but you can specify that the allocated result should have >+// length {resultLength}, which must be at least as large as {x->length()}. >+JSBigInt* JSBigInt::absoluteSubOne(VM& vm, JSBigInt* x, unsigned resultLength) >+{ >+ ASSERT(!x->isZero()); >+ ASSERT(resultLength >= x->length()); >+ JSBigInt* result = createWithLength(vm, resultLength); >+ >+ unsigned length = x->length(); >+ Digit borrow = 1; >+ for (unsigned i = 0; i < length; i++) { >+ Digit newBorrow = 0; >+ result->setDigit(i, digitSub(x->digit(i), borrow, newBorrow)); >+ borrow = newBorrow; >+ } >+ ASSERT(!borrow); >+ for (unsigned i = length; i < resultLength; i++) >+ result->setDigit(i, borrow); >+ >+ return result->rightTrim(vm); >+} >+ > // Lookup table for the maximum number of bits required per character of a > // base-N string representation of a number. To increase accuracy, the array > // value is the actual value multiplied by 32. To generate this table: >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index 4af7a5f7f24366c37450c9642e412605b06043d5..07fe4443b63e91bf9865b3c0df18ebb456a9ea50 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -112,7 +112,9 @@ public: > static JSBigInt* divide(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* remainder(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* unaryMinus(VM&, JSBigInt* x); >- >+ >+ static JSBigInt* bitwiseAnd(ExecState*, JSBigInt* x, JSBigInt* y); >+ > private: > > using Digit = uintptr_t; >@@ -148,6 +150,24 @@ private: > Digit absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex); > void inplaceRightShift(unsigned shift); > >+ enum class ExtraDigitsHandling { >+ Copy, >+ Skip >+ }; >+ >+ enum class SymmetricOp { >+ Symmetric, >+ NotSymmetric >+ }; >+ >+ static JSBigInt* absoluteBitwiseOp(ExecState*, JSBigInt* x, JSBigInt* y, ExtraDigitsHandling, SymmetricOp, std::function<Digit(Digit, Digit)> op); >+ static JSBigInt* absoluteAnd(ExecState*, JSBigInt* x, JSBigInt* y); >+ static JSBigInt* absoluteOr(ExecState*, JSBigInt* x, JSBigInt* y); >+ static JSBigInt* absoluteAndNot(ExecState*, JSBigInt* x, JSBigInt* y); >+ >+ static JSBigInt* absoluteAddOne(VM&, JSBigInt* x, bool sign); >+ static JSBigInt* absoluteSubOne(VM&, JSBigInt* x, unsigned resultLength); >+ > // Digit arithmetic helpers. > static Digit digitAdd(Digit a, Digit b, Digit& carry); > static Digit digitSub(Digit a, Digit b, Digit& borrow); >diff --git a/Source/JavaScriptCore/runtime/JSCJSValue.h b/Source/JavaScriptCore/runtime/JSCJSValue.h >index 94d5a515e96c9f21aed82bb0bec9e6da69662af3..af0fcb0d9797f9316825a8c711594811e307b69d 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValue.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValue.h >@@ -259,6 +259,7 @@ public: > double toNumber(ExecState*) const; > > Variant<JSBigInt*, double> toNumeric(ExecState*) const; >+ Variant<JSBigInt*, int32_t> toBigIntOrInt32(ExecState*) const; > > // toNumber conversion if it can be done without side effects. > std::optional<double> toNumberFromPrimitive() const; >diff --git a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >index 4ba9d507deb5fb5c566ee675b2cf11b10df49c11..3edbfd9d49a6cd4bcd168db489df8b134661c07a 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >@@ -750,6 +750,24 @@ ALWAYS_INLINE Variant<JSBigInt*, double> JSValue::toNumeric(ExecState* exec) con > return value; > } > >+ALWAYS_INLINE Variant<JSBigInt*, int32_t> JSValue::toBigIntOrInt32(ExecState* exec) const >+{ >+ if (isInt32()) >+ return asInt32(); >+ if (isBigInt()) >+ return asBigInt(*this); >+ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ JSValue primValue = this->toPrimitive(exec, PreferNumber); >+ RETURN_IF_EXCEPTION(scope, 0); >+ if (primValue.isBigInt()) >+ return asBigInt(primValue); >+ int32_t value = primValue.toInt32(exec); >+ RETURN_IF_EXCEPTION(scope, 0); >+ return value; >+} >+ > inline JSObject* JSValue::toObject(ExecState* exec) const > { > return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject()); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 574464a827f1fa70d6f6002c6dd5bdedd1008fd4..812dc8f2db76d47aab6e58980d905b617a931e3f 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,14 @@ >+2018-06-03 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "&" >+ https://bugs.webkit.org/show_bug.cgi?id=186228 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Fixing the default usage of "--useDollarVM=1" to enable use more options. >+ >+ * Scripts/run-jsc: >+ > 2018-06-02 Keith Miller <keith_miller@apple.com> > > run-jsc should pass the option to use dollar vm by default >diff --git a/Tools/Scripts/run-jsc b/Tools/Scripts/run-jsc >index 26374bc7c86824c2e226b78edf1c18497391445f..ddb244e302db442dd5f2fbf66257e6299a641725 100755 >--- a/Tools/Scripts/run-jsc >+++ b/Tools/Scripts/run-jsc >@@ -50,9 +50,9 @@ setConfiguration(); > my $jsc; > if ($debugger) { > my $debuggerCmd = defined($ENV{"DEBUGGER"}) ? $ENV{"DEBUGGER"} : "lldb"; >- $jsc = $debuggerCmd . " " . File::Spec->catfile(jscProductDir(), "jsc -- --useDollarVM=1") . "@ARGV"; >+ $jsc = $debuggerCmd . " " . File::Spec->catfile(jscProductDir(), "jsc -- --useDollarVM=1 ") . "@ARGV"; > } else { >- $jsc = File::Spec->catfile(jscProductDir(), "jsc --useDollarVM=1") . "@ARGV"; >+ $jsc = File::Spec->catfile(jscProductDir(), "jsc --useDollarVM=1 ") . "@ARGV"; > } > > my $dyld = jscProductDir(); >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index f4d2b34ab9c030827a5a15b1e5dd988b90d657ba..73175652940153035e8035062c3dc62dd73a2dac 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,18 @@ >+2018-06-03 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "&" >+ https://bugs.webkit.org/show_bug.cgi?id=186228 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * bigIntTests.yaml: >+ * stress/big-int-bitwise-and-general.js: Added. >+ * stress/big-int-bitwise-and-jit.js: Added. >+ * stress/big-int-bitwise-and-memory-stress.js: Added. >+ * stress/big-int-bitwise-and-to-primitive-precedence.js: Added. >+ * stress/big-int-bitwise-and-type-error.js: Added. >+ * stress/big-int-bitwise-and-wrapped-value.js: Added. >+ > 2018-06-02 Caio Lima <ticaiolima@gmail.com> > > [ESNext][BigInt] Implement support for addition operations >diff --git a/JSTests/bigIntTests.yaml b/JSTests/bigIntTests.yaml >index 787834ae639f6a5c00b7c9facaff54c3762f096f..0e2ac7e6d53162831f195a24281da850fbdafb2e 100644 >--- a/JSTests/bigIntTests.yaml >+++ b/JSTests/bigIntTests.yaml >@@ -222,3 +222,22 @@ > > - path: stress/big-int-subtraction-type-error.js > cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-general.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-jit.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-memory-stress.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-to-primitive-precedence.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-type-error.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-bitwise-and-wrapped-value.js >+ cmd: runBigIntEnabled >+ >diff --git a/JSTests/stress/big-int-bitwise-and-general.js b/JSTests/stress/big-int-bitwise-and-general.js >new file mode 100644 >index 0000000000000000000000000000000000000000..56e798e5006dbebc86d979fdbfdfbbbf817d479a >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-general.js >@@ -0,0 +1,97 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+assert.sameValue = function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+} >+ >+assert.sameValue(0b00n & 0b00n, 0b00n, "0b00n & 0b00n === 0b00n"); >+assert.sameValue(0b00n & 0b01n, 0b00n, "0b00n & 0b01n === 0b00n"); >+assert.sameValue(0b01n & 0b00n, 0b00n, "0b01n & 0b00n === 0b00n"); >+assert.sameValue(0b00n & 0b10n, 0b00n, "0b00n & 0b10n === 0b00n"); >+assert.sameValue(0b10n & 0b00n, 0b00n, "0b10n & 0b00n === 0b00n"); >+assert.sameValue(0b00n & 0b11n, 0b00n, "0b00n & 0b11n === 0b00n"); >+assert.sameValue(0b11n & 0b00n, 0b00n, "0b11n & 0b00n === 0b00n"); >+assert.sameValue(0b01n & 0b01n, 0b01n, "0b01n & 0b01n === 0b01n"); >+assert.sameValue(0b01n & 0b10n, 0b00n, "0b01n & 0b10n === 0b00n"); >+assert.sameValue(0b10n & 0b01n, 0b00n, "0b10n & 0b01n === 0b00n"); >+assert.sameValue(0b01n & 0b11n, 0b01n, "0b01n & 0b11n === 0b01n"); >+assert.sameValue(0b11n & 0b01n, 0b01n, "0b11n & 0b01n === 0b01n"); >+assert.sameValue(0b10n & 0b10n, 0b10n, "0b10n & 0b10n === 0b10n"); >+assert.sameValue(0b10n & 0b11n, 0b10n, "0b10n & 0b11n === 0b10n"); >+assert.sameValue(0b11n & 0b10n, 0b10n, "0b11n & 0b10n === 0b10n"); >+assert.sameValue(0xffffffffn & 0n, 0n, "0xffffffffn & 0n === 0n"); >+assert.sameValue(0n & 0xffffffffn, 0n, "0n & 0xffffffffn === 0n"); >+assert.sameValue(0xffffffffn & 0xffffffffn, 0xffffffffn, "0xffffffffn & 0xffffffffn === 0xffffffffn"); >+assert.sameValue(0xffffffffffffffffn & 0n, 0n, "0xffffffffffffffffn & 0n === 0n"); >+assert.sameValue(0n & 0xffffffffffffffffn, 0n, "0n & 0xffffffffffffffffn === 0n"); >+assert.sameValue(0xffffffffffffffffn & 0xffffffffn, 0xffffffffn, "0xffffffffffffffffn & 0xffffffffn === 0xffffffffn"); >+assert.sameValue(0xffffffffn & 0xffffffffffffffffn, 0xffffffffn, "0xffffffffn & 0xffffffffffffffffn === 0xffffffffn"); >+assert.sameValue( >+ 0xffffffffffffffffn & 0xffffffffffffffffn, 0xffffffffffffffffn, >+ "0xffffffffffffffffn & 0xffffffffffffffffn === 0xffffffffffffffffn"); >+assert.sameValue( >+ 0xbf2ed51ff75d380fd3be813ec6185780n & 0x4aabef2324cedff5387f1f65n, 0x42092803008e813400181700n, >+ "0xbf2ed51ff75d380fd3be813ec6185780n & 0x4aabef2324cedff5387f1f65n === 0x42092803008e813400181700n"); >+assert.sameValue( >+ 0x4aabef2324cedff5387f1f65n & 0xbf2ed51ff75d380fd3be813ec6185780n, 0x42092803008e813400181700n, >+ "0x4aabef2324cedff5387f1f65n & 0xbf2ed51ff75d380fd3be813ec6185780n === 0x42092803008e813400181700n"); >+assert.sameValue(0n & -1n, 0n, "0n & -1n === 0n"); >+assert.sameValue(-1n & 0n, 0n, "-1n & 0n === 0n"); >+assert.sameValue(0n & -2n, 0n, "0n & -2n === 0n"); >+assert.sameValue(-2n & 0n, 0n, "-2n & 0n === 0n"); >+assert.sameValue(1n & -2n, 0n, "1n & -2n === 0n"); >+assert.sameValue(-2n & 1n, 0n, "-2n & 1n === 0n"); >+assert.sameValue(2n & -2n, 2n, "2n & -2n === 2n"); >+assert.sameValue(-2n & 2n, 2n, "-2n & 2n === 2n"); >+assert.sameValue(2n & -3n, 0n, "2n & -3n === 0n"); >+assert.sameValue(-3n & 2n, 0n, "-3n & 2n === 0n"); >+assert.sameValue(-1n & -2n, -2n, "-1n & -2n === -2n"); >+assert.sameValue(-2n & -1n, -2n, "-2n & -1n === -2n"); >+assert.sameValue(-2n & -2n, -2n, "-2n & -2n === -2n"); >+assert.sameValue(-2n & -3n, -4n, "-2n & -3n === -4n"); >+assert.sameValue(-3n & -2n, -4n, "-3n & -2n === -4n"); >+assert.sameValue(0xffffffffn & -1n, 0xffffffffn, "0xffffffffn & -1n === 0xffffffffn"); >+assert.sameValue(-1n & 0xffffffffn, 0xffffffffn, "-1n & 0xffffffffn === 0xffffffffn"); >+assert.sameValue(0xffffffffffffffffn & -1n, 0xffffffffffffffffn, "0xffffffffffffffffn & -1n === 0xffffffffffffffffn"); >+assert.sameValue(-1n & 0xffffffffffffffffn, 0xffffffffffffffffn, "-1n & 0xffffffffffffffffn === 0xffffffffffffffffn"); >+assert.sameValue( >+ 0xbf2ed51ff75d380fd3be813ec6185780n & -0x4aabef2324cedff5387f1f65n, 0xbf2ed51fb554100cd330000ac6004080n, >+ "0xbf2ed51ff75d380fd3be813ec6185780n & -0x4aabef2324cedff5387f1f65n === 0xbf2ed51fb554100cd330000ac6004080n"); >+assert.sameValue( >+ -0x4aabef2324cedff5387f1f65n & 0xbf2ed51ff75d380fd3be813ec6185780n, 0xbf2ed51fb554100cd330000ac6004080n, >+ "-0x4aabef2324cedff5387f1f65n & 0xbf2ed51ff75d380fd3be813ec6185780n === 0xbf2ed51fb554100cd330000ac6004080n"); >+assert.sameValue( >+ -0xbf2ed51ff75d380fd3be813ec6185780n & 0x4aabef2324cedff5387f1f65n, 0x8a2c72024405ec138670800n, >+ "-0xbf2ed51ff75d380fd3be813ec6185780n & 0x4aabef2324cedff5387f1f65n === 0x8a2c72024405ec138670800n"); >+assert.sameValue( >+ 0x4aabef2324cedff5387f1f65n & -0xbf2ed51ff75d380fd3be813ec6185780n, 0x8a2c72024405ec138670800n, >+ "0x4aabef2324cedff5387f1f65n & -0xbf2ed51ff75d380fd3be813ec6185780n === 0x8a2c72024405ec138670800n"); >+assert.sameValue( >+ -0xbf2ed51ff75d380fd3be813ec6185780n & -0x4aabef2324cedff5387f1f65n, -0xbf2ed51fffffff2ff7fedffffe7f5f80n, >+ "-0xbf2ed51ff75d380fd3be813ec6185780n & -0x4aabef2324cedff5387f1f65n === -0xbf2ed51fffffff2ff7fedffffe7f5f80n"); >+assert.sameValue( >+ -0x4aabef2324cedff5387f1f65n & -0xbf2ed51ff75d380fd3be813ec6185780n, -0xbf2ed51fffffff2ff7fedffffe7f5f80n, >+ "-0x4aabef2324cedff5387f1f65n & -0xbf2ed51ff75d380fd3be813ec6185780n === -0xbf2ed51fffffff2ff7fedffffe7f5f80n"); >+assert.sameValue(-0xffffffffn & 0n, 0n, "-0xffffffffn & 0n === 0n"); >+assert.sameValue(0n & -0xffffffffn, 0n, "0n & -0xffffffffn === 0n"); >+assert.sameValue( >+ -0xffffffffffffffffn & 0x10000000000000000n, 0x10000000000000000n, >+ "-0xffffffffffffffffn & 0x10000000000000000n === 0x10000000000000000n"); >+assert.sameValue( >+ 0x10000000000000000n & -0xffffffffffffffffn, 0x10000000000000000n, >+ "0x10000000000000000n & -0xffffffffffffffffn === 0x10000000000000000n"); >+assert.sameValue( >+ -0xffffffffffffffffffffffffn & 0x10000000000000000n, 0n, >+ "-0xffffffffffffffffffffffffn & 0x10000000000000000n === 0n"); >+assert.sameValue( >+ 0x10000000000000000n & -0xffffffffffffffffffffffffn, 0n, >+ "0x10000000000000000n & -0xffffffffffffffffffffffffn === 0n"); >diff --git a/JSTests/stress/big-int-bitwise-and-jit.js b/JSTests/stress/big-int-bitwise-and-jit.js >new file mode 100644 >index 0000000000000000000000000000000000000000..901e91d51dde1f0fe8ada88e6f7a80adaecea8b4 >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-jit.js >@@ -0,0 +1,19 @@ >+//@ runBigIntEnabled >+ >+let assert = { >+ sameValue: function(i, e, m) { >+ if (i !== e) >+ throw new Error(m); >+ } >+} >+ >+function bigIntBitAnd(x, y) { >+ return x & y; >+} >+noInline(bigIntBitAnd); >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntBitAnd(0b11n, 0b1010n); >+ assert.sameValue(r, 0b10n, 0b11n + " & " + 0b1010n + " = " + r); >+} >+ >diff --git a/JSTests/stress/big-int-bitwise-and-memory-stress.js b/JSTests/stress/big-int-bitwise-and-memory-stress.js >new file mode 100644 >index 0000000000000000000000000000000000000000..61e7ae3b9c91c790d93bff3d458b5141f0a9454c >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-memory-stress.js >@@ -0,0 +1,14 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+let a = 0b11n; >+for (let i = 0; i < 1000000; i++) { >+ a &= 0b01n; >+} >+ >+assert(a === 0b01n); >+ >diff --git a/JSTests/stress/big-int-bitwise-and-to-primitive-precedence.js b/JSTests/stress/big-int-bitwise-and-to-primitive-precedence.js >new file mode 100644 >index 0000000000000000000000000000000000000000..bfa8e161fdf41798aef166475bedc1182a475977 >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-to-primitive-precedence.js >@@ -0,0 +1,29 @@ >+//@ runBigIntEnabled >+ >+assert = { >+ sameValue: function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+ } >+}; >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ throw new Error("Bad"); >+ } >+}; >+ >+try{ >+ o & Symbol("2"); >+ assert.sameValue(true, false, "Exception expected to be throwed, but executed without error"); >+} catch (e) { >+ assert.sameValue(e.message, "Bad", "Expected to throw Error('Bad'), but got: " + e); >+} >+ >+try{ >+ Symbol("2") & o; >+ assert.sameValue(true, false, "Exception expected to be throwed, but executed without error"); >+} catch (e) { >+ assert.sameValue(e instanceof TypeError, true, "Expected to throw TypeError, but got: " + e) >+} >+ >diff --git a/JSTests/stress/big-int-bitwise-and-type-error.js b/JSTests/stress/big-int-bitwise-and-type-error.js >new file mode 100644 >index 0000000000000000000000000000000000000000..dcb7768bac7beb1aec5b2769b76011ee41da5d1d >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-type-error.js >@@ -0,0 +1,106 @@ >+//@ runBigIntEnabled >+ >+function assert(a, message) { >+ if (!a) >+ throw new Error(message); >+} >+ >+function assertThrowTypeError(a, b, message) { >+ try { >+ let n = a & b; >+ assert(false, message + ": Should throw TypeError, but executed without exception"); >+ } catch (e) { >+ assert(e instanceof TypeError, message + ": expected TypeError, got: " + e); >+ } >+} >+ >+assertThrowTypeError(30n, "foo", "BigInt & String"); >+assertThrowTypeError("bar", 18757382984821n, "String & BigInt"); >+assertThrowTypeError(30n, Symbol("foo"), "BigInt & Symbol"); >+assertThrowTypeError(Symbol("bar"), 18757382984821n, "Symbol & BigInt"); >+assertThrowTypeError(30n, 3320, "BigInt & Int32"); >+assertThrowTypeError(33256, 18757382984821n, "Int32 & BigInt"); >+assertThrowTypeError(30n, 0.543, "BigInt & Double"); >+assertThrowTypeError(230.19293, 18757382984821n, "Double & BigInt"); >+assertThrowTypeError(30n, NaN, "BigInt & NaN"); >+assertThrowTypeError(NaN, 18757382984821n, "NaN & BigInt"); >+assertThrowTypeError(30n, NaN, "BigInt & NaN"); >+assertThrowTypeError(NaN, 18757382984821n, "NaN & BigInt"); >+assertThrowTypeError(30n, +Infinity, "BigInt & NaN"); >+assertThrowTypeError(+Infinity, 18757382984821n, "NaN & BigInt"); >+assertThrowTypeError(30n, -Infinity, "BigInt & -Infinity"); >+assertThrowTypeError(-Infinity, 18757382984821n, "-Infinity & BigInt"); >+assertThrowTypeError(30n, null, "BigInt & null"); >+assertThrowTypeError(null, 18757382984821n, "null & BigInt"); >+assertThrowTypeError(30n, undefined, "BigInt & undefined"); >+assertThrowTypeError(undefined, 18757382984821n, "undefined & BigInt"); >+assertThrowTypeError(30n, true, "BigInt & true"); >+assertThrowTypeError(true, 18757382984821n, "true & BigInt"); >+assertThrowTypeError(30n, false, "BigInt & false"); >+assertThrowTypeError(false, 18757382984821n, "false & BigInt"); >+ >+// Error when returning from object >+ >+let o = { >+ valueOf: function () { return Symbol("Foo"); } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.valueOf returning Symbol"); >+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Symbol & BigInt"); >+ >+o = { >+ valueOf: function () { return 33256; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.valueOf returning Int32"); >+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Int32 & BigInt"); >+ >+o = { >+ valueOf: function () { return 0.453; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.valueOf returning Double"); >+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Double & BigInt"); >+ >+o = { >+ toString: function () { return Symbol("Foo"); } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.toString returning Symbol"); >+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Symbol & BigInt"); >+ >+o = { >+ toString: function () { return 33256; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.toString returning Int32"); >+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Int32 & BigInt"); >+ >+o = { >+ toString: function () { return 0.453; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.toString returning Double"); >+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Double & BigInt"); >+ >+o = { >+ [Symbol.toPrimitive]: function () { return Symbol("Foo"); } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.@@toPrimitive returning Symbol"); >+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Symbol & BigInt"); >+ >+o = { >+ [Symbol.toPrimitive]: function () { return 33256; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.@@toPrimitive returning Int32"); >+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Int32 & BigInt"); >+ >+o = { >+ [Symbol.toPrimitive]: function () { return 0.453; } >+}; >+ >+assertThrowTypeError(30n, o, "BigInt & Object.@@toPrimitive returning Double"); >+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Double & BigInt"); >+ >diff --git a/JSTests/stress/big-int-bitwise-and-wrapped-value.js b/JSTests/stress/big-int-bitwise-and-wrapped-value.js >new file mode 100644 >index 0000000000000000000000000000000000000000..c4377f41abd357f2079267ccb52848747d720653 >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-and-wrapped-value.js >@@ -0,0 +1,37 @@ >+//@ runBigIntEnabled >+ >+assert = { >+ sameValue: function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+ } >+}; >+ >+function testBitAnd(x, y, z, message) { >+ assert.sameValue(x & y, z, message); >+ assert.sameValue(y & x, z, message); >+} >+ >+testBitAnd(Object(0b10n), 0b01n, 0b00n, "ToPrimitive: unbox object with internal slot"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 0b10n; >+ } >+}; >+testBitAnd(o, 0b01n, 0b00n, "ToPrimitive: @@toPrimitive"); >+ >+o = { >+ valueOf: function() { >+ return 0b10n; >+ } >+}; >+testBitAnd(o, 0b01n, 0b00n, "ToPrimitive: valueOf"); >+ >+o = { >+ toString: function() { >+ return 0b10n; >+ } >+} >+testBitAnd(o, 0b01n, 0b00n, "ToPrimitive: toString"); >+
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 186228
:
341869
|
341875
|
342234
|
342235
|
342236
|
342243
|
342259
|
342278
|
344302
|
344566
|
350526
|
350532
|
351082
|
351167
|
351214