diff options
Diffstat (limited to 'deps/v8/src/objects/bigint.cc')
-rw-r--r-- | deps/v8/src/objects/bigint.cc | 183 |
1 files changed, 124 insertions, 59 deletions
diff --git a/deps/v8/src/objects/bigint.cc b/deps/v8/src/objects/bigint.cc index 92b78f8821..b02c0f29d6 100644 --- a/deps/v8/src/objects/bigint.cc +++ b/deps/v8/src/objects/bigint.cc @@ -46,6 +46,8 @@ class MutableBigInt : public FreshlyAllocatedBigInt { static MaybeHandle<BigInt> MakeImmutable(MaybeHandle<MutableBigInt> maybe); static Handle<BigInt> MakeImmutable(Handle<MutableBigInt> result); + static void Canonicalize(MutableBigInt result); + // Allocation helpers. static MaybeHandle<MutableBigInt> New( Isolate* isolate, int length, @@ -64,6 +66,10 @@ class MutableBigInt : public FreshlyAllocatedBigInt { SLOW_DCHECK(bigint->IsBigInt()); return Handle<MutableBigInt>::cast(bigint); } + static MutableBigInt cast(Object o) { + SLOW_DCHECK(o.IsBigInt()); + return MutableBigInt(o.ptr()); + } static MutableBigInt unchecked_cast(Object o) { return MutableBigInt(o.ptr()); } @@ -87,8 +93,13 @@ class MutableBigInt : public FreshlyAllocatedBigInt { static MaybeHandle<BigInt> AbsoluteAdd(Isolate* isolate, Handle<BigInt> x, Handle<BigInt> y, bool result_sign); + + static void AbsoluteAdd(MutableBigInt result, BigInt x, BigInt y); + static Handle<BigInt> AbsoluteSub(Isolate* isolate, Handle<BigInt> x, Handle<BigInt> y, bool result_sign); + static void AbsoluteSub(MutableBigInt result, BigInt x, BigInt y); + static MaybeHandle<MutableBigInt> AbsoluteAddOne( Isolate* isolate, Handle<BigIntBase> x, bool sign, MutableBigInt result_storage = MutableBigInt()); @@ -120,6 +131,8 @@ class MutableBigInt : public FreshlyAllocatedBigInt { static int AbsoluteCompare(Handle<BigIntBase> x, Handle<BigIntBase> y); + static int AbsoluteCompare(BigIntBase x, BigIntBase y); + static void MultiplyAccumulate(Handle<BigIntBase> multiplicand, digit_t multiplier, Handle<MutableBigInt> accumulator, @@ -223,11 +236,24 @@ NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt) #include "src/objects/object-macros-undef.h" +template <typename T> +MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) { + // If the result of a BigInt computation is truncated to 64 bit, Turbofan + // can sometimes truncate intermediate results already, which can prevent + // those from exceeding the maximum length, effectively preventing a + // RangeError from being thrown. As this is a performance optimization, this + // behavior is accepted. To prevent the correctness fuzzer from detecting this + // difference, we crash the program. + if (FLAG_correctness_fuzzer_suppressions) { + FATAL("Aborting on invalid BigInt length"); + } + THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), T); +} + MaybeHandle<MutableBigInt> MutableBigInt::New(Isolate* isolate, int length, AllocationType allocation) { if (length > BigInt::kMaxLength) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - MutableBigInt); + return ThrowBigIntTooBig<MutableBigInt>(isolate); } Handle<MutableBigInt> result = Cast(isolate->factory()->NewBigInt(length, allocation)); @@ -347,32 +373,36 @@ MaybeHandle<BigInt> MutableBigInt::MakeImmutable( } Handle<BigInt> MutableBigInt::MakeImmutable(Handle<MutableBigInt> result) { + MutableBigInt::Canonicalize(*result); + return Handle<BigInt>::cast(result); +} + +void MutableBigInt::Canonicalize(MutableBigInt result) { // Check if we need to right-trim any leading zero-digits. - int old_length = result->length(); + int old_length = result.length(); int new_length = old_length; - while (new_length > 0 && result->digit(new_length - 1) == 0) new_length--; + while (new_length > 0 && result.digit(new_length - 1) == 0) new_length--; int to_trim = old_length - new_length; if (to_trim != 0) { - int size_delta = to_trim * kDigitSize; - Address new_end = result->address() + BigInt::SizeFor(new_length); - Heap* heap = result->GetHeap(); - if (!heap->IsLargeObject(*result)) { + int size_delta = to_trim * MutableBigInt::kDigitSize; + Address new_end = result.address() + BigInt::SizeFor(new_length); + Heap* heap = result.GetHeap(); + if (!heap->IsLargeObject(result)) { // We do not create a filler for objects in large object space. // TODO(hpayer): We should shrink the large object page if the size // of the object changed significantly. heap->CreateFillerObjectAt(new_end, size_delta, ClearRecordedSlots::kNo); } - result->synchronized_set_length(new_length); + result.synchronized_set_length(new_length); // Canonicalize -0n. if (new_length == 0) { - result->set_sign(false); + result.set_sign(false); // TODO(jkummerow): If we cache a canonical 0n, return that here. } } - DCHECK_IMPLIES(result->length() > 0, - result->digit(result->length() - 1) != 0); // MSD is non-zero. - return Handle<BigInt>(result.location()); + DCHECK_IMPLIES(result.length() > 0, + result.digit(result.length() - 1) != 0); // MSD is non-zero. } Handle<BigInt> BigInt::Zero(Isolate* isolate) { @@ -428,14 +458,12 @@ MaybeHandle<BigInt> BigInt::Exponentiate(Isolate* isolate, Handle<BigInt> base, // results. STATIC_ASSERT(kMaxLengthBits < std::numeric_limits<digit_t>::max()); if (exponent->length() > 1) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } digit_t exp_value = exponent->digit(0); if (exp_value == 1) return base; if (exp_value >= kMaxLengthBits) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } STATIC_ASSERT(kMaxLengthBits <= kMaxInt); int n = static_cast<int>(exp_value); @@ -1130,6 +1158,26 @@ void BigInt::BigIntShortPrint(std::ostream& os) { // Internal helpers. +void MutableBigInt::AbsoluteAdd(MutableBigInt result, BigInt x, BigInt y) { + DisallowHeapAllocation no_gc; + digit_t carry = 0; + int i = 0; + for (; i < y.length(); i++) { + digit_t new_carry = 0; + digit_t sum = digit_add(x.digit(i), y.digit(i), &new_carry); + sum = digit_add(sum, carry, &new_carry); + result.set_digit(i, sum); + carry = new_carry; + } + for (; i < x.length(); i++) { + digit_t new_carry = 0; + digit_t sum = digit_add(x.digit(i), carry, &new_carry); + result.set_digit(i, sum); + carry = new_carry; + } + result.set_digit(i, carry); +} + MaybeHandle<BigInt> MutableBigInt::AbsoluteAdd(Isolate* isolate, Handle<BigInt> x, Handle<BigInt> y, @@ -1146,22 +1194,9 @@ MaybeHandle<BigInt> MutableBigInt::AbsoluteAdd(Isolate* isolate, if (!New(isolate, x->length() + 1).ToHandle(&result)) { return MaybeHandle<BigInt>(); } - digit_t carry = 0; - int i = 0; - for (; i < y->length(); i++) { - digit_t new_carry = 0; - digit_t sum = digit_add(x->digit(i), y->digit(i), &new_carry); - sum = digit_add(sum, carry, &new_carry); - result->set_digit(i, sum); - carry = new_carry; - } - for (; i < x->length(); i++) { - digit_t new_carry = 0; - digit_t sum = digit_add(x->digit(i), carry, &new_carry); - result->set_digit(i, sum); - carry = new_carry; - } - result->set_digit(i, carry); + + AbsoluteAdd(*result, *x, *y); + result->set_sign(result_sign); return MakeImmutable(result); } @@ -1178,24 +1213,31 @@ Handle<BigInt> MutableBigInt::AbsoluteSub(Isolate* isolate, Handle<BigInt> x, return result_sign == x->sign() ? x : BigInt::UnaryMinus(isolate, x); } Handle<MutableBigInt> result = New(isolate, x->length()).ToHandleChecked(); + + AbsoluteSub(*result, *x, *y); + + result->set_sign(result_sign); + return MakeImmutable(result); +} + +void MutableBigInt::AbsoluteSub(MutableBigInt result, BigInt x, BigInt y) { + DisallowHeapAllocation no_gc; digit_t borrow = 0; int i = 0; - for (; i < y->length(); i++) { + for (; i < y.length(); i++) { digit_t new_borrow = 0; - digit_t difference = digit_sub(x->digit(i), y->digit(i), &new_borrow); + digit_t difference = digit_sub(x.digit(i), y.digit(i), &new_borrow); difference = digit_sub(difference, borrow, &new_borrow); - result->set_digit(i, difference); + result.set_digit(i, difference); borrow = new_borrow; } - for (; i < x->length(); i++) { + for (; i < x.length(); i++) { digit_t new_borrow = 0; - digit_t difference = digit_sub(x->digit(i), borrow, &new_borrow); - result->set_digit(i, difference); + digit_t difference = digit_sub(x.digit(i), borrow, &new_borrow); + result.set_digit(i, difference); borrow = new_borrow; } DCHECK_EQ(0, borrow); - result->set_sign(result_sign); - return MakeImmutable(result); } // Adds 1 to the absolute value of {x} and sets the result's sign to {sign}. @@ -1375,12 +1417,17 @@ Handle<MutableBigInt> MutableBigInt::AbsoluteXor(Isolate* isolate, // Returns a positive value if abs(x) > abs(y), a negative value if // abs(x) < abs(y), or zero if abs(x) == abs(y). int MutableBigInt::AbsoluteCompare(Handle<BigIntBase> x, Handle<BigIntBase> y) { - int diff = x->length() - y->length(); + return MutableBigInt::AbsoluteCompare(*x, *y); +} + +int MutableBigInt::AbsoluteCompare(BigIntBase x, BigIntBase y) { + DisallowHeapAllocation no_gc; + int diff = x.length() - y.length(); if (diff != 0) return diff; - int i = x->length() - 1; - while (i >= 0 && x->digit(i) == y->digit(i)) i--; + 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; + return x.digit(i) > y.digit(i) ? 1 : -1; } // Multiplies {multiplicand} with {multiplier} and adds the result to @@ -1716,8 +1763,7 @@ MaybeHandle<BigInt> MutableBigInt::LeftShiftByAbsolute(Isolate* isolate, Handle<BigIntBase> y) { Maybe<digit_t> maybe_shift = ToShiftAmount(y); if (maybe_shift.IsNothing()) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } digit_t shift = maybe_shift.FromJust(); int digit_shift = static_cast<int>(shift / kDigitBits); @@ -1727,8 +1773,7 @@ MaybeHandle<BigInt> MutableBigInt::LeftShiftByAbsolute(Isolate* isolate, (x->digit(length - 1) >> (kDigitBits - bits_shift)) != 0; int result_length = length + digit_shift + grow; if (result_length > kMaxLength) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } Handle<MutableBigInt> result; if (!New(isolate, result_length).ToHandle(&result)) { @@ -1887,8 +1932,7 @@ MaybeHandle<FreshlyAllocatedBigInt> BigInt::AllocateFor( } // All the overflow/maximum checks above fall through to here. if (should_throw == kThrowOnError) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - FreshlyAllocatedBigInt); + return ThrowBigIntTooBig<FreshlyAllocatedBigInt>(isolate); } else { return MaybeHandle<FreshlyAllocatedBigInt>(); } @@ -2155,10 +2199,6 @@ MaybeHandle<String> MutableBigInt::ToStringGeneric(Isolate* isolate, // the raw characters pointer (as the string might have moved). chars = result->GetChars(no_gc); } - if (interrupt_check.InterruptRequested() && - isolate->stack_guard()->HandleInterrupts().IsException(isolate)) { - return MaybeHandle<String>(); - } } } while (nonzero_digit > 0); last_digit = rest->digit(0); @@ -2250,8 +2290,7 @@ MaybeHandle<BigInt> BigInt::AsUintN(Isolate* isolate, uint64_t n, // If {x} is negative, simulate two's complement representation. if (x->sign()) { if (n > kMaxLengthBits) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } return MutableBigInt::TruncateAndSubFromPowerOfTwo( isolate, static_cast<int>(n), x, false); @@ -2395,8 +2434,7 @@ MaybeHandle<BigInt> BigInt::FromWords64(Isolate* isolate, int sign_bit, int words64_count, const uint64_t* words) { if (words64_count < 0 || words64_count > kMaxLength / (64 / kDigitBits)) { - THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), - BigInt); + return ThrowBigIntTooBig<BigInt>(isolate); } if (words64_count == 0) return MutableBigInt::Zero(isolate); STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32); @@ -2674,5 +2712,32 @@ void BigInt::BigIntPrint(std::ostream& os) { } #endif // OBJECT_PRINT +void MutableBigInt_AbsoluteAddAndCanonicalize(Address result_addr, + Address x_addr, Address y_addr) { + BigInt x = BigInt::cast(Object(x_addr)); + BigInt y = BigInt::cast(Object(y_addr)); + MutableBigInt result = MutableBigInt::cast(Object(result_addr)); + + MutableBigInt::AbsoluteAdd(result, x, y); + MutableBigInt::Canonicalize(result); +} + +int32_t MutableBigInt_AbsoluteCompare(Address x_addr, Address y_addr) { + BigInt x = BigInt::cast(Object(x_addr)); + BigInt y = BigInt::cast(Object(y_addr)); + + return MutableBigInt::AbsoluteCompare(x, y); +} + +void MutableBigInt_AbsoluteSubAndCanonicalize(Address result_addr, + Address x_addr, Address y_addr) { + BigInt x = BigInt::cast(Object(x_addr)); + BigInt y = BigInt::cast(Object(y_addr)); + MutableBigInt result = MutableBigInt::cast(Object(result_addr)); + + MutableBigInt::AbsoluteSub(result, x, y); + MutableBigInt::Canonicalize(result); +} + } // namespace internal } // namespace v8 |