WebKit Bugzilla
Attachment 340161 Details for
Bug 183996
: [ESNext][BigInt] Implement support for "/" operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-183996-20180511002058.patch (text/plain), 41.86 KB, created by
Caio Lima
on 2018-05-10 20:21:02 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-05-10 20:21:02 PDT
Size:
41.86 KB
patch
obsolete
>Subversion Revision: 231673 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 270d952a6b008ecceb63924df51a868fdd761879..c1b6a6efc9b0bf4ac121f0ffef0f4b9bce14bfff 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,31 @@ >+2018-05-11 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "/" operation >+ https://bugs.webkit.org/show_bug.cgi?id=183996 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch is introducing the support for BigInt into divide >+ operation int LLInt and JIT layers. >+ >+ * dfg/DFGOperations.cpp: >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::divide): >+ (JSC::JSBigInt::copy): >+ (JSC::JSBigInt::unaryMinus): >+ (JSC::JSBigInt::absoluteCompare): >+ (JSC::JSBigInt::absoluteDivLarge): >+ (JSC::JSBigInt::productGreaterThan): >+ (JSC::JSBigInt::inplaceAdd): >+ (JSC::JSBigInt::inplaceSub): >+ (JSC::JSBigInt::inplaceRightShift): >+ (JSC::JSBigInt::specialLeftShift): >+ (JSC::JSBigInt::digit): >+ (JSC::JSBigInt::setDigit): >+ * runtime/JSBigInt.h: >+ > 2018-05-10 Filip Pizlo <fpizlo@apple.com> > > DFG CFA should pick the right time to inject OSR entry data >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index 9c2f44b7869a0e92602ec148cb02a5e28b3842c2..11e4fc7fb8ab63dac3933a000b257031402aa43e 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -75,6 +75,7 @@ > #include "TypedArrayInlines.h" > #include "VMInlines.h" > #include <wtf/InlineASM.h> >+#include <wtf/Variant.h> > > #if ENABLE(JIT) > #if ENABLE(DFG_JIT) >@@ -424,10 +425,25 @@ EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue e > JSValue op1 = JSValue::decode(encodedOp1); > JSValue op2 = JSValue::decode(encodedOp2); > >- double a = op1.toNumber(exec); >+ auto leftNumeric = op1.toNumeric(exec); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ auto rightNumeric = op2.toNumeric(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::divide(*exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric)); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ return JSValue::encode(result); >+ } >+ >+ return throwVMTypeError(exec, scope, "Invalid operand in BigInt operation."); >+ } >+ > scope.release(); >- double b = op2.toNumber(exec); >+ >+ double a = WTF::get<double>(leftNumeric); >+ double b = WTF::get<double>(rightNumeric); > return JSValue::encode(jsNumber(a / b)); > } > >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index a550fc09b9a82de0f11c18f75facfcac5cf3cb10..6492cfaa74d83a7c50b346b809b7d41fd3127517 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -518,12 +518,25 @@ SLOW_PATH_DECL(slow_path_div) > BEGIN(); > JSValue left = OP_C(2).jsValue(); > JSValue right = OP_C(3).jsValue(); >- double a = left.toNumber(exec); >- if (UNLIKELY(throwScope.exception())) >- RETURN(JSValue()); >- double b = right.toNumber(exec); >- if (UNLIKELY(throwScope.exception())) >- RETURN(JSValue()); >+ auto leftNumeric = left.toNumeric(exec); >+ CHECK_EXCEPTION(); >+ auto rightNumeric = right.toNumeric(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)) { >+ JSValue result(JSBigInt::divide(*exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))); >+ CHECK_EXCEPTION(); >+ RETURN_WITH_PROFILING(result, { >+ updateArithProfileForBinaryArithOp(exec, pc, result, left, right); >+ }); >+ } >+ >+ THROW(createTypeError(exec, "Invalid mix of BigInt and other type in division.")); >+ } >+ >+ double a = WTF::get<double>(leftNumeric); >+ double b = WTF::get<double>(rightNumeric); > JSValue result = jsNumber(a / b); > RETURN_WITH_PROFILING(result, { > updateArithProfileForBinaryArithOp(exec, pc, result, left, right); >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp >index 5fad08fc5c653a3e612a37c28501f2137fd46315..9c5de17600db869da25c9e3a278a8b9411e69250 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp >+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp >@@ -68,7 +68,7 @@ void JSBigInt::visitChildren(JSCell* cell, SlotVisitor& visitor) > Base::visitChildren(thisObject, visitor); > } > >-JSBigInt::JSBigInt(VM& vm, Structure* structure, int length) >+JSBigInt::JSBigInt(VM& vm, Structure* structure, unsigned length) > : Base(vm, structure) > , m_length(length) > { } >@@ -92,13 +92,13 @@ JSBigInt* JSBigInt::createZero(VM& vm) > return zeroBigInt; > } > >-size_t JSBigInt::allocationSize(int length) >+size_t JSBigInt::allocationSize(unsigned length) > { > size_t sizeWithPadding = WTF::roundUpToMultipleOf<sizeof(size_t)>(sizeof(JSBigInt)); > return sizeWithPadding + length * sizeof(Digit); > } > >-JSBigInt* JSBigInt::createWithLength(VM& vm, int length) >+JSBigInt* JSBigInt::createWithLength(VM& vm, unsigned length) > { > JSBigInt* bigInt = new (NotNull, allocateCell<JSBigInt>(vm.heap, allocationSize(length))) JSBigInt(vm, vm.bigIntStructure.get(), length); > bigInt->finishCreation(vm); >@@ -250,6 +250,60 @@ inline void JSBigInt::inplaceMultiplyAdd(uintptr_t factor, uintptr_t summand) > internalMultiplyAdd(this, factor, summand, length(), this); > } > >+JSBigInt* JSBigInt::divide(ExecState& state, JSBigInt* x, JSBigInt* y) >+{ >+ // 1. If y is 0n, throw a RangeError exception. >+ VM& vm = state.vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ if (y->isZero()) { >+ throwRangeError(&state, scope, ASCIILiteral("0 is an invalid divisor value.")); >+ return nullptr; >+ } >+ >+ // 2. Let quotient be the mathematical value of x divided by y. >+ // 3. Return a BigInt representing quotient rounded towards 0 to the next >+ // integral value. >+ if (absoluteCompare(x, y) < 0) >+ return createZero(vm); >+ >+ JSBigInt* quotient = nullptr; >+ bool resultSign = x->sign() != y->sign(); >+ if (y->length() == 1) { >+ Digit divisor = y->digit(0); >+ if (divisor == 1) >+ return resultSign == x->sign() ? x : unaryMinus(state, x); >+ >+ Digit remainder; >+ absoluteDivSmall(state, x, divisor, "ient, remainder); >+ } else >+ absoluteDivLarge(state, x, y, "ient, nullptr); >+ >+ quotient->setSign(resultSign); >+ return quotient->rightTrim(vm); >+} >+ >+JSBigInt* JSBigInt::copy(ExecState& state, JSBigInt* x) >+{ >+ ASSERT(!x->isZero()); >+ >+ VM& vm = state.vm(); >+ JSBigInt* result = JSBigInt::createWithLength(vm, x->length()); >+ std::copy(x->dataStorage(), x->dataStorage() + x->length(), result->dataStorage()); >+ result->setSign(x->sign()); >+ return result; >+} >+ >+JSBigInt* JSBigInt::unaryMinus(ExecState& state, JSBigInt* x) >+{ >+ if (x->isZero()) >+ return x; >+ >+ JSBigInt* result = copy(state, x); >+ result->setSign(!x->sign()); >+ return result; >+} >+ > #if USE(JSVALUE32_64) > #define HAVE_TWO_DIGIT 1 > typedef uint64_t TwoDigit; >@@ -408,14 +462,14 @@ inline JSBigInt::Digit JSBigInt::digitDiv(Digit high, Digit low, Digit divisor, > > // Multiplies {source} with {factor} and adds {summand} to the result. > // {result} and {source} may be the same BigInt for inplace modification. >-void JSBigInt::internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, int n, JSBigInt* result) >+void JSBigInt::internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned n, JSBigInt* result) > { > ASSERT(source->length() >= n); > ASSERT(result->length() >= n); > > Digit carry = summand; > Digit high = 0; >- for (int i = 0; i < n; i++) { >+ for (unsigned i = 0; i < n; i++) { > Digit current = source->digit(i); > Digit newCarry = 0; > >@@ -451,7 +505,7 @@ bool JSBigInt::equals(JSBigInt* x, JSBigInt* y) > if (x->length() != y->length()) > return false; > >- for (int i = 0; i < x->length(); i++) { >+ for (unsigned i = 0; i < x->length(); i++) { > if (x->digit(i) != y->digit(i)) > return false; > } >@@ -459,6 +513,28 @@ bool JSBigInt::equals(JSBigInt* x, JSBigInt* y) > return true; > } > >+int JSBigInt::absoluteCompare(JSBigInt* x, JSBigInt* y) >+{ >+ if (x->length()) >+ ASSERT(x->digit(0)); >+ >+ if (y->length()) >+ ASSERT(y->digit(0)); >+ >+ int diff = x->length() - y->length(); >+ if (diff) >+ return diff; >+ >+ int i = x->length() - 1; >+ while (i >= 0 && x->digit(i) == y->digit(i)) >+ i--; >+ >+ if (i < 0) >+ return 0; >+ >+ return x->digit(i) > y->digit(i) ? 1 : -1; >+} >+ > // Divides {x} by {divisor}, returning the result in {quotient} and {remainder}. > // Mathematically, the contract is: > // quotient = (x - remainder) / divisor, with 0 <= remainder < divisor. >@@ -479,7 +555,7 @@ void JSBigInt::absoluteDivSmall(ExecState& state, JSBigInt* x, Digit divisor, JS > return; > } > >- int length = x->length(); >+ unsigned length = x->length(); > if (quotient != nullptr) { > if (*quotient == nullptr) > *quotient = JSBigInt::createWithLength(vm, length); >@@ -494,6 +570,211 @@ void JSBigInt::absoluteDivSmall(ExecState& state, JSBigInt* x, Digit divisor, JS > } > } > >+// Divides {dividend} by {divisor}, returning the result in {quotient} and >+// {remainder}. Mathematically, the contract is: >+// quotient = (dividend - remainder) / divisor, with 0 <= remainder < divisor. >+// Both {quotient} and {remainder} are optional, for callers that are only >+// interested in one of them. >+// See Knuth, Volume 2, section 4.3.1, Algorithm D. >+void JSBigInt::absoluteDivLarge(ExecState& state, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder) >+{ >+ ASSERT(divisor->length() >= 2); >+ ASSERT(dividend->length() >= divisor->length()); >+ >+ VM& vm = state.vm(); >+ // The unusual variable names inside this function are consistent with >+ // Knuth's book, as well as with Go's implementation of this algorithm. >+ // Maintaining this consistency is probably more useful than trying to >+ // come up with more descriptive names for them. >+ unsigned n = divisor->length(); >+ unsigned m = dividend->length() - n; >+ >+ // The quotient to be computed. >+ JSBigInt* q = nullptr; >+ if (quotient != nullptr) >+ q = createWithLength(vm, m + 1); >+ >+ // In each iteration, {qhatv} holds {divisor} * {current quotient digit}. >+ // "v" is the book's name for {divisor}, "qhat" the current quotient digit. >+ JSBigInt* qhatv = createWithLength(vm, m + 1); >+ >+ // D1. >+ // Left-shift inputs so that the divisor's MSB is set. This is necessary >+ // to prevent the digit-wise divisions (see digit_div call below) from >+ // overflowing (they take a two digits wide input, and return a one digit >+ // result). >+ Digit lastDigit = divisor->digit(n - 1); >+ unsigned shift = sizeof(lastDigit) == 8 ? clz64(lastDigit) : clz32(lastDigit); >+ >+ if (shift > 0) >+ divisor = absoluteSpecialLeftShift(state, divisor, shift, SameSizeResult); >+ >+ // Holds the (continuously updated) remaining part of the dividend, which >+ // eventually becomes the remainder. >+ JSBigInt* u = absoluteSpecialLeftShift(state, dividend, shift, AlwaysAddOneDigit); >+ >+ // D2. >+ // Iterate over the dividend's digit (like the "grad school" algorithm). >+ // {vn1} is the divisor's most significant digit. >+ Digit vn1 = divisor->digit(n - 1); >+ for (int j = m; j >= 0; j--) { >+ // D3. >+ // Estimate the current iteration's quotient digit (see Knuth for details). >+ // {qhat} is the current quotient digit. >+ Digit qhat = std::numeric_limits<Digit>::max(); >+ >+ // {ujn} is the dividend's most significant remaining digit. >+ Digit ujn = u->digit(j + n); >+ if (ujn != vn1) { >+ // {rhat} is the current iteration's remainder. >+ Digit rhat = 0; >+ // Estimate the current quotient digit by dividing the most significant >+ // digits of dividend and divisor. The result will not be too small, >+ // but could be a bit too large. >+ qhat = digitDiv(ujn, u->digit(j + n - 1), vn1, rhat); >+ >+ // Decrement the quotient estimate as needed by looking at the next >+ // digit, i.e. by testing whether >+ // qhat * v_{n-2} > (rhat << digitBits) + u_{j+n-2}. >+ Digit vn2 = divisor->digit(n - 2); >+ Digit ujn2 = u->digit(j + n - 2); >+ while (productGreaterThan(qhat, vn2, rhat, ujn2)) { >+ qhat--; >+ Digit prevRhat = rhat; >+ rhat += vn1; >+ // v[n-1] >= 0, so this tests for overflow. >+ if (rhat < prevRhat) >+ break; >+ } >+ } >+ >+ // D4. >+ // Multiply the divisor with the current quotient digit, and subtract >+ // it from the dividend. If there was "borrow", then the quotient digit >+ // was one too high, so we must correct it and undo one subtraction of >+ // the (shifted) divisor. >+ internalMultiplyAdd(divisor, qhat, 0, n, qhatv); >+ Digit c = u->absoluteInplaceSub(qhatv, j); >+ if (c) { >+ c = u->absoluteInplaceAdd(divisor, j); >+ u->setDigit(j + n, u->digit(j + n) + c); >+ qhat--; >+ } >+ >+ if (quotient != nullptr) >+ q->setDigit(j, qhat); >+ } >+ >+ if (quotient != nullptr) { >+ // Caller will right-trim. >+ *quotient = q; >+ } >+ >+ if (remainder != nullptr) { >+ u->inplaceRightShift(shift); >+ *remainder = u; >+ } >+} >+ >+// Returns whether (factor1 * factor2) > (high << kDigitBits) + low. >+bool JSBigInt::productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low) >+{ >+ Digit resultHigh; >+ Digit resultLow = digitMul(factor1, factor2, resultHigh); >+ return resultHigh > high || (resultHigh == high && resultLow > low); >+} >+ >+// Adds {summand} onto {this}, starting with {summand}'s 0th digit >+// at {this}'s {startIndex}'th digit. Returns the "carry" (0 or 1). >+JSBigInt::Digit JSBigInt::absoluteInplaceAdd(JSBigInt* summand, unsigned startIndex) >+{ >+ Digit carry = 0; >+ unsigned n = summand->length(); >+ ASSERT(length() >= startIndex + n); >+ for (unsigned i = 0; i < n; i++) { >+ Digit newCarry = 0; >+ Digit sum = digitAdd(digit(startIndex + i), summand->digit(i), newCarry); >+ sum = digitAdd(sum, carry, newCarry); >+ setDigit(startIndex + i, sum); >+ carry = newCarry; >+ } >+ >+ return carry; >+} >+ >+// Subtracts {subtrahend} from {this}, starting with {subtrahend}'s 0th digit >+// at {this}'s {startIndex}-th digit. Returns the "borrow" (0 or 1). >+JSBigInt::Digit JSBigInt::absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex) >+{ >+ Digit borrow = 0; >+ unsigned n = subtrahend->length(); >+ ASSERT(length() >= startIndex + n); >+ for (unsigned i = 0; i < n; i++) { >+ Digit newBorrow = 0; >+ Digit difference = digitSub(digit(startIndex + i), subtrahend->digit(i), newBorrow); >+ difference = digitSub(difference, borrow, newBorrow); >+ setDigit(startIndex + i, difference); >+ borrow = newBorrow; >+ } >+ >+ return borrow; >+} >+ >+void JSBigInt::inplaceRightShift(unsigned shift) >+{ >+ ASSERT(shift < digitBits); >+ ASSERT((digit(0) & ((static_cast<Digit>(1) << shift) - 1)) == 0); >+ >+ if (!shift) >+ return; >+ >+ Digit carry = digit(0) >> shift; >+ unsigned last = length() - 1; >+ for (unsigned i = 0; i < last; i++) { >+ Digit d = digit(i + 1); >+ setDigit(i, (d << (digitBits - shift)) | carry); >+ carry = d >> shift; >+ } >+ setDigit(last, carry); >+} >+ >+// Always copies the input, even when {shift} == 0. >+JSBigInt* JSBigInt::absoluteSpecialLeftShift(ExecState& state, JSBigInt* x, unsigned shift, SpecialLeftShiftMode mode) >+{ >+ ASSERT(shift < digitBits); >+ ASSERT(!x->isZero()); >+ VM& vm = state.vm(); >+ >+ unsigned n = x->length(); >+ unsigned resultLength = mode == AlwaysAddOneDigit ? n + 1 : n; >+ JSBigInt* result = createWithLength(vm, resultLength); >+ >+ if (!shift) { >+ for (unsigned i = 0; i < n; i++) >+ result->setDigit(i, x->digit(i)); >+ if (mode == AlwaysAddOneDigit) >+ result->setDigit(n, 0); >+ >+ return result; >+ } >+ >+ Digit carry = 0; >+ for (unsigned i = 0; i < n; i++) { >+ Digit d = x->digit(i); >+ result->setDigit(i, (d << shift) | carry); >+ carry = d >> (digitBits - shift); >+ } >+ >+ if (mode == AlwaysAddOneDigit) >+ result->setDigit(n, carry); >+ else { >+ ASSERT(mode == SameSizeResult); >+ ASSERT(!carry); >+ } >+ >+ return result; >+} >+ > // 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: >@@ -550,7 +831,7 @@ String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, int radix) > ASSERT(radix >= 2 && radix <= 36); > ASSERT(!x->isZero()); > >- int length = x->length(); >+ unsigned length = x->length(); > bool sign = x->sign(); > > uint8_t maxBitsPerChar = maxBitsPerCharTable[radix]; >@@ -571,7 +852,7 @@ String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, int radix) > > // By construction of chunkChars, there can't have been overflow. > ASSERT(chunkDivisor); >- int nonZeroDigit = length - 1; >+ unsigned nonZeroDigit = length - 1; > ASSERT(x->digit(nonZeroDigit)); > > // {rest} holds the part of the BigInt that we haven't looked at yet. >@@ -612,7 +893,7 @@ String JSBigInt::toStringGeneric(ExecState& state, JSBigInt* x, int radix) > ASSERT(resultString.size() <= static_cast<size_t>(maximumCharactersRequired)); > > // Remove leading zeroes. >- int newSizeNoLeadingZeroes = resultString.size(); >+ unsigned newSizeNoLeadingZeroes = resultString.size(); > while (newSizeNoLeadingZeroes > 1 && resultString[newSizeNoLeadingZeroes - 1] == '0') > newSizeNoLeadingZeroes--; > >@@ -631,14 +912,14 @@ JSBigInt* JSBigInt::rightTrim(VM& vm) > if (isZero()) > return this; > >- int nonZeroIndex = m_length - 1; >- while (nonZeroIndex >= 0 && !digit(nonZeroIndex)) >+ unsigned nonZeroIndex = m_length - 1; >+ while (!digit(nonZeroIndex)) > nonZeroIndex--; > > if (nonZeroIndex == m_length - 1) > return this; > >- int newLength = nonZeroIndex + 1; >+ unsigned newLength = nonZeroIndex + 1; > JSBigInt* trimmedBigInt = createWithLength(vm, newLength); > RELEASE_ASSERT(trimmedBigInt); > std::copy(dataStorage(), dataStorage() + newLength, trimmedBigInt->dataStorage()); >@@ -648,14 +929,14 @@ JSBigInt* JSBigInt::rightTrim(VM& vm) > return trimmedBigInt; > } > >-JSBigInt* JSBigInt::allocateFor(ExecState* state, VM& vm, int radix, int charcount) >+JSBigInt* JSBigInt::allocateFor(ExecState* state, VM& vm, unsigned radix, unsigned charcount) > { > ASSERT(2 <= radix && radix <= 36); > ASSERT(charcount >= 0); > > size_t bitsPerChar = maxBitsPerCharTable[radix]; > size_t chars = charcount; >- const int roundup = bitsPerCharTableMultiplier - 1; >+ const unsigned roundup = bitsPerCharTableMultiplier - 1; > if (chars <= (std::numeric_limits<size_t>::max() - roundup) / bitsPerChar) { > size_t bitsMin = bitsPerChar * chars; > >@@ -809,15 +1090,15 @@ inline JSBigInt::Digit* JSBigInt::dataStorage() > return reinterpret_cast<Digit*>(reinterpret_cast<char*>(this) + offsetOfData()); > } > >-inline JSBigInt::Digit JSBigInt::digit(int n) >+JSBigInt::Digit JSBigInt::digit(unsigned n) > { >- ASSERT(n >= 0 && n < length()); >+ ASSERT(n < length()); > return dataStorage()[n]; > } > >-inline void JSBigInt::setDigit(int n, Digit value) >+void JSBigInt::setDigit(unsigned n, Digit value) > { >- ASSERT(n >= 0 && n < length()); >+ ASSERT(n < length()); > dataStorage()[n] = value; > } > JSObject* JSBigInt::toObject(ExecState* exec, JSGlobalObject* globalObject) const >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index b9bf7512ffc13b8f4f2ba73ab4a178532b9c7934..83c35e4b84139c856194ef5edaa867f40d210364 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -41,7 +41,7 @@ class JSBigInt final : public JSCell { > > public: > >- JSBigInt(VM&, Structure*, int length); >+ JSBigInt(VM&, Structure*, unsigned length); > > enum class InitializationType { None, WithZero }; > void initialize(InitializationType); >@@ -49,12 +49,12 @@ public: > static void visitChildren(JSCell*, SlotVisitor&); > > static size_t estimatedSize(JSCell*); >- static size_t allocationSize(int length); >+ static size_t allocationSize(unsigned length); > > static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); > > static JSBigInt* createZero(VM&); >- static JSBigInt* createWithLength(VM&, int length); >+ static JSBigInt* createWithLength(VM&, unsigned length); > > static JSBigInt* createFrom(VM&, int32_t value); > static JSBigInt* createFrom(VM&, uint32_t value); >@@ -70,8 +70,8 @@ public: > void setSign(bool sign) { m_sign = sign; } > bool sign() const { return m_sign; } > >- void setLength(int length) { m_length = length; } >- int length() const { return m_length; } >+ void setLength(unsigned length) { m_length = length; } >+ unsigned length() const { return m_length; } > > enum ErrorParseMode { > ThrowExceptions, >@@ -93,6 +93,9 @@ public: > > JSObject* toObject(ExecState*, JSGlobalObject*) const; > >+ static JSBigInt* divide(ExecState&, JSBigInt* x, JSBigInt* y); >+ static JSBigInt* unaryMinus(ExecState&, JSBigInt* x); >+ > private: > > enum ComparisonResult { >@@ -117,8 +120,23 @@ private: > > static uint64_t calculateMaximumCharactersRequired(int length, int radix, Digit lastDigit, bool sign); > >+ static int absoluteCompare(JSBigInt* x, JSBigInt* y); > static void absoluteDivSmall(ExecState&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder); >- static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, int, JSBigInt* result); >+ static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, unsigned, JSBigInt* result); >+ static void multiplyAccumulate(JSBigInt* multiplicand, Digit multiplier, JSBigInt* accumulator, unsigned accumulatorIndex); >+ static void absoluteDivLarge(ExecState&, JSBigInt* dividend, JSBigInt* divisor, JSBigInt** quotient, JSBigInt** remainder); >+ >+ enum SpecialLeftShiftMode { >+ SameSizeResult, >+ AlwaysAddOneDigit >+ }; >+ >+ static JSBigInt* absoluteSpecialLeftShift(ExecState&, JSBigInt* x, unsigned shift, SpecialLeftShiftMode); >+ static bool productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low); >+ >+ Digit absoluteInplaceAdd(JSBigInt* summand, unsigned startIndex); >+ Digit absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex); >+ void inplaceRightShift(unsigned shift); > > // Digit arithmetic helpers. > static Digit digitAdd(Digit a, Digit b, Digit& carry); >@@ -139,8 +157,9 @@ private: > template <typename CharType> > static JSBigInt* parseInt(ExecState*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode, bool allowEmptyString = true); > >- static JSBigInt* allocateFor(ExecState*, VM&, int radix, int charcount); >+ static JSBigInt* allocateFor(ExecState*, VM&, unsigned radix, unsigned charcount); > >+ static JSBigInt* copy(ExecState&, JSBigInt* x); > JSBigInt* rightTrim(VM&); > > void inplaceMultiplyAdd(Digit multiplier, Digit part); >@@ -148,10 +167,10 @@ private: > static size_t offsetOfData(); > Digit* dataStorage(); > >- Digit digit(int); >- void setDigit(int, Digit); >+ Digit digit(unsigned); >+ void setDigit(unsigned, Digit); > >- int m_length; >+ unsigned m_length; > bool m_sign; > }; > >diff --git a/Source/JavaScriptCore/runtime/JSCJSValue.h b/Source/JavaScriptCore/runtime/JSCJSValue.h >index 21e80f87503c7ef91b7b2105eb0c725da2eab763..91dc1a40f14e37672f4101604c0690e6097e18fc 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValue.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValue.h >@@ -39,6 +39,7 @@ > namespace JSC { > > class AssemblyHelpers; >+class JSBigInt; > class ExecState; > class JSCell; > class JSValueSource; >@@ -257,6 +258,8 @@ public: > // toNumber conversion is expected to be side effect free if an exception has > // been set in the ExecState already. > double toNumber(ExecState*) const; >+ >+ Variant<JSBigInt*, double> toNumeric(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 23d3b26c59542b770e4d3d0a2461262e3de5c9a8..7266a862149be8534e93e4b5e6e820e227c5b3e9 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >@@ -37,6 +37,7 @@ > #include "JSProxy.h" > #include "JSStringInlines.h" > #include "MathCommon.h" >+#include <wtf/Variant.h> > #include <wtf/text/StringImpl.h> > > namespace JSC { >@@ -728,6 +729,19 @@ ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const > return toNumberSlowCase(exec); > } > >+ALWAYS_INLINE Variant<JSBigInt*, double> JSValue::toNumeric(ExecState* exec) const >+{ >+ 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); >+ double value = primValue.toNumber(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/JSTests/ChangeLog b/JSTests/ChangeLog >index 3311588041ea0bb56caf3796a4f25dc417b62052..b92f850b4693497580453406a13c902d632dca34 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,19 @@ >+2018-05-11 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement support for "/" operation >+ https://bugs.webkit.org/show_bug.cgi?id=183996 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * bigIntTests.yaml: >+ * stress/big-int-div-jit.js: Added. >+ * stress/big-int-div-memory-stress.js: Added. >+ * stress/big-int-div-to-primitive-precedence.js: Added. >+ * stress/big-int-div-to-primitive.js: Added. >+ * stress/big-int-div-type-error.js: Added. >+ * stress/big-int-div-wrapped-value.js: Added. >+ * stress/big-int-division.js: Added. >+ > 2018-05-10 Leo Balter <leonardo.balter@gmail.com> > > Update Test262 tests through the new import script - 20180509 >diff --git a/JSTests/bigIntTests.yaml b/JSTests/bigIntTests.yaml >index 7ae22cb1bb2aff62cc4ddf496299f96a0744f7ae..e5a819743fd4c49108b1780c8acbb8ce5c950d03 100644 >--- a/JSTests/bigIntTests.yaml >+++ b/JSTests/bigIntTests.yaml >@@ -97,3 +97,21 @@ > - path: stress/big-int-to-string.js > cmd: runBigIntEnabled > >+- path: stress/big-int-div-jit.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-div-memory-stress.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-div-to-primitive.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-div-type-error.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-div-wrapped-value.js >+ cmd: runBigIntEnabled >+ >+- path: stress/big-int-division.js >+ cmd: runBigIntEnabled >+ >diff --git a/JSTests/stress/big-int-div-jit.js b/JSTests/stress/big-int-div-jit.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0e217e8307e39d4f40c15a2ad0708448266a904f >--- /dev/null >+++ b/JSTests/stress/big-int-div-jit.js >@@ -0,0 +1,19 @@ >+//@ runBigIntEnabled >+ >+let assert = { >+ sameValue: function(i, e, m) { >+ if (i !== e) >+ throw new Error(m); >+ } >+} >+ >+function bigIntDiv(x, y) { >+ return x / y; >+} >+noInline(bigIntDiv); >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntDiv(30n, 10n); >+ assert.sameValue(r, 3n, 30n + " / " + 10n + " = " + r); >+} >+ >diff --git a/JSTests/stress/big-int-div-memory-stress.js b/JSTests/stress/big-int-div-memory-stress.js >new file mode 100644 >index 0000000000000000000000000000000000000000..0cf0b9b6faf3ef85c5f59d3ba9bf4a974f73f6f4 >--- /dev/null >+++ b/JSTests/stress/big-int-div-memory-stress.js >@@ -0,0 +1,15 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+let a = 0n; >+let b = 30n; >+for (let i = 0; i < 1000000; i++) { >+ a = b / 2n; >+} >+ >+assert(a === 15n); >+ >diff --git a/JSTests/stress/big-int-div-to-primitive.js b/JSTests/stress/big-int-div-to-primitive.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a2973447ea4258262252eafdaae0d62ef1821c88 >--- /dev/null >+++ b/JSTests/stress/big-int-div-to-primitive.js >@@ -0,0 +1,34 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+assert.sameValue = function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+} >+ >+function testDiv(x, y, z) { >+ assert.sameValue(x / y, z, x + " / " + y + " = " + z); >+} >+ >+let o = { >+ [Symbol.toPrimitive]: function () { return 300000000000n; } >+} >+ >+testDiv(500000000000438n, o, 1666n); >+ >+o.valueOf = function () { >+ throw new Error("Should never execute it"); >+}; >+ >+testDiv(700000000000438n, o, 2333n); >+ >+o.toString = function () { >+ throw new Error("Should never execute it"); >+}; >+ >+testDiv(700000000000438n, o, 2333n); >+ >diff --git a/JSTests/stress/big-int-div-type-error.js b/JSTests/stress/big-int-div-type-error.js >new file mode 100644 >index 0000000000000000000000000000000000000000..27982cd78e030150eafaa4f9346e4f667d5e661b >--- /dev/null >+++ b/JSTests/stress/big-int-div-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-div-wrapped-value.js b/JSTests/stress/big-int-div-wrapped-value.js >new file mode 100644 >index 0000000000000000000000000000000000000000..9bb9aee983af0c0e09758e772384f5eb3c46dc90 >--- /dev/null >+++ b/JSTests/stress/big-int-div-wrapped-value.js >@@ -0,0 +1,46 @@ >+//@ runBigIntEnabled >+ >+assert = { >+ sameValue: function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+ } >+}; >+ >+function testDiv(x, y, z, message) { >+ assert.sameValue(x / y, z, message); >+} >+ >+testDiv(Object(2n), 1n, 2n, "ToPrimitive: unbox object with internal slot"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 2n; >+ } >+}; >+testDiv(o, 1n, 2n, "ToPrimitive: @@toPrimitive"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ } >+}; >+testDiv(o, 1n, 2n, "ToPrimitive: valueOf"); >+ >+o = { >+ toString: function() { >+ return 2n; >+ } >+} >+testDiv(o, 1n, 2n, "ToPrimitive: toString"); >+ >+o = { >+ valueOf: function() { >+ return 2n; >+ }, >+ toString: function () { >+ throw new Error("Should never execute it"); >+ } >+}; >+testDiv(o, 1n, 2n, "ToPrimitive: valueOf"); >+ >diff --git a/JSTests/stress/big-int-division.js b/JSTests/stress/big-int-division.js >new file mode 100644 >index 0000000000000000000000000000000000000000..401890ad6316cece7a9b2cad020aab0f5db2991a >--- /dev/null >+++ b/JSTests/stress/big-int-division.js >@@ -0,0 +1,131 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Robin Templeton. 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); >+} >+ >+function testDiv(x, y, z) { >+ assert.sameValue(x / y, z, x + " / " + y + " = " + z); >+} >+ >+testDiv(0xFEDCBA9876543210n, 0xFEDCBA9876543210n, 0x1n); >+testDiv(0xFEDCBA9876543210n, 0xFEDCBA987654320Fn, 0x1n); >+testDiv(0xFEDCBA9876543210n, 0xFEDCBA98n, 0x100000000n); >+testDiv(0xFEDCBA9876543210n, 0xFEDCBA97n, 0x100000001n); >+testDiv(0xFEDCBA9876543210n, 0x1234n, 0xE0042813BE5DCn); >+testDiv(0xFEDCBA9876543210n, 0x3n, 0x54F43E32D21C10B0n); >+testDiv(0xFEDCBA9876543210n, 0x2n, 0x7F6E5D4C3B2A1908n); >+testDiv(0xFEDCBA9876543210n, 0x1n, 0xFEDCBA9876543210n); >+testDiv(0xFEDCBA9876543210n, BigInt("-1"), BigInt("-18364758544493064720")); >+testDiv(0xFEDCBA9876543210n, BigInt("-2"), BigInt("-9182379272246532360")); >+testDiv(0xFEDCBA9876543210n, BigInt("-3"), BigInt("-6121586181497688240")); >+testDiv(0xFEDCBA9876543210n, BigInt("-4275878551"), BigInt("-4294967297")); >+testDiv(0xFEDCBA9876543210n, BigInt("-18364758544493064719"), BigInt("-1")); >+testDiv(0xFEDCBA987654320Fn, 0xFEDCBA9876543210n, 0x0n); >+testDiv(0xFEDCBA987654320Fn, 0xFEDCBA987654320Fn, 0x1n); >+testDiv(0xFEDCBA987654320Fn, 0xFEDCBA98n, 0x100000000n); >+testDiv(0xFEDCBA987654320Fn, 0xFEDCBA97n, 0x100000001n); >+testDiv(0xFEDCBA987654320Fn, 0x1234n, 0xE0042813BE5DCn); >+testDiv(0xFEDCBA987654320Fn, 0x3n, 0x54F43E32D21C10AFn); >+testDiv(0xFEDCBA987654320Fn, 0x2n, 0x7F6E5D4C3B2A1907n); >+testDiv(0xFEDCBA987654320Fn, 0x1n, 0xFEDCBA987654320Fn); >+testDiv(0xFEDCBA98n, 0xFEDCBA9876543210n, 0x0n); >+testDiv(0xFEDCBA98n, 0xFEDCBA987654320Fn, 0x0n); >+testDiv(0xFEDCBA98n, 0xFEDCBA98n, 0x1n); >+testDiv(0xFEDCBA98n, 0xFEDCBA97n, 0x1n); >+testDiv(0xFEDCBA98n, 0x1234n, 0xE0042n); >+testDiv(0xFEDCBA98n, 0x3n, 0x54F43E32n); >+testDiv(0xFEDCBA98n, 0x2n, 0x7F6E5D4Cn); >+testDiv(0xFEDCBA98n, 0x1n, 0xFEDCBA98n); >+testDiv(0xFEDCBA98n, BigInt("-1"), BigInt("-4275878552")); >+testDiv(0xFEDCBA98n, BigInt("-2"), BigInt("-2137939276")); >+testDiv(0xFEDCBA98n, BigInt("-3"), BigInt("-1425292850")); >+testDiv(0xFEDCBA98n, BigInt("-4275878551"), BigInt("-1")); >+testDiv(0xFEDCBA98n, BigInt("-18364758544493064719"), 0x0n); >+testDiv(0xFEDCBA97n, 0xFEDCBA9876543210n, 0x0n); >+testDiv(0xFEDCBA97n, 0xFEDCBA987654320Fn, 0x0n); >+testDiv(0xFEDCBA97n, 0xFEDCBA98n, 0x0n); >+testDiv(0xFEDCBA97n, 0xFEDCBA97n, 0x1n); >+testDiv(0xFEDCBA97n, 0x1234n, 0xE0042n); >+testDiv(0xFEDCBA97n, 0x3n, 0x54F43E32n); >+testDiv(0xFEDCBA97n, 0x2n, 0x7F6E5D4Bn); >+testDiv(0xFEDCBA97n, 0x1n, 0xFEDCBA97n); >+testDiv(0x3n, 0xFEDCBA9876543210n, 0x0n); >+testDiv(0x3n, 0xFEDCBA98n, 0x0n); >+testDiv(0x3n, 0x1234n, 0x0n); >+testDiv(0x3n, 0x3n, 0x1n); >+testDiv(0x3n, 0x2n, 0x1n); >+testDiv(0x3n, 0x1n, 0x3n); >+testDiv(0x3n, BigInt("-2"), BigInt("-1")); >+testDiv(0x3n, BigInt("-3"), BigInt("-1")); >+testDiv(0x3n, BigInt("-4275878551"), 0x0n); >+testDiv(0x3n, BigInt("-18364758544493064719"), 0x0n); >+testDiv(0x2n, 0xFEDCBA98n, 0x0n); >+testDiv(0x2n, 0xFEDCBA97n, 0x0n); >+testDiv(0x2n, 0x3n, 0x0n); >+testDiv(0x2n, 0x1n, 0x2n); >+testDiv(0x2n, BigInt("-1"), BigInt("-2")); >+testDiv(0x2n, BigInt("-2"), BigInt("-1")); >+testDiv(0x2n, BigInt("-3"), 0x0n); >+testDiv(0x1n, 0x1234n, 0x0n); >+testDiv(0x1n, 0x3n, 0x0n); >+testDiv(0x1n, 0x2n, 0x0n); >+testDiv(0x1n, 0x1n, 0x1n); >+testDiv(0x1n, BigInt("-1"), BigInt("-1")); >+testDiv(0x1n, BigInt("-3"), 0x0n); >+testDiv(0x1n, BigInt("-4660"), 0x0n); >+testDiv(0x1n, BigInt("-18364758544493064719"), 0x0n); >+testDiv(BigInt("-1"), 0xFEDCBA9876543210n, 0x0n); >+testDiv(BigInt("-1"), 0xFEDCBA987654320Fn, 0x0n); >+testDiv(BigInt("-1"), 0xFEDCBA98n, 0x0n); >+testDiv(BigInt("-1"), 0xFEDCBA97n, 0x0n); >+testDiv(BigInt("-1"), 0x3n, 0x0n); >+testDiv(BigInt("-1"), 0x1n, BigInt("-1")); >+testDiv(BigInt("-1"), BigInt("-3"), 0x0n); >+testDiv(BigInt("-1"), BigInt("-4660"), 0x0n); >+testDiv(BigInt("-1"), BigInt("-18364758544493064719"), 0x0n); >+testDiv(BigInt("-2"), 0xFEDCBA9876543210n, 0x0n); >+testDiv(BigInt("-3"), 0x3n, BigInt("-1")); >+testDiv(BigInt("-3"), 0x2n, BigInt("-1")); >+testDiv(BigInt("-3"), BigInt("-1"), 0x3n); >+testDiv(BigInt("-3"), BigInt("-3"), 0x1n); >+testDiv(BigInt("-3"), BigInt("-4660"), 0x0n); >+testDiv(BigInt("-3"), BigInt("-4275878551"), 0x0n); >+testDiv(BigInt("-3"), BigInt("-4275878552"), 0x0n); >+testDiv(BigInt("-3"), BigInt("-18364758544493064720"), 0x0n); >+testDiv(BigInt("-18364758544493064719"), 0xFEDCBA97n, BigInt("-4294967297")); >+testDiv(BigInt("-18364758544493064719"), 0x1234n, BigInt("-3940935309977052")); >+testDiv(BigInt("-18364758544493064719"), 0x3n, BigInt("-6121586181497688239")); >+testDiv(BigInt("-18364758544493064719"), 0x2n, BigInt("-9182379272246532359")); >+testDiv(BigInt("-18364758544493064719"), 0x1n, BigInt("-18364758544493064719")); >+testDiv(BigInt("-18364758544493064719"), BigInt("-1"), 0xFEDCBA987654320Fn); >+testDiv(BigInt("-18364758544493064719"), BigInt("-4275878551"), 0x100000001n); >+testDiv(BigInt("-18364758544493064719"), BigInt("-18364758544493064719"), 0x1n); >+testDiv(BigInt("-18364758544493064720"), 0xFEDCBA9876543210n, BigInt("-1")); >+testDiv(BigInt("-18364758544493064720"), 0x1234n, BigInt("-3940935309977052")); >+testDiv(BigInt("-18364758544493064720"), 0x3n, BigInt("-6121586181497688240")); >+testDiv(BigInt("-18364758544493064720"), 0x2n, BigInt("-9182379272246532360")); >+testDiv(BigInt("-18364758544493064720"), 0x1n, BigInt("-18364758544493064720")); >+testDiv(BigInt("-18364758544493064720"), BigInt("-1"), 0xFEDCBA9876543210n); >+testDiv(BigInt("-18364758544493064720"), BigInt("-3"), 0x54F43E32D21C10B0n); >+testDiv(BigInt("-18364758544493064720"), BigInt("-4660"), 0xE0042813BE5DCn); >+testDiv(BigInt("-18364758544493064720"), BigInt("-4275878552"), 0x100000000n); >+testDiv(BigInt("-18364758544493064720"), BigInt("-18364758544493064720"), 0x1n); >+ >+// Test division by 0 >+try { >+ let a = 102122311n / 0n; >+} catch (e) { >+ assert(e instanceof RangeError); >+ assert(e.message == "0 is an invalid divisor value."); >+} >+
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 183996
:
336498
|
337576
|
338187
|
338995
|
339410
|
339510
|
339608
|
340161
|
340267
|
340413
|
340463
|
340471
|
340550