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