| File: | out/../deps/v8/src/objects/bigint.cc |
| Warning: | line 1103, column 57 The result of the left shift is undefined due to shifting by '65', which is greater or equal to the width of type 'uint64_t' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // Copyright 2017 the V8 project authors. All rights reserved. | |||
| 2 | // Use of this source code is governed by a BSD-style license that can be | |||
| 3 | // found in the LICENSE file. | |||
| 4 | ||||
| 5 | // Parts of the implementation below: | |||
| 6 | ||||
| 7 | // Copyright (c) 2014 the Dart project authors. Please see the AUTHORS file [1] | |||
| 8 | // for details. All rights reserved. Use of this source code is governed by a | |||
| 9 | // BSD-style license that can be found in the LICENSE file [2]. | |||
| 10 | // | |||
| 11 | // [1] https://github.com/dart-lang/sdk/blob/master/AUTHORS | |||
| 12 | // [2] https://github.com/dart-lang/sdk/blob/master/LICENSE | |||
| 13 | ||||
| 14 | // Copyright 2009 The Go Authors. All rights reserved. | |||
| 15 | // Use of this source code is governed by a BSD-style | |||
| 16 | // license that can be found in the LICENSE file [3]. | |||
| 17 | // | |||
| 18 | // [3] https://golang.org/LICENSE | |||
| 19 | ||||
| 20 | #include "src/objects/bigint.h" | |||
| 21 | ||||
| 22 | #include "src/base/numbers/double.h" | |||
| 23 | #include "src/bigint/bigint.h" | |||
| 24 | #include "src/execution/isolate-inl.h" | |||
| 25 | #include "src/heap/factory.h" | |||
| 26 | #include "src/heap/heap-write-barrier-inl.h" | |||
| 27 | #include "src/numbers/conversions.h" | |||
| 28 | #include "src/objects/heap-number-inl.h" | |||
| 29 | #include "src/objects/instance-type-inl.h" | |||
| 30 | #include "src/objects/objects-inl.h" | |||
| 31 | #include "src/objects/smi.h" | |||
| 32 | ||||
| 33 | namespace v8 { | |||
| 34 | namespace internal { | |||
| 35 | ||||
| 36 | // The MutableBigInt class is an implementation detail designed to prevent | |||
| 37 | // accidental mutation of a BigInt after its construction. Step-by-step | |||
| 38 | // construction of a BigInt must happen in terms of MutableBigInt, the | |||
| 39 | // final result is then passed through MutableBigInt::MakeImmutable and not | |||
| 40 | // modified further afterwards. | |||
| 41 | // Many of the functions in this class use arguments of type {BigIntBase}, | |||
| 42 | // indicating that they will be used in a read-only capacity, and both | |||
| 43 | // {BigInt} and {MutableBigInt} objects can be passed in. | |||
| 44 | class MutableBigInt : public FreshlyAllocatedBigInt { | |||
| 45 | public: | |||
| 46 | // Bottleneck for converting MutableBigInts to BigInts. | |||
| 47 | static MaybeHandle<BigInt> MakeImmutable(MaybeHandle<MutableBigInt> maybe); | |||
| 48 | template <typename Isolate = v8::internal::Isolate> | |||
| 49 | static Handle<BigInt> MakeImmutable(Handle<MutableBigInt> result); | |||
| 50 | ||||
| 51 | static void Canonicalize(MutableBigInt result); | |||
| 52 | ||||
| 53 | // Allocation helpers. | |||
| 54 | template <typename IsolateT> | |||
| 55 | static MaybeHandle<MutableBigInt> New( | |||
| 56 | IsolateT* isolate, int length, | |||
| 57 | AllocationType allocation = AllocationType::kYoung); | |||
| 58 | static Handle<BigInt> NewFromInt(Isolate* isolate, int value); | |||
| 59 | static Handle<BigInt> NewFromDouble(Isolate* isolate, double value); | |||
| 60 | void InitializeDigits(int length, byte value = 0); | |||
| 61 | static Handle<MutableBigInt> Copy(Isolate* isolate, | |||
| 62 | Handle<BigIntBase> source); | |||
| 63 | template <typename IsolateT> | |||
| 64 | static Handle<BigInt> Zero( | |||
| 65 | IsolateT* isolate, AllocationType allocation = AllocationType::kYoung) { | |||
| 66 | // TODO(jkummerow): Consider caching a canonical zero-BigInt. | |||
| 67 | return MakeImmutable<IsolateT>( | |||
| 68 | New(isolate, 0, allocation).ToHandleChecked()); | |||
| 69 | } | |||
| 70 | ||||
| 71 | static Handle<MutableBigInt> Cast(Handle<FreshlyAllocatedBigInt> bigint) { | |||
| 72 | SLOW_DCHECK(bigint->IsBigInt())((void)0); | |||
| 73 | return Handle<MutableBigInt>::cast(bigint); | |||
| 74 | } | |||
| 75 | static MutableBigInt cast(Object o) { | |||
| 76 | SLOW_DCHECK(o.IsBigInt())((void)0); | |||
| 77 | return MutableBigInt(o.ptr()); | |||
| 78 | } | |||
| 79 | static MutableBigInt unchecked_cast(Object o) { | |||
| 80 | return MutableBigInt(o.ptr()); | |||
| 81 | } | |||
| 82 | ||||
| 83 | // Internal helpers. | |||
| 84 | static MaybeHandle<MutableBigInt> AbsoluteAddOne( | |||
| 85 | Isolate* isolate, Handle<BigIntBase> x, bool sign, | |||
| 86 | MutableBigInt result_storage = MutableBigInt()); | |||
| 87 | static Handle<MutableBigInt> AbsoluteSubOne(Isolate* isolate, | |||
| 88 | Handle<BigIntBase> x); | |||
| 89 | ||||
| 90 | // Specialized helpers for shift operations. | |||
| 91 | static MaybeHandle<BigInt> LeftShiftByAbsolute(Isolate* isolate, | |||
| 92 | Handle<BigIntBase> x, | |||
| 93 | Handle<BigIntBase> y); | |||
| 94 | static Handle<BigInt> RightShiftByAbsolute(Isolate* isolate, | |||
| 95 | Handle<BigIntBase> x, | |||
| 96 | Handle<BigIntBase> y); | |||
| 97 | static Handle<BigInt> RightShiftByMaximum(Isolate* isolate, bool sign); | |||
| 98 | static Maybe<digit_t> ToShiftAmount(Handle<BigIntBase> x); | |||
| 99 | ||||
| 100 | static double ToDouble(Handle<BigIntBase> x); | |||
| 101 | enum Rounding { kRoundDown, kTie, kRoundUp }; | |||
| 102 | static Rounding DecideRounding(Handle<BigIntBase> x, int mantissa_bits_unset, | |||
| 103 | int digit_index, uint64_t current_digit); | |||
| 104 | ||||
| 105 | // Returns the least significant 64 bits, simulating two's complement | |||
| 106 | // representation. | |||
| 107 | static uint64_t GetRawBits(BigIntBase x, bool* lossless); | |||
| 108 | ||||
| 109 | static inline bool digit_ismax(digit_t x) { | |||
| 110 | return static_cast<digit_t>(~x) == 0; | |||
| 111 | } | |||
| 112 | ||||
| 113 | // Internal field setters. Non-mutable BigInts don't have these. | |||
| 114 | #include "src/objects/object-macros.h" | |||
| 115 | inline void set_sign(bool new_sign) { | |||
| 116 | int32_t bitfield = RELAXED_READ_INT32_FIELD(*this, kBitfieldOffset); | |||
| 117 | bitfield = SignBits::update(bitfield, new_sign); | |||
| 118 | RELAXED_WRITE_INT32_FIELD(*this, kBitfieldOffset, bitfield); | |||
| 119 | } | |||
| 120 | inline void set_length(int new_length, ReleaseStoreTag) { | |||
| 121 | int32_t bitfield = RELAXED_READ_INT32_FIELD(*this, kBitfieldOffset); | |||
| 122 | bitfield = LengthBits::update(bitfield, new_length); | |||
| 123 | RELEASE_WRITE_INT32_FIELD(*this, kBitfieldOffset, bitfield); | |||
| 124 | } | |||
| 125 | inline void initialize_bitfield(bool sign, int length) { | |||
| 126 | int32_t bitfield = LengthBits::encode(length) | SignBits::encode(sign); | |||
| 127 | WriteField<int32_t>(kBitfieldOffset, bitfield); | |||
| 128 | } | |||
| 129 | inline void set_digit(int n, digit_t value) { | |||
| 130 | SLOW_DCHECK(0 <= n && n < length())((void)0); | |||
| 131 | WriteField<digit_t>(kDigitsOffset + n * kDigitSize, value); | |||
| 132 | } | |||
| 133 | ||||
| 134 | void set_64_bits(uint64_t bits); | |||
| 135 | ||||
| 136 | bool IsMutableBigInt() const { return IsBigInt(); } | |||
| 137 | ||||
| 138 | static_assert(std::is_same<bigint::digit_t, BigIntBase::digit_t>::value, | |||
| 139 | "We must be able to call BigInt library functions"); | |||
| 140 | ||||
| 141 | NEVER_READ_ONLY_SPACE | |||
| 142 | ||||
| 143 | OBJECT_CONSTRUCTORS(MutableBigInt, FreshlyAllocatedBigInt); | |||
| 144 | }; | |||
| 145 | ||||
| 146 | OBJECT_CONSTRUCTORS_IMPL(MutableBigInt, FreshlyAllocatedBigInt) | |||
| 147 | NEVER_READ_ONLY_SPACE_IMPL(MutableBigInt) | |||
| 148 | ||||
| 149 | #include "src/base/platform/wrappers.h" | |||
| 150 | #include "src/objects/object-macros-undef.h" | |||
| 151 | ||||
| 152 | bigint::Digits GetDigits(BigIntBase bigint) { | |||
| 153 | return bigint::Digits( | |||
| 154 | reinterpret_cast<bigint::digit_t*>( | |||
| 155 | bigint.ptr() + BigIntBase::kDigitsOffset - kHeapObjectTag), | |||
| 156 | bigint.length()); | |||
| 157 | } | |||
| 158 | bigint::Digits GetDigits(Handle<BigIntBase> bigint) { | |||
| 159 | return GetDigits(*bigint); | |||
| 160 | } | |||
| 161 | ||||
| 162 | bigint::RWDigits GetRWDigits(MutableBigInt bigint) { | |||
| 163 | return bigint::RWDigits( | |||
| 164 | reinterpret_cast<bigint::digit_t*>( | |||
| 165 | bigint.ptr() + BigIntBase::kDigitsOffset - kHeapObjectTag), | |||
| 166 | bigint.length()); | |||
| 167 | } | |||
| 168 | bigint::RWDigits GetRWDigits(Handle<MutableBigInt> bigint) { | |||
| 169 | return GetRWDigits(*bigint); | |||
| 170 | } | |||
| 171 | ||||
| 172 | template <typename T, typename Isolate> | |||
| 173 | MaybeHandle<T> ThrowBigIntTooBig(Isolate* isolate) { | |||
| 174 | // If the result of a BigInt computation is truncated to 64 bit, Turbofan | |||
| 175 | // can sometimes truncate intermediate results already, which can prevent | |||
| 176 | // those from exceeding the maximum length, effectively preventing a | |||
| 177 | // RangeError from being thrown. As this is a performance optimization, this | |||
| 178 | // behavior is accepted. To prevent the correctness fuzzer from detecting this | |||
| 179 | // difference, we crash the program. | |||
| 180 | if (FLAG_correctness_fuzzer_suppressions) { | |||
| 181 | FATAL("Aborting on invalid BigInt length")V8_Fatal("Aborting on invalid BigInt length"); | |||
| 182 | } | |||
| 183 | THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntTooBig), T)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<T>(__isolate__->factory()->NewRangeError(MessageTemplate ::kBigIntTooBig)); } while (false); | |||
| 184 | } | |||
| 185 | ||||
| 186 | template <typename IsolateT> | |||
| 187 | MaybeHandle<MutableBigInt> MutableBigInt::New(IsolateT* isolate, int length, | |||
| 188 | AllocationType allocation) { | |||
| 189 | if (length > BigInt::kMaxLength) { | |||
| 190 | return ThrowBigIntTooBig<MutableBigInt>(isolate); | |||
| 191 | } | |||
| 192 | Handle<MutableBigInt> result = | |||
| 193 | Cast(isolate->factory()->NewBigInt(length, allocation)); | |||
| 194 | result->initialize_bitfield(false, length); | |||
| 195 | #if DEBUG | |||
| 196 | result->InitializeDigits(length, 0xBF); | |||
| 197 | #endif | |||
| 198 | return result; | |||
| 199 | } | |||
| 200 | ||||
| 201 | Handle<BigInt> MutableBigInt::NewFromInt(Isolate* isolate, int value) { | |||
| 202 | if (value == 0) return Zero(isolate); | |||
| 203 | Handle<MutableBigInt> result = Cast(isolate->factory()->NewBigInt(1)); | |||
| 204 | bool sign = value < 0; | |||
| 205 | result->initialize_bitfield(sign, 1); | |||
| 206 | if (!sign) { | |||
| 207 | result->set_digit(0, value); | |||
| 208 | } else { | |||
| 209 | if (value == kMinInt) { | |||
| 210 | STATIC_ASSERT(kMinInt == -kMaxInt - 1)static_assert(kMinInt == -kMaxInt - 1, "kMinInt == -kMaxInt - 1" ); | |||
| 211 | result->set_digit(0, static_cast<BigInt::digit_t>(kMaxInt) + 1); | |||
| 212 | } else { | |||
| 213 | result->set_digit(0, -value); | |||
| 214 | } | |||
| 215 | } | |||
| 216 | return MakeImmutable(result); | |||
| 217 | } | |||
| 218 | ||||
| 219 | Handle<BigInt> MutableBigInt::NewFromDouble(Isolate* isolate, double value) { | |||
| 220 | DCHECK_EQ(value, std::floor(value))((void) 0); | |||
| 221 | if (value == 0) return Zero(isolate); | |||
| 222 | ||||
| 223 | bool sign = value < 0; // -0 was already handled above. | |||
| 224 | uint64_t double_bits = bit_cast<uint64_t>(value); | |||
| 225 | int raw_exponent = | |||
| 226 | static_cast<int>(double_bits >> base::Double::kPhysicalSignificandSize) & | |||
| 227 | 0x7FF; | |||
| 228 | DCHECK_NE(raw_exponent, 0x7FF)((void) 0); | |||
| 229 | DCHECK_GE(raw_exponent, 0x3FF)((void) 0); | |||
| 230 | int exponent = raw_exponent - 0x3FF; | |||
| 231 | int digits = exponent / kDigitBits + 1; | |||
| 232 | Handle<MutableBigInt> result = Cast(isolate->factory()->NewBigInt(digits)); | |||
| 233 | result->initialize_bitfield(sign, digits); | |||
| 234 | ||||
| 235 | // We construct a BigInt from the double {value} by shifting its mantissa | |||
| 236 | // according to its exponent and mapping the bit pattern onto digits. | |||
| 237 | // | |||
| 238 | // <----------- bitlength = exponent + 1 -----------> | |||
| 239 | // <----- 52 ------> <------ trailing zeroes ------> | |||
| 240 | // mantissa: 1yyyyyyyyyyyyyyyyy 0000000000000000000000000000000 | |||
| 241 | // digits: 0001xxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx | |||
| 242 | // <--> <------> | |||
| 243 | // msd_topbit kDigitBits | |||
| 244 | // | |||
| 245 | uint64_t mantissa = | |||
| 246 | (double_bits & base::Double::kSignificandMask) | base::Double::kHiddenBit; | |||
| 247 | const int kMantissaTopBit = base::Double::kSignificandSize - 1; // 0-indexed. | |||
| 248 | // 0-indexed position of most significant bit in the most significant digit. | |||
| 249 | int msd_topbit = exponent % kDigitBits; | |||
| 250 | // Number of unused bits in {mantissa}. We'll keep them shifted to the | |||
| 251 | // left (i.e. most significant part) of the underlying uint64_t. | |||
| 252 | int remaining_mantissa_bits = 0; | |||
| 253 | // Next digit under construction. | |||
| 254 | digit_t digit; | |||
| 255 | ||||
| 256 | // First, build the MSD by shifting the mantissa appropriately. | |||
| 257 | if (msd_topbit < kMantissaTopBit) { | |||
| 258 | remaining_mantissa_bits = kMantissaTopBit - msd_topbit; | |||
| 259 | digit = mantissa >> remaining_mantissa_bits; | |||
| 260 | mantissa = mantissa << (64 - remaining_mantissa_bits); | |||
| 261 | } else { | |||
| 262 | DCHECK_GE(msd_topbit, kMantissaTopBit)((void) 0); | |||
| 263 | digit = mantissa << (msd_topbit - kMantissaTopBit); | |||
| 264 | mantissa = 0; | |||
| 265 | } | |||
| 266 | result->set_digit(digits - 1, digit); | |||
| 267 | // Then fill in the rest of the digits. | |||
| 268 | for (int digit_index = digits - 2; digit_index >= 0; digit_index--) { | |||
| 269 | if (remaining_mantissa_bits > 0) { | |||
| 270 | remaining_mantissa_bits -= kDigitBits; | |||
| 271 | if (sizeof(digit) == 4) { | |||
| 272 | digit = mantissa >> 32; | |||
| 273 | mantissa = mantissa << 32; | |||
| 274 | } else { | |||
| 275 | DCHECK_EQ(sizeof(digit), 8)((void) 0); | |||
| 276 | digit = mantissa; | |||
| 277 | mantissa = 0; | |||
| 278 | } | |||
| 279 | } else { | |||
| 280 | digit = 0; | |||
| 281 | } | |||
| 282 | result->set_digit(digit_index, digit); | |||
| 283 | } | |||
| 284 | return MakeImmutable(result); | |||
| 285 | } | |||
| 286 | ||||
| 287 | Handle<MutableBigInt> MutableBigInt::Copy(Isolate* isolate, | |||
| 288 | Handle<BigIntBase> source) { | |||
| 289 | int length = source->length(); | |||
| 290 | // Allocating a BigInt of the same length as an existing BigInt cannot throw. | |||
| 291 | Handle<MutableBigInt> result = New(isolate, length).ToHandleChecked(); | |||
| 292 | memcpy(reinterpret_cast<void*>(result->address() + BigIntBase::kHeaderSize), | |||
| 293 | reinterpret_cast<void*>(source->address() + BigIntBase::kHeaderSize), | |||
| 294 | BigInt::SizeFor(length) - BigIntBase::kHeaderSize); | |||
| 295 | return result; | |||
| 296 | } | |||
| 297 | ||||
| 298 | void MutableBigInt::InitializeDigits(int length, byte value) { | |||
| 299 | memset(reinterpret_cast<void*>(ptr() + kDigitsOffset - kHeapObjectTag), value, | |||
| 300 | length * kDigitSize); | |||
| 301 | } | |||
| 302 | ||||
| 303 | MaybeHandle<BigInt> MutableBigInt::MakeImmutable( | |||
| 304 | MaybeHandle<MutableBigInt> maybe) { | |||
| 305 | Handle<MutableBigInt> result; | |||
| 306 | if (!maybe.ToHandle(&result)) return MaybeHandle<BigInt>(); | |||
| 307 | return MakeImmutable(result); | |||
| 308 | } | |||
| 309 | ||||
| 310 | template <typename IsolateT> | |||
| 311 | Handle<BigInt> MutableBigInt::MakeImmutable(Handle<MutableBigInt> result) { | |||
| 312 | MutableBigInt::Canonicalize(*result); | |||
| 313 | return Handle<BigInt>::cast(result); | |||
| 314 | } | |||
| 315 | ||||
| 316 | void MutableBigInt::Canonicalize(MutableBigInt result) { | |||
| 317 | // Check if we need to right-trim any leading zero-digits. | |||
| 318 | int old_length = result.length(); | |||
| 319 | int new_length = old_length; | |||
| 320 | while (new_length > 0 && result.digit(new_length - 1) == 0) new_length--; | |||
| 321 | int to_trim = old_length - new_length; | |||
| 322 | if (to_trim != 0) { | |||
| 323 | int size_delta = to_trim * MutableBigInt::kDigitSize; | |||
| 324 | Address new_end = result.address() + BigInt::SizeFor(new_length); | |||
| 325 | Heap* heap = result.GetHeap(); | |||
| 326 | if (!heap->IsLargeObject(result)) { | |||
| 327 | // We do not create a filler for objects in large object space. | |||
| 328 | // TODO(hpayer): We should shrink the large object page if the size | |||
| 329 | // of the object changed significantly. | |||
| 330 | heap->CreateFillerObjectAt(new_end, size_delta, ClearRecordedSlots::kNo); | |||
| 331 | } | |||
| 332 | result.set_length(new_length, kReleaseStore); | |||
| 333 | ||||
| 334 | // Canonicalize -0n. | |||
| 335 | if (new_length == 0) { | |||
| 336 | result.set_sign(false); | |||
| 337 | // TODO(jkummerow): If we cache a canonical 0n, return that here. | |||
| 338 | } | |||
| 339 | } | |||
| 340 | DCHECK_IMPLIES(result.length() > 0,((void) 0) | |||
| 341 | result.digit(result.length() - 1) != 0)((void) 0); // MSD is non-zero. | |||
| 342 | } | |||
| 343 | ||||
| 344 | template <typename IsolateT> | |||
| 345 | Handle<BigInt> BigInt::Zero(IsolateT* isolate, AllocationType allocation) { | |||
| 346 | return MutableBigInt::Zero(isolate, allocation); | |||
| 347 | } | |||
| 348 | template Handle<BigInt> BigInt::Zero(Isolate* isolate, | |||
| 349 | AllocationType allocation); | |||
| 350 | template Handle<BigInt> BigInt::Zero(LocalIsolate* isolate, | |||
| 351 | AllocationType allocation); | |||
| 352 | ||||
| 353 | Handle<BigInt> BigInt::UnaryMinus(Isolate* isolate, Handle<BigInt> x) { | |||
| 354 | // Special case: There is no -0n. | |||
| 355 | if (x->is_zero()) { | |||
| 356 | return x; | |||
| 357 | } | |||
| 358 | Handle<MutableBigInt> result = MutableBigInt::Copy(isolate, x); | |||
| 359 | result->set_sign(!x->sign()); | |||
| 360 | return MutableBigInt::MakeImmutable(result); | |||
| 361 | } | |||
| 362 | ||||
| 363 | MaybeHandle<BigInt> BigInt::BitwiseNot(Isolate* isolate, Handle<BigInt> x) { | |||
| 364 | MaybeHandle<MutableBigInt> result; | |||
| 365 | if (x->sign()) { | |||
| 366 | // ~(-x) == ~(~(x-1)) == x-1 | |||
| 367 | result = MutableBigInt::AbsoluteSubOne(isolate, x); | |||
| 368 | } else { | |||
| 369 | // ~x == -x-1 == -(x+1) | |||
| 370 | result = MutableBigInt::AbsoluteAddOne(isolate, x, true); | |||
| 371 | } | |||
| 372 | return MutableBigInt::MakeImmutable(result); | |||
| 373 | } | |||
| 374 | ||||
| 375 | MaybeHandle<BigInt> BigInt::Exponentiate(Isolate* isolate, Handle<BigInt> base, | |||
| 376 | Handle<BigInt> exponent) { | |||
| 377 | // 1. If exponent is < 0, throw a RangeError exception. | |||
| 378 | if (exponent->sign()) { | |||
| 379 | THROW_NEW_ERROR(isolate,do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntNegativeExponent)); } while (false) | |||
| 380 | NewRangeError(MessageTemplate::kBigIntNegativeExponent),do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntNegativeExponent)); } while (false) | |||
| 381 | BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntNegativeExponent)); } while (false); | |||
| 382 | } | |||
| 383 | // 2. If base is 0n and exponent is 0n, return 1n. | |||
| 384 | if (exponent->is_zero()) { | |||
| 385 | return MutableBigInt::NewFromInt(isolate, 1); | |||
| 386 | } | |||
| 387 | // 3. Return a BigInt representing the mathematical value of base raised | |||
| 388 | // to the power exponent. | |||
| 389 | if (base->is_zero()) return base; | |||
| 390 | if (base->length() == 1 && base->digit(0) == 1) { | |||
| 391 | // (-1) ** even_number == 1. | |||
| 392 | if (base->sign() && (exponent->digit(0) & 1) == 0) { | |||
| 393 | return UnaryMinus(isolate, base); | |||
| 394 | } | |||
| 395 | // (-1) ** odd_number == -1; 1 ** anything == 1. | |||
| 396 | return base; | |||
| 397 | } | |||
| 398 | // For all bases >= 2, very large exponents would lead to unrepresentable | |||
| 399 | // results. | |||
| 400 | STATIC_ASSERT(kMaxLengthBits < std::numeric_limits<digit_t>::max())static_assert(kMaxLengthBits < std::numeric_limits<digit_t >::max(), "kMaxLengthBits < std::numeric_limits<digit_t>::max()" ); | |||
| 401 | if (exponent->length() > 1) { | |||
| 402 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 403 | } | |||
| 404 | digit_t exp_value = exponent->digit(0); | |||
| 405 | if (exp_value == 1) return base; | |||
| 406 | if (exp_value >= kMaxLengthBits) { | |||
| 407 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 408 | } | |||
| 409 | STATIC_ASSERT(kMaxLengthBits <= kMaxInt)static_assert(kMaxLengthBits <= kMaxInt, "kMaxLengthBits <= kMaxInt" ); | |||
| 410 | int n = static_cast<int>(exp_value); | |||
| 411 | if (base->length() == 1 && base->digit(0) == 2) { | |||
| 412 | // Fast path for 2^n. | |||
| 413 | int needed_digits = 1 + (n / kDigitBits); | |||
| 414 | Handle<MutableBigInt> result; | |||
| 415 | if (!MutableBigInt::New(isolate, needed_digits).ToHandle(&result)) { | |||
| 416 | return MaybeHandle<BigInt>(); | |||
| 417 | } | |||
| 418 | result->InitializeDigits(needed_digits); | |||
| 419 | // All bits are zero. Now set the n-th bit. | |||
| 420 | digit_t msd = static_cast<digit_t>(1) << (n % kDigitBits); | |||
| 421 | result->set_digit(needed_digits - 1, msd); | |||
| 422 | // Result is negative for odd powers of -2n. | |||
| 423 | if (base->sign()) result->set_sign((n & 1) != 0); | |||
| 424 | return MutableBigInt::MakeImmutable(result); | |||
| 425 | } | |||
| 426 | Handle<BigInt> result; | |||
| 427 | Handle<BigInt> running_square = base; | |||
| 428 | // This implicitly sets the result's sign correctly. | |||
| 429 | if (n & 1) result = base; | |||
| 430 | n >>= 1; | |||
| 431 | for (; n != 0; n >>= 1) { | |||
| 432 | MaybeHandle<BigInt> maybe_result = | |||
| 433 | Multiply(isolate, running_square, running_square); | |||
| 434 | if (!maybe_result.ToHandle(&running_square)) return maybe_result; | |||
| 435 | if (n & 1) { | |||
| 436 | if (result.is_null()) { | |||
| 437 | result = running_square; | |||
| 438 | } else { | |||
| 439 | maybe_result = Multiply(isolate, result, running_square); | |||
| 440 | if (!maybe_result.ToHandle(&result)) return maybe_result; | |||
| 441 | } | |||
| 442 | } | |||
| 443 | } | |||
| 444 | return result; | |||
| 445 | } | |||
| 446 | ||||
| 447 | MaybeHandle<BigInt> BigInt::Multiply(Isolate* isolate, Handle<BigInt> x, | |||
| 448 | Handle<BigInt> y) { | |||
| 449 | if (x->is_zero()) return x; | |||
| 450 | if (y->is_zero()) return y; | |||
| 451 | int result_length = bigint::MultiplyResultLength(GetDigits(x), GetDigits(y)); | |||
| 452 | Handle<MutableBigInt> result; | |||
| 453 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) { | |||
| 454 | return MaybeHandle<BigInt>(); | |||
| 455 | } | |||
| 456 | DisallowGarbageCollection no_gc; | |||
| 457 | bigint::Status status = isolate->bigint_processor()->Multiply( | |||
| 458 | GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 459 | if (status == bigint::Status::kInterrupted) { | |||
| 460 | AllowGarbageCollection terminating_anyway; | |||
| 461 | isolate->TerminateExecution(); | |||
| 462 | return {}; | |||
| 463 | } | |||
| 464 | result->set_sign(x->sign() != y->sign()); | |||
| 465 | return MutableBigInt::MakeImmutable(result); | |||
| 466 | } | |||
| 467 | ||||
| 468 | MaybeHandle<BigInt> BigInt::Divide(Isolate* isolate, Handle<BigInt> x, | |||
| 469 | Handle<BigInt> y) { | |||
| 470 | // 1. If y is 0n, throw a RangeError exception. | |||
| 471 | if (y->is_zero()) { | |||
| 472 | THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntDivZero),do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntDivZero)); } while (false) | |||
| 473 | BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntDivZero)); } while (false); | |||
| 474 | } | |||
| 475 | // 2. Let quotient be the mathematical value of x divided by y. | |||
| 476 | // 3. Return a BigInt representing quotient rounded towards 0 to the next | |||
| 477 | // integral value. | |||
| 478 | if (bigint::Compare(GetDigits(x), GetDigits(y)) < 0) { | |||
| 479 | return Zero(isolate); | |||
| 480 | } | |||
| 481 | bool result_sign = x->sign() != y->sign(); | |||
| 482 | if (y->length() == 1 && y->digit(0) == 1) { | |||
| 483 | return result_sign == x->sign() ? x : UnaryMinus(isolate, x); | |||
| 484 | } | |||
| 485 | Handle<MutableBigInt> quotient; | |||
| 486 | int result_length = bigint::DivideResultLength(GetDigits(x), GetDigits(y)); | |||
| 487 | if (!MutableBigInt::New(isolate, result_length).ToHandle("ient)) { | |||
| 488 | return {}; | |||
| 489 | } | |||
| 490 | DisallowGarbageCollection no_gc; | |||
| 491 | bigint::Status status = isolate->bigint_processor()->Divide( | |||
| 492 | GetRWDigits(quotient), GetDigits(x), GetDigits(y)); | |||
| 493 | if (status == bigint::Status::kInterrupted) { | |||
| 494 | AllowGarbageCollection terminating_anyway; | |||
| 495 | isolate->TerminateExecution(); | |||
| 496 | return {}; | |||
| 497 | } | |||
| 498 | quotient->set_sign(result_sign); | |||
| 499 | return MutableBigInt::MakeImmutable(quotient); | |||
| 500 | } | |||
| 501 | ||||
| 502 | MaybeHandle<BigInt> BigInt::Remainder(Isolate* isolate, Handle<BigInt> x, | |||
| 503 | Handle<BigInt> y) { | |||
| 504 | // 1. If y is 0n, throw a RangeError exception. | |||
| 505 | if (y->is_zero()) { | |||
| 506 | THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kBigIntDivZero),do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntDivZero)); } while (false) | |||
| 507 | BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntDivZero)); } while (false); | |||
| 508 | } | |||
| 509 | // 2. Return the BigInt representing x modulo y. | |||
| 510 | // See https://github.com/tc39/proposal-bigint/issues/84 though. | |||
| 511 | if (bigint::Compare(GetDigits(x), GetDigits(y)) < 0) return x; | |||
| 512 | if (y->length() == 1 && y->digit(0) == 1) return Zero(isolate); | |||
| 513 | Handle<MutableBigInt> remainder; | |||
| 514 | int result_length = bigint::ModuloResultLength(GetDigits(y)); | |||
| 515 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&remainder)) { | |||
| 516 | return {}; | |||
| 517 | } | |||
| 518 | DisallowGarbageCollection no_gc; | |||
| 519 | bigint::Status status = isolate->bigint_processor()->Modulo( | |||
| 520 | GetRWDigits(remainder), GetDigits(x), GetDigits(y)); | |||
| 521 | if (status == bigint::Status::kInterrupted) { | |||
| 522 | AllowGarbageCollection terminating_anyway; | |||
| 523 | isolate->TerminateExecution(); | |||
| 524 | return {}; | |||
| 525 | } | |||
| 526 | remainder->set_sign(x->sign()); | |||
| 527 | return MutableBigInt::MakeImmutable(remainder); | |||
| 528 | } | |||
| 529 | ||||
| 530 | MaybeHandle<BigInt> BigInt::Add(Isolate* isolate, Handle<BigInt> x, | |||
| 531 | Handle<BigInt> y) { | |||
| 532 | if (x->is_zero()) return y; | |||
| 533 | if (y->is_zero()) return x; | |||
| 534 | bool xsign = x->sign(); | |||
| 535 | bool ysign = y->sign(); | |||
| 536 | int result_length = | |||
| 537 | bigint::AddSignedResultLength(x->length(), y->length(), xsign == ysign); | |||
| 538 | Handle<MutableBigInt> result; | |||
| 539 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) { | |||
| 540 | // Allocation fails when {result_length} exceeds the max BigInt size. | |||
| 541 | return {}; | |||
| 542 | } | |||
| 543 | DisallowGarbageCollection no_gc; | |||
| 544 | bool result_sign = bigint::AddSigned(GetRWDigits(result), GetDigits(x), xsign, | |||
| 545 | GetDigits(y), ysign); | |||
| 546 | result->set_sign(result_sign); | |||
| 547 | return MutableBigInt::MakeImmutable(result); | |||
| 548 | } | |||
| 549 | ||||
| 550 | MaybeHandle<BigInt> BigInt::Subtract(Isolate* isolate, Handle<BigInt> x, | |||
| 551 | Handle<BigInt> y) { | |||
| 552 | if (y->is_zero()) return x; | |||
| 553 | if (x->is_zero()) return UnaryMinus(isolate, y); | |||
| 554 | bool xsign = x->sign(); | |||
| 555 | bool ysign = y->sign(); | |||
| 556 | int result_length = bigint::SubtractSignedResultLength( | |||
| 557 | x->length(), y->length(), xsign == ysign); | |||
| 558 | Handle<MutableBigInt> result; | |||
| 559 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) { | |||
| 560 | // Allocation fails when {result_length} exceeds the max BigInt size. | |||
| 561 | return {}; | |||
| 562 | } | |||
| 563 | DisallowGarbageCollection no_gc; | |||
| 564 | bool result_sign = bigint::SubtractSigned(GetRWDigits(result), GetDigits(x), | |||
| 565 | xsign, GetDigits(y), ysign); | |||
| 566 | result->set_sign(result_sign); | |||
| 567 | return MutableBigInt::MakeImmutable(result); | |||
| 568 | } | |||
| 569 | ||||
| 570 | MaybeHandle<BigInt> BigInt::LeftShift(Isolate* isolate, Handle<BigInt> x, | |||
| 571 | Handle<BigInt> y) { | |||
| 572 | if (y->is_zero() || x->is_zero()) return x; | |||
| 573 | if (y->sign()) return MutableBigInt::RightShiftByAbsolute(isolate, x, y); | |||
| 574 | return MutableBigInt::LeftShiftByAbsolute(isolate, x, y); | |||
| 575 | } | |||
| 576 | ||||
| 577 | MaybeHandle<BigInt> BigInt::SignedRightShift(Isolate* isolate, Handle<BigInt> x, | |||
| 578 | Handle<BigInt> y) { | |||
| 579 | if (y->is_zero() || x->is_zero()) return x; | |||
| 580 | if (y->sign()) return MutableBigInt::LeftShiftByAbsolute(isolate, x, y); | |||
| 581 | return MutableBigInt::RightShiftByAbsolute(isolate, x, y); | |||
| 582 | } | |||
| 583 | ||||
| 584 | MaybeHandle<BigInt> BigInt::UnsignedRightShift(Isolate* isolate, | |||
| 585 | Handle<BigInt> x, | |||
| 586 | Handle<BigInt> y) { | |||
| 587 | THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntShr), BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewTypeError (MessageTemplate::kBigIntShr)); } while (false); | |||
| 588 | } | |||
| 589 | ||||
| 590 | namespace { | |||
| 591 | ||||
| 592 | // Produces comparison result for {left_negative} == sign(x) != sign(y). | |||
| 593 | ComparisonResult UnequalSign(bool left_negative) { | |||
| 594 | return left_negative ? ComparisonResult::kLessThan | |||
| 595 | : ComparisonResult::kGreaterThan; | |||
| 596 | } | |||
| 597 | ||||
| 598 | // Produces result for |x| > |y|, with {both_negative} == sign(x) == sign(y); | |||
| 599 | ComparisonResult AbsoluteGreater(bool both_negative) { | |||
| 600 | return both_negative ? ComparisonResult::kLessThan | |||
| 601 | : ComparisonResult::kGreaterThan; | |||
| 602 | } | |||
| 603 | ||||
| 604 | // Produces result for |x| < |y|, with {both_negative} == sign(x) == sign(y). | |||
| 605 | ComparisonResult AbsoluteLess(bool both_negative) { | |||
| 606 | return both_negative ? ComparisonResult::kGreaterThan | |||
| 607 | : ComparisonResult::kLessThan; | |||
| 608 | } | |||
| 609 | ||||
| 610 | } // namespace | |||
| 611 | ||||
| 612 | // (Never returns kUndefined.) | |||
| 613 | ComparisonResult BigInt::CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y) { | |||
| 614 | bool x_sign = x->sign(); | |||
| 615 | if (x_sign != y->sign()) return UnequalSign(x_sign); | |||
| 616 | ||||
| 617 | int result = bigint::Compare(GetDigits(x), GetDigits(y)); | |||
| 618 | if (result > 0) return AbsoluteGreater(x_sign); | |||
| 619 | if (result < 0) return AbsoluteLess(x_sign); | |||
| 620 | return ComparisonResult::kEqual; | |||
| 621 | } | |||
| 622 | ||||
| 623 | bool BigInt::EqualToBigInt(BigInt x, BigInt y) { | |||
| 624 | if (x.sign() != y.sign()) return false; | |||
| 625 | if (x.length() != y.length()) return false; | |||
| 626 | for (int i = 0; i < x.length(); i++) { | |||
| 627 | if (x.digit(i) != y.digit(i)) return false; | |||
| 628 | } | |||
| 629 | return true; | |||
| 630 | } | |||
| 631 | ||||
| 632 | MaybeHandle<BigInt> BigInt::BitwiseAnd(Isolate* isolate, Handle<BigInt> x, | |||
| 633 | Handle<BigInt> y) { | |||
| 634 | bool x_sign = x->sign(); | |||
| 635 | bool y_sign = y->sign(); | |||
| 636 | Handle<MutableBigInt> result; | |||
| 637 | if (!x_sign && !y_sign) { | |||
| 638 | int result_length = | |||
| 639 | bigint::BitwiseAnd_PosPos_ResultLength(x->length(), y->length()); | |||
| 640 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 641 | bigint::BitwiseAnd_PosPos(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 642 | DCHECK(!result->sign())((void) 0); | |||
| 643 | } else if (x_sign && y_sign) { | |||
| 644 | int result_length = | |||
| 645 | bigint::BitwiseAnd_NegNeg_ResultLength(x->length(), y->length()); | |||
| 646 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) { | |||
| 647 | return {}; | |||
| 648 | } | |||
| 649 | bigint::BitwiseAnd_NegNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 650 | result->set_sign(true); | |||
| 651 | } else { | |||
| 652 | if (x_sign) std::swap(x, y); | |||
| 653 | int result_length = bigint::BitwiseAnd_PosNeg_ResultLength(x->length()); | |||
| 654 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 655 | bigint::BitwiseAnd_PosNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 656 | DCHECK(!result->sign())((void) 0); | |||
| 657 | } | |||
| 658 | return MutableBigInt::MakeImmutable(result); | |||
| 659 | } | |||
| 660 | ||||
| 661 | MaybeHandle<BigInt> BigInt::BitwiseXor(Isolate* isolate, Handle<BigInt> x, | |||
| 662 | Handle<BigInt> y) { | |||
| 663 | bool x_sign = x->sign(); | |||
| 664 | bool y_sign = y->sign(); | |||
| 665 | Handle<MutableBigInt> result; | |||
| 666 | if (!x_sign && !y_sign) { | |||
| 667 | int result_length = | |||
| 668 | bigint::BitwiseXor_PosPos_ResultLength(x->length(), y->length()); | |||
| 669 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 670 | bigint::BitwiseXor_PosPos(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 671 | DCHECK(!result->sign())((void) 0); | |||
| 672 | } else if (x_sign && y_sign) { | |||
| 673 | int result_length = | |||
| 674 | bigint::BitwiseXor_NegNeg_ResultLength(x->length(), y->length()); | |||
| 675 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 676 | bigint::BitwiseXor_NegNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 677 | DCHECK(!result->sign())((void) 0); | |||
| 678 | } else { | |||
| 679 | if (x_sign) std::swap(x, y); | |||
| 680 | int result_length = | |||
| 681 | bigint::BitwiseXor_PosNeg_ResultLength(x->length(), y->length()); | |||
| 682 | if (!MutableBigInt::New(isolate, result_length).ToHandle(&result)) { | |||
| 683 | return {}; | |||
| 684 | } | |||
| 685 | bigint::BitwiseXor_PosNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 686 | result->set_sign(true); | |||
| 687 | } | |||
| 688 | return MutableBigInt::MakeImmutable(result); | |||
| 689 | } | |||
| 690 | ||||
| 691 | MaybeHandle<BigInt> BigInt::BitwiseOr(Isolate* isolate, Handle<BigInt> x, | |||
| 692 | Handle<BigInt> y) { | |||
| 693 | bool x_sign = x->sign(); | |||
| 694 | bool y_sign = y->sign(); | |||
| 695 | int result_length = bigint::BitwiseOrResultLength(x->length(), y->length()); | |||
| 696 | Handle<MutableBigInt> result = | |||
| 697 | MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 698 | if (!x_sign && !y_sign) { | |||
| 699 | bigint::BitwiseOr_PosPos(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 700 | DCHECK(!result->sign())((void) 0); | |||
| 701 | } else if (x_sign && y_sign) { | |||
| 702 | bigint::BitwiseOr_NegNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 703 | result->set_sign(true); | |||
| 704 | } else { | |||
| 705 | if (x_sign) std::swap(x, y); | |||
| 706 | bigint::BitwiseOr_PosNeg(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 707 | result->set_sign(true); | |||
| 708 | } | |||
| 709 | return MutableBigInt::MakeImmutable(result); | |||
| 710 | } | |||
| 711 | ||||
| 712 | MaybeHandle<BigInt> BigInt::Increment(Isolate* isolate, Handle<BigInt> x) { | |||
| 713 | if (x->sign()) { | |||
| 714 | Handle<MutableBigInt> result = MutableBigInt::AbsoluteSubOne(isolate, x); | |||
| 715 | result->set_sign(true); | |||
| 716 | return MutableBigInt::MakeImmutable(result); | |||
| 717 | } else { | |||
| 718 | return MutableBigInt::MakeImmutable( | |||
| 719 | MutableBigInt::AbsoluteAddOne(isolate, x, false)); | |||
| 720 | } | |||
| 721 | } | |||
| 722 | ||||
| 723 | MaybeHandle<BigInt> BigInt::Decrement(Isolate* isolate, Handle<BigInt> x) { | |||
| 724 | MaybeHandle<MutableBigInt> result; | |||
| 725 | if (x->sign()) { | |||
| 726 | result = MutableBigInt::AbsoluteAddOne(isolate, x, true); | |||
| 727 | } else if (x->is_zero()) { | |||
| 728 | // TODO(jkummerow): Consider caching a canonical -1n BigInt. | |||
| 729 | return MutableBigInt::NewFromInt(isolate, -1); | |||
| 730 | } else { | |||
| 731 | result = MutableBigInt::AbsoluteSubOne(isolate, x); | |||
| 732 | } | |||
| 733 | return MutableBigInt::MakeImmutable(result); | |||
| 734 | } | |||
| 735 | ||||
| 736 | Maybe<ComparisonResult> BigInt::CompareToString(Isolate* isolate, | |||
| 737 | Handle<BigInt> x, | |||
| 738 | Handle<String> y) { | |||
| 739 | // a. Let ny be StringToBigInt(y); | |||
| 740 | MaybeHandle<BigInt> maybe_ny = StringToBigInt(isolate, y); | |||
| 741 | // b. If ny is NaN, return undefined. | |||
| 742 | Handle<BigInt> ny; | |||
| 743 | if (!maybe_ny.ToHandle(&ny)) { | |||
| 744 | if (isolate->has_pending_exception()) { | |||
| 745 | return Nothing<ComparisonResult>(); | |||
| 746 | } else { | |||
| 747 | return Just(ComparisonResult::kUndefined); | |||
| 748 | } | |||
| 749 | } | |||
| 750 | // c. Return BigInt::lessThan(x, ny). | |||
| 751 | return Just(CompareToBigInt(x, ny)); | |||
| 752 | } | |||
| 753 | ||||
| 754 | Maybe<bool> BigInt::EqualToString(Isolate* isolate, Handle<BigInt> x, | |||
| 755 | Handle<String> y) { | |||
| 756 | // a. Let n be StringToBigInt(y). | |||
| 757 | MaybeHandle<BigInt> maybe_n = StringToBigInt(isolate, y); | |||
| 758 | // b. If n is NaN, return false. | |||
| 759 | Handle<BigInt> n; | |||
| 760 | if (!maybe_n.ToHandle(&n)) { | |||
| 761 | if (isolate->has_pending_exception()) { | |||
| 762 | return Nothing<bool>(); | |||
| 763 | } else { | |||
| 764 | return Just(false); | |||
| 765 | } | |||
| 766 | } | |||
| 767 | // c. Return the result of x == n. | |||
| 768 | return Just(EqualToBigInt(*x, *n)); | |||
| 769 | } | |||
| 770 | ||||
| 771 | bool BigInt::EqualToNumber(Handle<BigInt> x, Handle<Object> y) { | |||
| 772 | DCHECK(y->IsNumber())((void) 0); | |||
| 773 | // a. If x or y are any of NaN, +∞, or -∞, return false. | |||
| 774 | // b. If the mathematical value of x is equal to the mathematical value of y, | |||
| 775 | // return true, otherwise return false. | |||
| 776 | if (y->IsSmi()) { | |||
| 777 | int value = Smi::ToInt(*y); | |||
| 778 | if (value == 0) return x->is_zero(); | |||
| 779 | // Any multi-digit BigInt is bigger than a Smi. | |||
| 780 | STATIC_ASSERT(sizeof(digit_t) >= sizeof(value))static_assert(sizeof(digit_t) >= sizeof(value), "sizeof(digit_t) >= sizeof(value)" ); | |||
| 781 | return (x->length() == 1) && (x->sign() == (value < 0)) && | |||
| 782 | (x->digit(0) == | |||
| 783 | static_cast<digit_t>(std::abs(static_cast<int64_t>(value)))); | |||
| 784 | } | |||
| 785 | DCHECK(y->IsHeapNumber())((void) 0); | |||
| 786 | double value = Handle<HeapNumber>::cast(y)->value(); | |||
| 787 | return CompareToDouble(x, value) == ComparisonResult::kEqual; | |||
| 788 | } | |||
| 789 | ||||
| 790 | ComparisonResult BigInt::CompareToNumber(Handle<BigInt> x, Handle<Object> y) { | |||
| 791 | DCHECK(y->IsNumber())((void) 0); | |||
| 792 | if (y->IsSmi()) { | |||
| 793 | bool x_sign = x->sign(); | |||
| 794 | int y_value = Smi::ToInt(*y); | |||
| 795 | bool y_sign = (y_value < 0); | |||
| 796 | if (x_sign != y_sign) return UnequalSign(x_sign); | |||
| 797 | ||||
| 798 | if (x->is_zero()) { | |||
| 799 | DCHECK(!y_sign)((void) 0); | |||
| 800 | return y_value == 0 ? ComparisonResult::kEqual | |||
| 801 | : ComparisonResult::kLessThan; | |||
| 802 | } | |||
| 803 | // Any multi-digit BigInt is bigger than a Smi. | |||
| 804 | STATIC_ASSERT(sizeof(digit_t) >= sizeof(y_value))static_assert(sizeof(digit_t) >= sizeof(y_value), "sizeof(digit_t) >= sizeof(y_value)" ); | |||
| 805 | if (x->length() > 1) return AbsoluteGreater(x_sign); | |||
| 806 | ||||
| 807 | digit_t abs_value = std::abs(static_cast<int64_t>(y_value)); | |||
| 808 | digit_t x_digit = x->digit(0); | |||
| 809 | if (x_digit > abs_value) return AbsoluteGreater(x_sign); | |||
| 810 | if (x_digit < abs_value) return AbsoluteLess(x_sign); | |||
| 811 | return ComparisonResult::kEqual; | |||
| 812 | } | |||
| 813 | DCHECK(y->IsHeapNumber())((void) 0); | |||
| 814 | double value = Handle<HeapNumber>::cast(y)->value(); | |||
| 815 | return CompareToDouble(x, value); | |||
| 816 | } | |||
| 817 | ||||
| 818 | ComparisonResult BigInt::CompareToDouble(Handle<BigInt> x, double y) { | |||
| 819 | if (std::isnan(y)) return ComparisonResult::kUndefined; | |||
| 820 | if (y == V8_INFINITYstd::numeric_limits<double>::infinity()) return ComparisonResult::kLessThan; | |||
| 821 | if (y == -V8_INFINITYstd::numeric_limits<double>::infinity()) return ComparisonResult::kGreaterThan; | |||
| 822 | bool x_sign = x->sign(); | |||
| 823 | // Note that this is different from the double's sign bit for -0. That's | |||
| 824 | // intentional because -0 must be treated like 0. | |||
| 825 | bool y_sign = (y < 0); | |||
| 826 | if (x_sign != y_sign) return UnequalSign(x_sign); | |||
| 827 | if (y == 0) { | |||
| 828 | DCHECK(!x_sign)((void) 0); | |||
| 829 | return x->is_zero() ? ComparisonResult::kEqual | |||
| 830 | : ComparisonResult::kGreaterThan; | |||
| 831 | } | |||
| 832 | if (x->is_zero()) { | |||
| 833 | DCHECK(!y_sign)((void) 0); | |||
| 834 | return ComparisonResult::kLessThan; | |||
| 835 | } | |||
| 836 | uint64_t double_bits = bit_cast<uint64_t>(y); | |||
| 837 | int raw_exponent = | |||
| 838 | static_cast<int>(double_bits >> base::Double::kPhysicalSignificandSize) & | |||
| 839 | 0x7FF; | |||
| 840 | uint64_t mantissa = double_bits & base::Double::kSignificandMask; | |||
| 841 | // Non-finite doubles are handled above. | |||
| 842 | DCHECK_NE(raw_exponent, 0x7FF)((void) 0); | |||
| 843 | int exponent = raw_exponent - 0x3FF; | |||
| 844 | if (exponent < 0) { | |||
| 845 | // The absolute value of the double is less than 1. Only 0n has an | |||
| 846 | // absolute value smaller than that, but we've already covered that case. | |||
| 847 | DCHECK(!x->is_zero())((void) 0); | |||
| 848 | return AbsoluteGreater(x_sign); | |||
| 849 | } | |||
| 850 | int x_length = x->length(); | |||
| 851 | digit_t x_msd = x->digit(x_length - 1); | |||
| 852 | int msd_leading_zeros = base::bits::CountLeadingZeros(x_msd); | |||
| 853 | int x_bitlength = x_length * kDigitBits - msd_leading_zeros; | |||
| 854 | int y_bitlength = exponent + 1; | |||
| 855 | if (x_bitlength < y_bitlength) return AbsoluteLess(x_sign); | |||
| 856 | if (x_bitlength > y_bitlength) return AbsoluteGreater(x_sign); | |||
| 857 | ||||
| 858 | // At this point, we know that signs and bit lengths (i.e. position of | |||
| 859 | // the most significant bit in exponent-free representation) are identical. | |||
| 860 | // {x} is not zero, {y} is finite and not denormal. | |||
| 861 | // Now we virtually convert the double to an integer by shifting its | |||
| 862 | // mantissa according to its exponent, so it will align with the BigInt {x}, | |||
| 863 | // and then we compare them bit for bit until we find a difference or the | |||
| 864 | // least significant bit. | |||
| 865 | // <----- 52 ------> <-- virtual trailing zeroes --> | |||
| 866 | // y / mantissa: 1yyyyyyyyyyyyyyyyy 0000000000000000000000000000000 | |||
| 867 | // x / digits: 0001xxxx xxxxxxxx xxxxxxxx ... | |||
| 868 | // <--> <------> | |||
| 869 | // msd_topbit kDigitBits | |||
| 870 | // | |||
| 871 | mantissa |= base::Double::kHiddenBit; | |||
| 872 | const int kMantissaTopBit = 52; // 0-indexed. | |||
| 873 | // 0-indexed position of {x}'s most significant bit within the {msd}. | |||
| 874 | int msd_topbit = kDigitBits - 1 - msd_leading_zeros; | |||
| 875 | DCHECK_EQ(msd_topbit, (x_bitlength - 1) % kDigitBits)((void) 0); | |||
| 876 | // Shifted chunk of {mantissa} for comparing with {digit}. | |||
| 877 | digit_t compare_mantissa; | |||
| 878 | // Number of unprocessed bits in {mantissa}. We'll keep them shifted to | |||
| 879 | // the left (i.e. most significant part) of the underlying uint64_t. | |||
| 880 | int remaining_mantissa_bits = 0; | |||
| 881 | ||||
| 882 | // First, compare the most significant digit against the beginning of | |||
| 883 | // the mantissa. | |||
| 884 | if (msd_topbit < kMantissaTopBit) { | |||
| 885 | remaining_mantissa_bits = (kMantissaTopBit - msd_topbit); | |||
| 886 | compare_mantissa = mantissa >> remaining_mantissa_bits; | |||
| 887 | mantissa = mantissa << (64 - remaining_mantissa_bits); | |||
| 888 | } else { | |||
| 889 | DCHECK_GE(msd_topbit, kMantissaTopBit)((void) 0); | |||
| 890 | compare_mantissa = mantissa << (msd_topbit - kMantissaTopBit); | |||
| 891 | mantissa = 0; | |||
| 892 | } | |||
| 893 | if (x_msd > compare_mantissa) return AbsoluteGreater(x_sign); | |||
| 894 | if (x_msd < compare_mantissa) return AbsoluteLess(x_sign); | |||
| 895 | ||||
| 896 | // Then, compare additional digits against any remaining mantissa bits. | |||
| 897 | for (int digit_index = x_length - 2; digit_index >= 0; digit_index--) { | |||
| 898 | if (remaining_mantissa_bits > 0) { | |||
| 899 | remaining_mantissa_bits -= kDigitBits; | |||
| 900 | if (sizeof(mantissa) != sizeof(x_msd)) { | |||
| 901 | compare_mantissa = mantissa >> (64 - kDigitBits); | |||
| 902 | // "& 63" to appease compilers. kDigitBits is 32 here anyway. | |||
| 903 | mantissa = mantissa << (kDigitBits & 63); | |||
| 904 | } else { | |||
| 905 | compare_mantissa = mantissa; | |||
| 906 | mantissa = 0; | |||
| 907 | } | |||
| 908 | } else { | |||
| 909 | compare_mantissa = 0; | |||
| 910 | } | |||
| 911 | digit_t digit = x->digit(digit_index); | |||
| 912 | if (digit > compare_mantissa) return AbsoluteGreater(x_sign); | |||
| 913 | if (digit < compare_mantissa) return AbsoluteLess(x_sign); | |||
| 914 | } | |||
| 915 | ||||
| 916 | // Integer parts are equal; check whether {y} has a fractional part. | |||
| 917 | if (mantissa != 0) { | |||
| 918 | DCHECK_GT(remaining_mantissa_bits, 0)((void) 0); | |||
| 919 | return AbsoluteLess(x_sign); | |||
| 920 | } | |||
| 921 | return ComparisonResult::kEqual; | |||
| 922 | } | |||
| 923 | ||||
| 924 | MaybeHandle<String> BigInt::ToString(Isolate* isolate, Handle<BigInt> bigint, | |||
| 925 | int radix, ShouldThrow should_throw) { | |||
| 926 | if (bigint->is_zero()) { | |||
| 927 | return isolate->factory()->zero_string(); | |||
| 928 | } | |||
| 929 | const bool sign = bigint->sign(); | |||
| 930 | int chars_allocated; | |||
| 931 | int chars_written; | |||
| 932 | Handle<SeqOneByteString> result; | |||
| 933 | if (bigint->length() == 1 && radix == 10) { | |||
| 934 | // Fast path for the most common case, to avoid call/dispatch overhead. | |||
| 935 | // The logic is the same as what the full implementation does below, | |||
| 936 | // just inlined and specialized for the preconditions. | |||
| 937 | // Microbenchmarks rejoice! | |||
| 938 | digit_t digit = bigint->digit(0); | |||
| 939 | int bit_length = kDigitBits - base::bits::CountLeadingZeros(digit); | |||
| 940 | constexpr int kShift = 7; | |||
| 941 | // This is Math.log2(10) * (1 << kShift), scaled just far enough to | |||
| 942 | // make the computations below always precise (after rounding). | |||
| 943 | constexpr int kShiftedBitsPerChar = 425; | |||
| 944 | chars_allocated = (bit_length << kShift) / kShiftedBitsPerChar + 1 + sign; | |||
| 945 | result = isolate->factory() | |||
| 946 | ->NewRawOneByteString(chars_allocated) | |||
| 947 | .ToHandleChecked(); | |||
| 948 | DisallowGarbageCollection no_gc; | |||
| 949 | uint8_t* start = result->GetChars(no_gc); | |||
| 950 | uint8_t* out = start + chars_allocated; | |||
| 951 | while (digit != 0) { | |||
| 952 | *(--out) = '0' + (digit % 10); | |||
| 953 | digit /= 10; | |||
| 954 | } | |||
| 955 | if (sign) *(--out) = '-'; | |||
| 956 | if (out == start) { | |||
| 957 | chars_written = chars_allocated; | |||
| 958 | } else { | |||
| 959 | DCHECK_LT(start, out)((void) 0); | |||
| 960 | // The result is one character shorter than predicted. This is | |||
| 961 | // unavoidable, e.g. a 4-bit BigInt can be as big as "10" or as small as | |||
| 962 | // "9", so we must allocate 2 characters for it, and will only later find | |||
| 963 | // out whether all characters were used. | |||
| 964 | chars_written = chars_allocated - static_cast<int>(out - start); | |||
| 965 | std::memmove(start, out, chars_written); | |||
| 966 | } | |||
| 967 | } else { | |||
| 968 | // Generic path, handles anything. | |||
| 969 | DCHECK(radix >= 2 && radix <= 36)((void) 0); | |||
| 970 | chars_allocated = | |||
| 971 | bigint::ToStringResultLength(GetDigits(bigint), radix, sign); | |||
| 972 | if (chars_allocated > String::kMaxLength) { | |||
| 973 | if (should_throw == kThrowOnError) { | |||
| 974 | THROW_NEW_ERROR(isolate, NewInvalidStringLengthError(), String)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<String>(__isolate__->factory()->NewInvalidStringLengthError ()); } while (false); | |||
| 975 | } else { | |||
| 976 | return {}; | |||
| 977 | } | |||
| 978 | } | |||
| 979 | result = isolate->factory() | |||
| 980 | ->NewRawOneByteString(chars_allocated) | |||
| 981 | .ToHandleChecked(); | |||
| 982 | chars_written = chars_allocated; | |||
| 983 | DisallowGarbageCollection no_gc; | |||
| 984 | char* characters = reinterpret_cast<char*>(result->GetChars(no_gc)); | |||
| 985 | bigint::Status status = isolate->bigint_processor()->ToString( | |||
| 986 | characters, &chars_written, GetDigits(bigint), radix, sign); | |||
| 987 | if (status == bigint::Status::kInterrupted) { | |||
| 988 | AllowGarbageCollection terminating_anyway; | |||
| 989 | isolate->TerminateExecution(); | |||
| 990 | return {}; | |||
| 991 | } | |||
| 992 | } | |||
| 993 | ||||
| 994 | // Right-trim any over-allocation (which can happen due to conservative | |||
| 995 | // estimates). | |||
| 996 | if (chars_written < chars_allocated) { | |||
| 997 | result->set_length(chars_written, kReleaseStore); | |||
| 998 | int string_size = SeqOneByteString::SizeFor(chars_allocated); | |||
| 999 | int needed_size = SeqOneByteString::SizeFor(chars_written); | |||
| 1000 | if (needed_size < string_size && !isolate->heap()->IsLargeObject(*result)) { | |||
| 1001 | Address new_end = result->address() + needed_size; | |||
| 1002 | isolate->heap()->CreateFillerObjectAt( | |||
| 1003 | new_end, (string_size - needed_size), ClearRecordedSlots::kNo); | |||
| 1004 | } | |||
| 1005 | } | |||
| 1006 | #if DEBUG | |||
| 1007 | // Verify that all characters have been written. | |||
| 1008 | DCHECK(result->length() == chars_written)((void) 0); | |||
| 1009 | DisallowGarbageCollection no_gc; | |||
| 1010 | uint8_t* chars = result->GetChars(no_gc); | |||
| 1011 | for (int i = 0; i < chars_written; i++) { | |||
| 1012 | DCHECK_NE(chars[i], bigint::kStringZapValue)((void) 0); | |||
| 1013 | } | |||
| 1014 | #endif | |||
| 1015 | return result; | |||
| 1016 | } | |||
| 1017 | ||||
| 1018 | MaybeHandle<BigInt> BigInt::FromNumber(Isolate* isolate, | |||
| 1019 | Handle<Object> number) { | |||
| 1020 | DCHECK(number->IsNumber())((void) 0); | |||
| 1021 | if (number->IsSmi()) { | |||
| 1022 | return MutableBigInt::NewFromInt(isolate, Smi::ToInt(*number)); | |||
| 1023 | } | |||
| 1024 | double value = HeapNumber::cast(*number).value(); | |||
| 1025 | if (!std::isfinite(value) || (DoubleToInteger(value) != value)) { | |||
| 1026 | THROW_NEW_ERROR(isolate,do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntFromNumber, number)); } while (false ) | |||
| 1027 | NewRangeError(MessageTemplate::kBigIntFromNumber, number),do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntFromNumber, number)); } while (false ) | |||
| 1028 | BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewRangeError (MessageTemplate::kBigIntFromNumber, number)); } while (false ); | |||
| 1029 | } | |||
| 1030 | return MutableBigInt::NewFromDouble(isolate, value); | |||
| 1031 | } | |||
| 1032 | ||||
| 1033 | MaybeHandle<BigInt> BigInt::FromObject(Isolate* isolate, Handle<Object> obj) { | |||
| 1034 | if (obj->IsJSReceiver()) { | |||
| 1035 | ASSIGN_RETURN_ON_EXCEPTION(do { if (!(JSReceiver::ToPrimitive(isolate, Handle<JSReceiver >::cast(obj), ToPrimitiveHint::kNumber)).ToHandle(&obj )) { ((void) 0); return MaybeHandle<BigInt>(); } } while (false) | |||
| 1036 | isolate, obj,do { if (!(JSReceiver::ToPrimitive(isolate, Handle<JSReceiver >::cast(obj), ToPrimitiveHint::kNumber)).ToHandle(&obj )) { ((void) 0); return MaybeHandle<BigInt>(); } } while (false) | |||
| 1037 | JSReceiver::ToPrimitive(isolate, Handle<JSReceiver>::cast(obj),do { if (!(JSReceiver::ToPrimitive(isolate, Handle<JSReceiver >::cast(obj), ToPrimitiveHint::kNumber)).ToHandle(&obj )) { ((void) 0); return MaybeHandle<BigInt>(); } } while (false) | |||
| 1038 | ToPrimitiveHint::kNumber),do { if (!(JSReceiver::ToPrimitive(isolate, Handle<JSReceiver >::cast(obj), ToPrimitiveHint::kNumber)).ToHandle(&obj )) { ((void) 0); return MaybeHandle<BigInt>(); } } while (false) | |||
| 1039 | BigInt)do { if (!(JSReceiver::ToPrimitive(isolate, Handle<JSReceiver >::cast(obj), ToPrimitiveHint::kNumber)).ToHandle(&obj )) { ((void) 0); return MaybeHandle<BigInt>(); } } while (false); | |||
| 1040 | } | |||
| 1041 | ||||
| 1042 | if (obj->IsBoolean()) { | |||
| 1043 | return MutableBigInt::NewFromInt(isolate, obj->BooleanValue(isolate)); | |||
| 1044 | } | |||
| 1045 | if (obj->IsBigInt()) { | |||
| 1046 | return Handle<BigInt>::cast(obj); | |||
| 1047 | } | |||
| 1048 | if (obj->IsString()) { | |||
| 1049 | Handle<BigInt> n; | |||
| 1050 | if (!StringToBigInt(isolate, Handle<String>::cast(obj)).ToHandle(&n)) { | |||
| 1051 | if (isolate->has_pending_exception()) { | |||
| 1052 | return MaybeHandle<BigInt>(); | |||
| 1053 | } else { | |||
| 1054 | Handle<String> str = Handle<String>::cast(obj); | |||
| 1055 | constexpr int kMaxRenderedLength = 1000; | |||
| 1056 | if (str->length() > kMaxRenderedLength) { | |||
| 1057 | Factory* factory = isolate->factory(); | |||
| 1058 | Handle<String> prefix = | |||
| 1059 | factory->NewProperSubString(str, 0, kMaxRenderedLength); | |||
| 1060 | Handle<SeqTwoByteString> ellipsis = | |||
| 1061 | factory->NewRawTwoByteString(1).ToHandleChecked(); | |||
| 1062 | ellipsis->SeqTwoByteStringSet(0, 0x2026); | |||
| 1063 | str = factory->NewConsString(prefix, ellipsis).ToHandleChecked(); | |||
| 1064 | } | |||
| 1065 | THROW_NEW_ERROR(isolate,do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewSyntaxError (MessageTemplate::kBigIntFromObject, str)); } while (false) | |||
| 1066 | NewSyntaxError(MessageTemplate::kBigIntFromObject, str),do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewSyntaxError (MessageTemplate::kBigIntFromObject, str)); } while (false) | |||
| 1067 | BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewSyntaxError (MessageTemplate::kBigIntFromObject, str)); } while (false); | |||
| 1068 | } | |||
| 1069 | } | |||
| 1070 | return n; | |||
| 1071 | } | |||
| 1072 | ||||
| 1073 | THROW_NEW_ERROR(do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewTypeError (MessageTemplate::kBigIntFromObject, obj)); } while (false) | |||
| 1074 | isolate, NewTypeError(MessageTemplate::kBigIntFromObject, obj), BigInt)do { auto* __isolate__ = (isolate); return __isolate__->template Throw<BigInt>(__isolate__->factory()->NewTypeError (MessageTemplate::kBigIntFromObject, obj)); } while (false); | |||
| 1075 | } | |||
| 1076 | ||||
| 1077 | Handle<Object> BigInt::ToNumber(Isolate* isolate, Handle<BigInt> x) { | |||
| 1078 | if (x->is_zero()) return Handle<Smi>(Smi::zero(), isolate); | |||
| 1079 | if (x->length() == 1 && x->digit(0) < Smi::kMaxValue) { | |||
| ||||
| 1080 | int value = static_cast<int>(x->digit(0)); | |||
| 1081 | if (x->sign()) value = -value; | |||
| 1082 | return Handle<Smi>(Smi::FromInt(value), isolate); | |||
| 1083 | } | |||
| 1084 | double result = MutableBigInt::ToDouble(x); | |||
| 1085 | return isolate->factory()->NewHeapNumber(result); | |||
| 1086 | } | |||
| 1087 | ||||
| 1088 | double MutableBigInt::ToDouble(Handle<BigIntBase> x) { | |||
| 1089 | if (x->is_zero()) return 0.0; | |||
| 1090 | int x_length = x->length(); | |||
| 1091 | digit_t x_msd = x->digit(x_length - 1); | |||
| 1092 | int msd_leading_zeros = base::bits::CountLeadingZeros(x_msd); | |||
| 1093 | int x_bitlength = x_length * kDigitBits - msd_leading_zeros; | |||
| 1094 | if (x_bitlength > 1024) return x->sign() ? -V8_INFINITYstd::numeric_limits<double>::infinity() : V8_INFINITYstd::numeric_limits<double>::infinity(); | |||
| 1095 | uint64_t exponent = x_bitlength - 1; | |||
| 1096 | // We need the most significant bit shifted to the position of a double's | |||
| 1097 | // "hidden bit". We also need to hide that MSB, so we shift it out. | |||
| 1098 | uint64_t current_digit = x_msd; | |||
| 1099 | int digit_index = x_length - 1; | |||
| 1100 | int shift = msd_leading_zeros + 1 + (64 - kDigitBits); | |||
| 1101 | DCHECK_LE(1, shift)((void) 0); | |||
| 1102 | DCHECK_LE(shift, 64)((void) 0); | |||
| 1103 | uint64_t mantissa = (shift
| |||
| ||||
| 1104 | mantissa >>= 12; | |||
| 1105 | int mantissa_bits_unset = shift - 12; | |||
| 1106 | // If not all mantissa bits are defined yet, get more digits as needed. | |||
| 1107 | if (mantissa_bits_unset >= kDigitBits && digit_index > 0) { | |||
| 1108 | digit_index--; | |||
| 1109 | current_digit = static_cast<uint64_t>(x->digit(digit_index)); | |||
| 1110 | mantissa |= (current_digit << (mantissa_bits_unset - kDigitBits)); | |||
| 1111 | mantissa_bits_unset -= kDigitBits; | |||
| 1112 | } | |||
| 1113 | if (mantissa_bits_unset > 0 && digit_index > 0) { | |||
| 1114 | DCHECK_LT(mantissa_bits_unset, kDigitBits)((void) 0); | |||
| 1115 | digit_index--; | |||
| 1116 | current_digit = static_cast<uint64_t>(x->digit(digit_index)); | |||
| 1117 | mantissa |= (current_digit >> (kDigitBits - mantissa_bits_unset)); | |||
| 1118 | mantissa_bits_unset -= kDigitBits; | |||
| 1119 | } | |||
| 1120 | // If there are unconsumed digits left, we may have to round. | |||
| 1121 | Rounding rounding = | |||
| 1122 | DecideRounding(x, mantissa_bits_unset, digit_index, current_digit); | |||
| 1123 | if (rounding == kRoundUp || (rounding == kTie && (mantissa & 1) == 1)) { | |||
| 1124 | mantissa++; | |||
| 1125 | // Incrementing the mantissa can overflow the mantissa bits. In that case | |||
| 1126 | // the new mantissa will be all zero (plus hidden bit). | |||
| 1127 | if ((mantissa >> base::Double::kPhysicalSignificandSize) != 0) { | |||
| 1128 | mantissa = 0; | |||
| 1129 | exponent++; | |||
| 1130 | // Incrementing the exponent can overflow too. | |||
| 1131 | if (exponent > 1023) { | |||
| 1132 | return x->sign() ? -V8_INFINITYstd::numeric_limits<double>::infinity() : V8_INFINITYstd::numeric_limits<double>::infinity(); | |||
| 1133 | } | |||
| 1134 | } | |||
| 1135 | } | |||
| 1136 | // Assemble the result. | |||
| 1137 | uint64_t sign_bit = x->sign() ? (static_cast<uint64_t>(1) << 63) : 0; | |||
| 1138 | exponent = (exponent + 0x3FF) << base::Double::kPhysicalSignificandSize; | |||
| 1139 | uint64_t double_bits = sign_bit | exponent | mantissa; | |||
| 1140 | return bit_cast<double>(double_bits); | |||
| 1141 | } | |||
| 1142 | ||||
| 1143 | // This is its own function to simplify control flow. The meaning of the | |||
| 1144 | // parameters is defined by {ToDouble}'s local variable usage. | |||
| 1145 | MutableBigInt::Rounding MutableBigInt::DecideRounding(Handle<BigIntBase> x, | |||
| 1146 | int mantissa_bits_unset, | |||
| 1147 | int digit_index, | |||
| 1148 | uint64_t current_digit) { | |||
| 1149 | if (mantissa_bits_unset > 0) return kRoundDown; | |||
| 1150 | int top_unconsumed_bit; | |||
| 1151 | if (mantissa_bits_unset < 0) { | |||
| 1152 | // There are unconsumed bits in {current_digit}. | |||
| 1153 | top_unconsumed_bit = -mantissa_bits_unset - 1; | |||
| 1154 | } else { | |||
| 1155 | DCHECK_EQ(mantissa_bits_unset, 0)((void) 0); | |||
| 1156 | // {current_digit} fit the mantissa exactly; look at the next digit. | |||
| 1157 | if (digit_index == 0) return kRoundDown; | |||
| 1158 | digit_index--; | |||
| 1159 | current_digit = static_cast<uint64_t>(x->digit(digit_index)); | |||
| 1160 | top_unconsumed_bit = kDigitBits - 1; | |||
| 1161 | } | |||
| 1162 | // If the most significant remaining bit is 0, round down. | |||
| 1163 | uint64_t bitmask = static_cast<uint64_t>(1) << top_unconsumed_bit; | |||
| 1164 | if ((current_digit & bitmask) == 0) { | |||
| 1165 | return kRoundDown; | |||
| 1166 | } | |||
| 1167 | // If any other remaining bit is set, round up. | |||
| 1168 | bitmask -= 1; | |||
| 1169 | if ((current_digit & bitmask) != 0) return kRoundUp; | |||
| 1170 | while (digit_index > 0) { | |||
| 1171 | digit_index--; | |||
| 1172 | if (x->digit(digit_index) != 0) return kRoundUp; | |||
| 1173 | } | |||
| 1174 | return kTie; | |||
| 1175 | } | |||
| 1176 | ||||
| 1177 | void BigInt::BigIntShortPrint(std::ostream& os) { | |||
| 1178 | if (sign()) os << "-"; | |||
| 1179 | int len = length(); | |||
| 1180 | if (len == 0) { | |||
| 1181 | os << "0"; | |||
| 1182 | return; | |||
| 1183 | } | |||
| 1184 | if (len > 1) os << "..."; | |||
| 1185 | os << digit(0); | |||
| 1186 | } | |||
| 1187 | ||||
| 1188 | // Internal helpers. | |||
| 1189 | ||||
| 1190 | // Adds 1 to the absolute value of {x} and sets the result's sign to {sign}. | |||
| 1191 | // {result_storage} is optional; if present, it will be used to store the | |||
| 1192 | // result, otherwise a new BigInt will be allocated for the result. | |||
| 1193 | // {result_storage} and {x} may refer to the same BigInt for in-place | |||
| 1194 | // modification. | |||
| 1195 | MaybeHandle<MutableBigInt> MutableBigInt::AbsoluteAddOne( | |||
| 1196 | Isolate* isolate, Handle<BigIntBase> x, bool sign, | |||
| 1197 | MutableBigInt result_storage) { | |||
| 1198 | int input_length = x->length(); | |||
| 1199 | // The addition will overflow into a new digit if all existing digits are | |||
| 1200 | // at maximum. | |||
| 1201 | bool will_overflow = true; | |||
| 1202 | for (int i = 0; i < input_length; i++) { | |||
| 1203 | if (!digit_ismax(x->digit(i))) { | |||
| 1204 | will_overflow = false; | |||
| 1205 | break; | |||
| 1206 | } | |||
| 1207 | } | |||
| 1208 | int result_length = input_length + will_overflow; | |||
| 1209 | Handle<MutableBigInt> result(result_storage, isolate); | |||
| 1210 | if (result_storage.is_null()) { | |||
| 1211 | if (!New(isolate, result_length).ToHandle(&result)) { | |||
| 1212 | return MaybeHandle<MutableBigInt>(); | |||
| 1213 | } | |||
| 1214 | } else { | |||
| 1215 | DCHECK(result->length() == result_length)((void) 0); | |||
| 1216 | } | |||
| 1217 | if (input_length == 0) { | |||
| 1218 | result->set_digit(0, 1); | |||
| 1219 | } else if (input_length == 1 && !will_overflow) { | |||
| 1220 | result->set_digit(0, x->digit(0) + 1); | |||
| 1221 | } else { | |||
| 1222 | bigint::AddOne(GetRWDigits(result), GetDigits(x)); | |||
| 1223 | } | |||
| 1224 | result->set_sign(sign); | |||
| 1225 | return result; | |||
| 1226 | } | |||
| 1227 | ||||
| 1228 | // Subtracts 1 from the absolute value of {x}. {x} must not be zero. | |||
| 1229 | Handle<MutableBigInt> MutableBigInt::AbsoluteSubOne(Isolate* isolate, | |||
| 1230 | Handle<BigIntBase> x) { | |||
| 1231 | DCHECK(!x->is_zero())((void) 0); | |||
| 1232 | int length = x->length(); | |||
| 1233 | Handle<MutableBigInt> result = New(isolate, length).ToHandleChecked(); | |||
| 1234 | if (length == 1) { | |||
| 1235 | result->set_digit(0, x->digit(0) - 1); | |||
| 1236 | } else { | |||
| 1237 | bigint::SubtractOne(GetRWDigits(result), GetDigits(x)); | |||
| 1238 | } | |||
| 1239 | return result; | |||
| 1240 | } | |||
| 1241 | ||||
| 1242 | MaybeHandle<BigInt> MutableBigInt::LeftShiftByAbsolute(Isolate* isolate, | |||
| 1243 | Handle<BigIntBase> x, | |||
| 1244 | Handle<BigIntBase> y) { | |||
| 1245 | Maybe<digit_t> maybe_shift = ToShiftAmount(y); | |||
| 1246 | if (maybe_shift.IsNothing()) { | |||
| 1247 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 1248 | } | |||
| 1249 | digit_t shift = maybe_shift.FromJust(); | |||
| 1250 | const int result_length = bigint::LeftShift_ResultLength( | |||
| 1251 | x->length(), x->digit(x->length() - 1), shift); | |||
| 1252 | if (result_length > kMaxLength) { | |||
| 1253 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 1254 | } | |||
| 1255 | Handle<MutableBigInt> result; | |||
| 1256 | if (!New(isolate, result_length).ToHandle(&result)) { | |||
| 1257 | return MaybeHandle<BigInt>(); | |||
| 1258 | } | |||
| 1259 | bigint::LeftShift(GetRWDigits(result), GetDigits(x), shift); | |||
| 1260 | result->set_sign(x->sign()); | |||
| 1261 | return MakeImmutable(result); | |||
| 1262 | } | |||
| 1263 | ||||
| 1264 | Handle<BigInt> MutableBigInt::RightShiftByAbsolute(Isolate* isolate, | |||
| 1265 | Handle<BigIntBase> x, | |||
| 1266 | Handle<BigIntBase> y) { | |||
| 1267 | const bool sign = x->sign(); | |||
| 1268 | Maybe<digit_t> maybe_shift = ToShiftAmount(y); | |||
| 1269 | if (maybe_shift.IsNothing()) { | |||
| 1270 | return RightShiftByMaximum(isolate, sign); | |||
| 1271 | } | |||
| 1272 | const digit_t shift = maybe_shift.FromJust(); | |||
| 1273 | bigint::RightShiftState state; | |||
| 1274 | const int result_length = | |||
| 1275 | bigint::RightShift_ResultLength(GetDigits(x), sign, shift, &state); | |||
| 1276 | DCHECK_LE(result_length, x->length())((void) 0); | |||
| 1277 | if (result_length <= 0) { | |||
| 1278 | return RightShiftByMaximum(isolate, sign); | |||
| 1279 | } | |||
| 1280 | Handle<MutableBigInt> result = New(isolate, result_length).ToHandleChecked(); | |||
| 1281 | bigint::RightShift(GetRWDigits(result), GetDigits(x), shift, state); | |||
| 1282 | if (sign) result->set_sign(true); | |||
| 1283 | return MakeImmutable(result); | |||
| 1284 | } | |||
| 1285 | ||||
| 1286 | Handle<BigInt> MutableBigInt::RightShiftByMaximum(Isolate* isolate, bool sign) { | |||
| 1287 | if (sign) { | |||
| 1288 | // TODO(jkummerow): Consider caching a canonical -1n BigInt. | |||
| 1289 | return NewFromInt(isolate, -1); | |||
| 1290 | } else { | |||
| 1291 | return Zero(isolate); | |||
| 1292 | } | |||
| 1293 | } | |||
| 1294 | ||||
| 1295 | // Returns the value of {x} if it is less than the maximum bit length of | |||
| 1296 | // a BigInt, or Nothing otherwise. | |||
| 1297 | Maybe<BigInt::digit_t> MutableBigInt::ToShiftAmount(Handle<BigIntBase> x) { | |||
| 1298 | if (x->length() > 1) return Nothing<digit_t>(); | |||
| 1299 | digit_t value = x->digit(0); | |||
| 1300 | STATIC_ASSERT(kMaxLengthBits < std::numeric_limits<digit_t>::max())static_assert(kMaxLengthBits < std::numeric_limits<digit_t >::max(), "kMaxLengthBits < std::numeric_limits<digit_t>::max()" ); | |||
| 1301 | if (value > kMaxLengthBits) return Nothing<digit_t>(); | |||
| 1302 | return Just(value); | |||
| 1303 | } | |||
| 1304 | ||||
| 1305 | void Terminate(Isolate* isolate) { isolate->TerminateExecution(); } | |||
| 1306 | // {LocalIsolate} doesn't support interruption or termination. | |||
| 1307 | void Terminate(LocalIsolate* isolate) { UNREACHABLE()V8_Fatal("unreachable code"); } | |||
| 1308 | ||||
| 1309 | template <typename IsolateT> | |||
| 1310 | MaybeHandle<BigInt> BigInt::Allocate(IsolateT* isolate, | |||
| 1311 | bigint::FromStringAccumulator* accumulator, | |||
| 1312 | bool negative, AllocationType allocation) { | |||
| 1313 | int digits = accumulator->ResultLength(); | |||
| 1314 | DCHECK_LE(digits, kMaxLength)((void) 0); | |||
| 1315 | Handle<MutableBigInt> result = | |||
| 1316 | MutableBigInt::New(isolate, digits, allocation).ToHandleChecked(); | |||
| 1317 | bigint::Status status = | |||
| 1318 | isolate->bigint_processor()->FromString(GetRWDigits(result), accumulator); | |||
| 1319 | if (status == bigint::Status::kInterrupted) { | |||
| 1320 | Terminate(isolate); | |||
| 1321 | return {}; | |||
| 1322 | } | |||
| 1323 | if (digits > 0) result->set_sign(negative); | |||
| 1324 | return MutableBigInt::MakeImmutable(result); | |||
| 1325 | } | |||
| 1326 | template MaybeHandle<BigInt> BigInt::Allocate(Isolate*, | |||
| 1327 | bigint::FromStringAccumulator*, | |||
| 1328 | bool, AllocationType); | |||
| 1329 | template MaybeHandle<BigInt> BigInt::Allocate(LocalIsolate*, | |||
| 1330 | bigint::FromStringAccumulator*, | |||
| 1331 | bool, AllocationType); | |||
| 1332 | ||||
| 1333 | // The serialization format MUST NOT CHANGE without updating the format | |||
| 1334 | // version in value-serializer.cc! | |||
| 1335 | uint32_t BigInt::GetBitfieldForSerialization() const { | |||
| 1336 | // In order to make the serialization format the same on 32/64 bit builds, | |||
| 1337 | // we convert the length-in-digits to length-in-bytes for serialization. | |||
| 1338 | // Being able to do this depends on having enough LengthBits: | |||
| 1339 | STATIC_ASSERT(kMaxLength * kDigitSize <= LengthBits::kMax)static_assert(kMaxLength * kDigitSize <= LengthBits::kMax, "kMaxLength * kDigitSize <= LengthBits::kMax"); | |||
| 1340 | int bytelength = length() * kDigitSize; | |||
| 1341 | return SignBits::encode(sign()) | LengthBits::encode(bytelength); | |||
| 1342 | } | |||
| 1343 | ||||
| 1344 | int BigInt::DigitsByteLengthForBitfield(uint32_t bitfield) { | |||
| 1345 | return LengthBits::decode(bitfield); | |||
| 1346 | } | |||
| 1347 | ||||
| 1348 | // The serialization format MUST NOT CHANGE without updating the format | |||
| 1349 | // version in value-serializer.cc! | |||
| 1350 | void BigInt::SerializeDigits(uint8_t* storage) { | |||
| 1351 | void* digits = | |||
| 1352 | reinterpret_cast<void*>(ptr() + kDigitsOffset - kHeapObjectTag); | |||
| 1353 | #if defined(V8_TARGET_LITTLE_ENDIAN1) | |||
| 1354 | int bytelength = length() * kDigitSize; | |||
| 1355 | memcpy(storage, digits, bytelength); | |||
| 1356 | #elif defined(V8_TARGET_BIG_ENDIAN) | |||
| 1357 | digit_t* digit_storage = reinterpret_cast<digit_t*>(storage); | |||
| 1358 | const digit_t* digit = reinterpret_cast<const digit_t*>(digits); | |||
| 1359 | for (int i = 0; i < length(); i++) { | |||
| 1360 | *digit_storage = ByteReverse(*digit); | |||
| 1361 | digit_storage++; | |||
| 1362 | digit++; | |||
| 1363 | } | |||
| 1364 | #endif // V8_TARGET_BIG_ENDIAN | |||
| 1365 | } | |||
| 1366 | ||||
| 1367 | // The serialization format MUST NOT CHANGE without updating the format | |||
| 1368 | // version in value-serializer.cc! | |||
| 1369 | MaybeHandle<BigInt> BigInt::FromSerializedDigits( | |||
| 1370 | Isolate* isolate, uint32_t bitfield, | |||
| 1371 | base::Vector<const uint8_t> digits_storage) { | |||
| 1372 | int bytelength = LengthBits::decode(bitfield); | |||
| 1373 | DCHECK(digits_storage.length() == bytelength)((void) 0); | |||
| 1374 | bool sign = SignBits::decode(bitfield); | |||
| 1375 | int length = (bytelength + kDigitSize - 1) / kDigitSize; // Round up. | |||
| 1376 | Handle<MutableBigInt> result = | |||
| 1377 | MutableBigInt::Cast(isolate->factory()->NewBigInt(length)); | |||
| 1378 | result->initialize_bitfield(sign, length); | |||
| 1379 | void* digits = | |||
| 1380 | reinterpret_cast<void*>(result->ptr() + kDigitsOffset - kHeapObjectTag); | |||
| 1381 | #if defined(V8_TARGET_LITTLE_ENDIAN1) | |||
| 1382 | memcpy(digits, digits_storage.begin(), bytelength); | |||
| 1383 | void* padding_start = | |||
| 1384 | reinterpret_cast<void*>(reinterpret_cast<Address>(digits) + bytelength); | |||
| 1385 | memset(padding_start, 0, length * kDigitSize - bytelength); | |||
| 1386 | #elif defined(V8_TARGET_BIG_ENDIAN) | |||
| 1387 | digit_t* digit = reinterpret_cast<digit_t*>(digits); | |||
| 1388 | const digit_t* digit_storage = | |||
| 1389 | reinterpret_cast<const digit_t*>(digits_storage.begin()); | |||
| 1390 | for (int i = 0; i < bytelength / kDigitSize; i++) { | |||
| 1391 | *digit = ByteReverse(*digit_storage); | |||
| 1392 | digit_storage++; | |||
| 1393 | digit++; | |||
| 1394 | } | |||
| 1395 | if (bytelength % kDigitSize) { | |||
| 1396 | *digit = 0; | |||
| 1397 | byte* digit_byte = reinterpret_cast<byte*>(digit); | |||
| 1398 | digit_byte += sizeof(*digit) - 1; | |||
| 1399 | const byte* digit_storage_byte = | |||
| 1400 | reinterpret_cast<const byte*>(digit_storage); | |||
| 1401 | for (int i = 0; i < bytelength % kDigitSize; i++) { | |||
| 1402 | *digit_byte = *digit_storage_byte; | |||
| 1403 | digit_byte--; | |||
| 1404 | digit_storage_byte++; | |||
| 1405 | } | |||
| 1406 | } | |||
| 1407 | #endif // V8_TARGET_BIG_ENDIAN | |||
| 1408 | return MutableBigInt::MakeImmutable(result); | |||
| 1409 | } | |||
| 1410 | ||||
| 1411 | Handle<BigInt> BigInt::AsIntN(Isolate* isolate, uint64_t n, Handle<BigInt> x) { | |||
| 1412 | if (x->is_zero() || n > kMaxLengthBits) return x; | |||
| 1413 | if (n == 0) return MutableBigInt::Zero(isolate); | |||
| 1414 | int needed_length = | |||
| 1415 | bigint::AsIntNResultLength(GetDigits(x), x->sign(), static_cast<int>(n)); | |||
| 1416 | if (needed_length == -1) return x; | |||
| 1417 | Handle<MutableBigInt> result = | |||
| 1418 | MutableBigInt::New(isolate, needed_length).ToHandleChecked(); | |||
| 1419 | bool negative = bigint::AsIntN(GetRWDigits(result), GetDigits(x), x->sign(), | |||
| 1420 | static_cast<int>(n)); | |||
| 1421 | result->set_sign(negative); | |||
| 1422 | return MutableBigInt::MakeImmutable(result); | |||
| 1423 | } | |||
| 1424 | ||||
| 1425 | MaybeHandle<BigInt> BigInt::AsUintN(Isolate* isolate, uint64_t n, | |||
| 1426 | Handle<BigInt> x) { | |||
| 1427 | if (x->is_zero()) return x; | |||
| 1428 | if (n == 0) return MutableBigInt::Zero(isolate); | |||
| 1429 | Handle<MutableBigInt> result; | |||
| 1430 | if (x->sign()) { | |||
| 1431 | if (n > kMaxLengthBits) { | |||
| 1432 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 1433 | } | |||
| 1434 | int result_length = bigint::AsUintN_Neg_ResultLength(static_cast<int>(n)); | |||
| 1435 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 1436 | bigint::AsUintN_Neg(GetRWDigits(result), GetDigits(x), static_cast<int>(n)); | |||
| 1437 | } else { | |||
| 1438 | if (n >= kMaxLengthBits) return x; | |||
| 1439 | int result_length = | |||
| 1440 | bigint::AsUintN_Pos_ResultLength(GetDigits(x), static_cast<int>(n)); | |||
| 1441 | if (result_length < 0) return x; | |||
| 1442 | result = MutableBigInt::New(isolate, result_length).ToHandleChecked(); | |||
| 1443 | bigint::AsUintN_Pos(GetRWDigits(result), GetDigits(x), static_cast<int>(n)); | |||
| 1444 | } | |||
| 1445 | DCHECK(!result->sign())((void) 0); | |||
| 1446 | return MutableBigInt::MakeImmutable(result); | |||
| 1447 | } | |||
| 1448 | ||||
| 1449 | Handle<BigInt> BigInt::FromInt64(Isolate* isolate, int64_t n) { | |||
| 1450 | if (n == 0) return MutableBigInt::Zero(isolate); | |||
| 1451 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1452 | int length = 64 / kDigitBits; | |||
| 1453 | Handle<MutableBigInt> result = | |||
| 1454 | MutableBigInt::Cast(isolate->factory()->NewBigInt(length)); | |||
| 1455 | bool sign = n < 0; | |||
| 1456 | result->initialize_bitfield(sign, length); | |||
| 1457 | uint64_t absolute; | |||
| 1458 | if (!sign) { | |||
| 1459 | absolute = static_cast<uint64_t>(n); | |||
| 1460 | } else { | |||
| 1461 | if (n == std::numeric_limits<int64_t>::min()) { | |||
| 1462 | absolute = static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1; | |||
| 1463 | } else { | |||
| 1464 | absolute = static_cast<uint64_t>(-n); | |||
| 1465 | } | |||
| 1466 | } | |||
| 1467 | result->set_64_bits(absolute); | |||
| 1468 | return MutableBigInt::MakeImmutable(result); | |||
| 1469 | } | |||
| 1470 | ||||
| 1471 | Handle<BigInt> BigInt::FromUint64(Isolate* isolate, uint64_t n) { | |||
| 1472 | if (n == 0) return MutableBigInt::Zero(isolate); | |||
| 1473 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1474 | int length = 64 / kDigitBits; | |||
| 1475 | Handle<MutableBigInt> result = | |||
| 1476 | MutableBigInt::Cast(isolate->factory()->NewBigInt(length)); | |||
| 1477 | result->initialize_bitfield(false, length); | |||
| 1478 | result->set_64_bits(n); | |||
| 1479 | return MutableBigInt::MakeImmutable(result); | |||
| 1480 | } | |||
| 1481 | ||||
| 1482 | MaybeHandle<BigInt> BigInt::FromWords64(Isolate* isolate, int sign_bit, | |||
| 1483 | int words64_count, | |||
| 1484 | const uint64_t* words) { | |||
| 1485 | if (words64_count < 0 || words64_count > kMaxLength / (64 / kDigitBits)) { | |||
| 1486 | return ThrowBigIntTooBig<BigInt>(isolate); | |||
| 1487 | } | |||
| 1488 | if (words64_count == 0) return MutableBigInt::Zero(isolate); | |||
| 1489 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1490 | int length = (64 / kDigitBits) * words64_count; | |||
| 1491 | DCHECK_GT(length, 0)((void) 0); | |||
| 1492 | if (kDigitBits == 32 && words[words64_count - 1] <= (1ULL << 32)) length--; | |||
| 1493 | ||||
| 1494 | Handle<MutableBigInt> result; | |||
| 1495 | if (!MutableBigInt::New(isolate, length).ToHandle(&result)) { | |||
| 1496 | return MaybeHandle<BigInt>(); | |||
| 1497 | } | |||
| 1498 | ||||
| 1499 | result->set_sign(sign_bit); | |||
| 1500 | if (kDigitBits == 64) { | |||
| 1501 | for (int i = 0; i < length; ++i) { | |||
| 1502 | result->set_digit(i, static_cast<digit_t>(words[i])); | |||
| 1503 | } | |||
| 1504 | } else { | |||
| 1505 | for (int i = 0; i < length; i += 2) { | |||
| 1506 | digit_t lo = static_cast<digit_t>(words[i / 2]); | |||
| 1507 | digit_t hi = static_cast<digit_t>(words[i / 2] >> 32); | |||
| 1508 | result->set_digit(i, lo); | |||
| 1509 | if (i + 1 < length) result->set_digit(i + 1, hi); | |||
| 1510 | } | |||
| 1511 | } | |||
| 1512 | ||||
| 1513 | return MutableBigInt::MakeImmutable(result); | |||
| 1514 | } | |||
| 1515 | ||||
| 1516 | int BigInt::Words64Count() { | |||
| 1517 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1518 | return length() / (64 / kDigitBits) + | |||
| 1519 | (kDigitBits == 32 && length() % 2 == 1 ? 1 : 0); | |||
| 1520 | } | |||
| 1521 | ||||
| 1522 | void BigInt::ToWordsArray64(int* sign_bit, int* words64_count, | |||
| 1523 | uint64_t* words) { | |||
| 1524 | DCHECK_NE(sign_bit, nullptr)((void) 0); | |||
| 1525 | DCHECK_NE(words64_count, nullptr)((void) 0); | |||
| 1526 | *sign_bit = sign(); | |||
| 1527 | int available_words = *words64_count; | |||
| 1528 | *words64_count = Words64Count(); | |||
| 1529 | if (available_words == 0) return; | |||
| 1530 | DCHECK_NE(words, nullptr)((void) 0); | |||
| 1531 | ||||
| 1532 | int len = length(); | |||
| 1533 | if (kDigitBits == 64) { | |||
| 1534 | for (int i = 0; i < len && i < available_words; ++i) words[i] = digit(i); | |||
| 1535 | } else { | |||
| 1536 | for (int i = 0; i < len && available_words > 0; i += 2) { | |||
| 1537 | uint64_t lo = digit(i); | |||
| 1538 | uint64_t hi = (i + 1) < len ? digit(i + 1) : 0; | |||
| 1539 | words[i / 2] = lo | (hi << 32); | |||
| 1540 | available_words--; | |||
| 1541 | } | |||
| 1542 | } | |||
| 1543 | } | |||
| 1544 | ||||
| 1545 | uint64_t MutableBigInt::GetRawBits(BigIntBase x, bool* lossless) { | |||
| 1546 | if (lossless != nullptr) *lossless = true; | |||
| 1547 | if (x.is_zero()) return 0; | |||
| 1548 | int len = x.length(); | |||
| 1549 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1550 | if (lossless != nullptr && len > 64 / kDigitBits) *lossless = false; | |||
| 1551 | uint64_t raw = static_cast<uint64_t>(x.digit(0)); | |||
| 1552 | if (kDigitBits == 32 && len > 1) { | |||
| 1553 | raw |= static_cast<uint64_t>(x.digit(1)) << 32; | |||
| 1554 | } | |||
| 1555 | // Simulate two's complement. MSVC dislikes "-raw". | |||
| 1556 | return x.sign() ? ((~raw) + 1u) : raw; | |||
| 1557 | } | |||
| 1558 | ||||
| 1559 | int64_t BigInt::AsInt64(bool* lossless) { | |||
| 1560 | uint64_t raw = MutableBigInt::GetRawBits(*this, lossless); | |||
| 1561 | int64_t result = static_cast<int64_t>(raw); | |||
| 1562 | if (lossless != nullptr && (result < 0) != sign()) *lossless = false; | |||
| 1563 | return result; | |||
| 1564 | } | |||
| 1565 | ||||
| 1566 | uint64_t BigInt::AsUint64(bool* lossless) { | |||
| 1567 | uint64_t result = MutableBigInt::GetRawBits(*this, lossless); | |||
| 1568 | if (lossless != nullptr && sign()) *lossless = false; | |||
| 1569 | return result; | |||
| 1570 | } | |||
| 1571 | ||||
| 1572 | void MutableBigInt::set_64_bits(uint64_t bits) { | |||
| 1573 | STATIC_ASSERT(kDigitBits == 64 || kDigitBits == 32)static_assert(kDigitBits == 64 || kDigitBits == 32, "kDigitBits == 64 || kDigitBits == 32" ); | |||
| 1574 | if (kDigitBits == 64) { | |||
| 1575 | set_digit(0, static_cast<digit_t>(bits)); | |||
| 1576 | } else { | |||
| 1577 | set_digit(0, static_cast<digit_t>(bits & 0xFFFFFFFFu)); | |||
| 1578 | set_digit(1, static_cast<digit_t>(bits >> 32)); | |||
| 1579 | } | |||
| 1580 | } | |||
| 1581 | ||||
| 1582 | #ifdef OBJECT_PRINT1 | |||
| 1583 | void BigIntBase::BigIntBasePrint(std::ostream& os) { | |||
| 1584 | DisallowGarbageCollection no_gc; | |||
| 1585 | PrintHeader(os, "BigInt"); | |||
| 1586 | int len = length(); | |||
| 1587 | os << "\n- length: " << len; | |||
| 1588 | os << "\n- sign: " << sign(); | |||
| 1589 | if (len > 0) { | |||
| 1590 | os << "\n- digits:"; | |||
| 1591 | for (int i = 0; i < len; i++) { | |||
| 1592 | os << "\n 0x" << std::hex << digit(i); | |||
| 1593 | } | |||
| 1594 | } | |||
| 1595 | os << std::dec << "\n"; | |||
| 1596 | } | |||
| 1597 | #endif // OBJECT_PRINT | |||
| 1598 | ||||
| 1599 | void MutableBigInt_AbsoluteAddAndCanonicalize(Address result_addr, | |||
| 1600 | Address x_addr, Address y_addr) { | |||
| 1601 | BigInt x = BigInt::cast(Object(x_addr)); | |||
| 1602 | BigInt y = BigInt::cast(Object(y_addr)); | |||
| 1603 | MutableBigInt result = MutableBigInt::cast(Object(result_addr)); | |||
| 1604 | ||||
| 1605 | bigint::Add(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 1606 | MutableBigInt::Canonicalize(result); | |||
| 1607 | } | |||
| 1608 | ||||
| 1609 | int32_t MutableBigInt_AbsoluteCompare(Address x_addr, Address y_addr) { | |||
| 1610 | BigInt x = BigInt::cast(Object(x_addr)); | |||
| 1611 | BigInt y = BigInt::cast(Object(y_addr)); | |||
| 1612 | ||||
| 1613 | return bigint::Compare(GetDigits(x), GetDigits(y)); | |||
| 1614 | } | |||
| 1615 | ||||
| 1616 | void MutableBigInt_AbsoluteSubAndCanonicalize(Address result_addr, | |||
| 1617 | Address x_addr, Address y_addr) { | |||
| 1618 | BigInt x = BigInt::cast(Object(x_addr)); | |||
| 1619 | BigInt y = BigInt::cast(Object(y_addr)); | |||
| 1620 | MutableBigInt result = MutableBigInt::cast(Object(result_addr)); | |||
| 1621 | ||||
| 1622 | bigint::Subtract(GetRWDigits(result), GetDigits(x), GetDigits(y)); | |||
| 1623 | MutableBigInt::Canonicalize(result); | |||
| 1624 | } | |||
| 1625 | ||||
| 1626 | } // namespace internal | |||
| 1627 | } // namespace v8 |