BigIntType.cpp (125738B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * Portions of this code taken from WebKit, whose copyright is as follows: 9 * 10 * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com> 11 * Copyright (C) 2017-2018 Apple Inc. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 30 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * Portions of this code taken from V8, whose copyright notice is as follows: 35 * 36 * Copyright 2017 the V8 project authors. All rights reserved. 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions are 39 * met: 40 * * Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * * Redistributions in binary form must reproduce the above 43 * copyright notice, this list of conditions and the following 44 * disclaimer in the documentation and/or other materials provided 45 * with the distribution. 46 * * Neither the name of Google Inc. nor the names of its 47 * contributors may be used to endorse or promote products derived 48 * from this software without specific prior written permission. 49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 52 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 53 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 55 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 59 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * 61 * Portions of this code taken from Dart, whose copyright notice is as follows: 62 * 63 * Copyright (c) 2014 the Dart project authors. Please see the AUTHORS file 64 * [1] for details. All rights reserved. Use of this source code is governed by 65 * a BSD-style license that can be found in the LICENSE file [2]. 66 * 67 * [1] https://github.com/dart-lang/sdk/blob/master/AUTHORS 68 * [2] https://github.com/dart-lang/sdk/blob/master/LICENSE 69 * 70 * Portions of this code taken from Go, whose copyright notice is as follows: 71 * 72 * Copyright 2009 The Go Authors. All rights reserved. 73 * Use of this source code is governed by a BSD-style 74 * license that can be found in the LICENSE file [3]. 75 * 76 * [3] https://golang.org/LICENSE 77 */ 78 79 #include "vm/BigIntType.h" 80 81 #include "mozilla/Casting.h" 82 #include "mozilla/CheckedArithmetic.h" 83 #include "mozilla/CheckedInt.h" 84 #include "mozilla/FloatingPoint.h" 85 #include "mozilla/HashFunctions.h" 86 #include "mozilla/MathAlgorithms.h" 87 #include "mozilla/Maybe.h" 88 #include "mozilla/MemoryChecking.h" 89 #include "mozilla/Range.h" 90 #include "mozilla/RangedPtr.h" 91 #include "mozilla/Span.h" // mozilla::Span 92 #include "mozilla/TextUtils.h" 93 #include "mozilla/Try.h" 94 #include "mozilla/WrappingOperations.h" 95 96 #include <charconv> 97 #include <functional> 98 #include <limits> 99 #include <memory> 100 #include <type_traits> // std::is_same_v 101 102 #include "jsnum.h" 103 104 #include "gc/GCEnum.h" 105 #include "js/BigInt.h" 106 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_* 107 #include "js/Printer.h" // js::GenericPrinter 108 #include "js/StableStringChars.h" 109 #include "js/Utility.h" 110 #include "util/DifferentialTesting.h" 111 #include "vm/JSONPrinter.h" // js::JSONPrinter 112 #include "vm/StaticStrings.h" 113 114 #include "gc/BufferAllocator-inl.h" 115 #include "gc/GCContext-inl.h" 116 #include "gc/Nursery-inl.h" 117 #include "vm/JSContext-inl.h" 118 #include "vm/StringType-inl.h" 119 120 using namespace js; 121 122 using JS::AutoStableStringChars; 123 using mozilla::Abs; 124 using mozilla::AssertedCast; 125 using mozilla::Maybe; 126 using mozilla::NegativeInfinity; 127 using mozilla::Nothing; 128 using mozilla::PositiveInfinity; 129 using mozilla::Range; 130 using mozilla::RangedPtr; 131 using mozilla::Some; 132 using mozilla::WrapToSigned; 133 134 static inline unsigned DigitLeadingZeroes(BigInt::Digit x) { 135 return sizeof(x) == 4 ? mozilla::CountLeadingZeroes32(x) 136 : mozilla::CountLeadingZeroes64(x); 137 } 138 139 #ifdef DEBUG 140 static bool HasLeadingZeroes(const BigInt* bi) { 141 return bi->digitLength() > 0 && bi->digit(bi->digitLength() - 1) == 0; 142 } 143 #endif 144 145 BigInt* BigInt::createUninitialized(JSContext* cx, size_t digitLength, 146 bool isNegative, gc::Heap heap) { 147 if (digitLength > MaxDigitLength) { 148 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 149 return nullptr; 150 } 151 152 BigInt* x = cx->newCell<BigInt>(heap); 153 if (!x) { 154 return nullptr; 155 } 156 157 x->setLengthAndFlags(digitLength, isNegative ? SignBit : 0); 158 159 MOZ_ASSERT(x->digitLength() == digitLength); 160 MOZ_ASSERT(x->isNegative() == isNegative); 161 162 if (digitLength > InlineDigitsLength) { 163 x->heapDigits_ = js::AllocateCellBuffer<Digit>(cx, x, digitLength); 164 if (!x->heapDigits_) { 165 // |x| is partially initialized, expose it as a BigInt using inline digits 166 // to the GC. 167 x->setLengthAndFlags(0, 0); 168 return nullptr; 169 } 170 } 171 172 return x; 173 } 174 175 void BigInt::initializeDigitsToZero() { 176 auto digs = digits(); 177 std::uninitialized_fill_n(digs.begin(), digs.Length(), 0); 178 } 179 180 js::HashNumber BigInt::hash() const { 181 js::HashNumber h = 182 mozilla::HashBytes(digits().data(), digitLength() * sizeof(Digit)); 183 return mozilla::AddToHash(h, isNegative()); 184 } 185 186 size_t BigInt::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { 187 return hasInlineDigits() ? 0 : gc::GetAllocSize(zone(), heapDigits_); 188 } 189 190 size_t BigInt::sizeOfExcludingThisInNursery( 191 mozilla::MallocSizeOf mallocSizeOf) const { 192 MOZ_ASSERT(!isTenured()); 193 194 if (hasInlineDigits()) { 195 return 0; 196 } 197 198 const Nursery& nursery = runtimeFromMainThread()->gc.nursery(); 199 if (nursery.isInside(heapDigits_)) { 200 // Buffer allocations are aligned to the size of JS::Value. 201 return RoundUp(digitLength() * sizeof(Digit), sizeof(Value)); 202 } 203 204 return gc::GetAllocSize(zone(), heapDigits_); 205 } 206 207 BigInt* BigInt::zero(JSContext* cx, gc::Heap heap) { 208 return createUninitialized(cx, 0, false, heap); 209 } 210 211 BigInt* BigInt::createFromDigit(JSContext* cx, Digit d, bool isNegative, 212 gc::Heap heap) { 213 MOZ_ASSERT(d != 0); 214 BigInt* res = createUninitialized(cx, 1, isNegative, heap); 215 if (!res) { 216 return nullptr; 217 } 218 res->setDigit(0, d); 219 return res; 220 } 221 222 BigInt* BigInt::one(JSContext* cx) { return createFromDigit(cx, 1, false); } 223 224 BigInt* BigInt::negativeOne(JSContext* cx) { 225 return createFromDigit(cx, 1, true); 226 } 227 228 BigInt* BigInt::createFromNonZeroRawUint64(JSContext* cx, uint64_t n, 229 bool isNegative) { 230 MOZ_ASSERT(n != 0); 231 232 size_t resultLength = 1; 233 if (DigitBits == 32 && (n >> 32) != 0) { 234 resultLength = 2; 235 } 236 237 BigInt* result = createUninitialized(cx, resultLength, isNegative); 238 if (!result) { 239 return nullptr; 240 } 241 result->setDigit(0, n); 242 if (DigitBits == 32 && resultLength > 1) { 243 result->setDigit(1, n >> 32); 244 } 245 246 MOZ_ASSERT(!HasLeadingZeroes(result)); 247 return result; 248 } 249 250 BigInt* BigInt::neg(JSContext* cx, HandleBigInt x) { 251 if (x->isZero()) { 252 return x; 253 } 254 255 BigInt* result = copy(cx, x); 256 if (!result) { 257 return nullptr; 258 } 259 result->toggleHeaderFlagBit(SignBit); 260 return result; 261 } 262 263 #if !defined(JS_64BIT) 264 # define HAVE_TWO_DIGIT 1 265 using TwoDigit = uint64_t; 266 #elif defined(__SIZEOF_INT128__) 267 # define HAVE_TWO_DIGIT 1 268 using TwoDigit = __uint128_t; 269 #endif 270 271 inline BigInt::Digit BigInt::digitMul(Digit a, Digit b, Digit* high) { 272 #if defined(HAVE_TWO_DIGIT) 273 TwoDigit result = static_cast<TwoDigit>(a) * static_cast<TwoDigit>(b); 274 *high = result >> DigitBits; 275 276 return static_cast<Digit>(result); 277 #else 278 // Multiply in half-pointer-sized chunks. 279 // For inputs [AH AL]*[BH BL], the result is: 280 // 281 // [AL*BL] // rLow 282 // + [AL*BH] // rMid1 283 // + [AH*BL] // rMid2 284 // + [AH*BH] // rHigh 285 // = [R4 R3 R2 R1] // high = [R4 R3], low = [R2 R1] 286 // 287 // Where of course we must be careful with carries between the columns. 288 Digit aLow = a & HalfDigitMask; 289 Digit aHigh = a >> HalfDigitBits; 290 Digit bLow = b & HalfDigitMask; 291 Digit bHigh = b >> HalfDigitBits; 292 293 Digit rLow = aLow * bLow; 294 Digit rMid1 = aLow * bHigh; 295 Digit rMid2 = aHigh * bLow; 296 Digit rHigh = aHigh * bHigh; 297 298 Digit carry = 0; 299 Digit low = digitAdd(rLow, rMid1 << HalfDigitBits, &carry); 300 low = digitAdd(low, rMid2 << HalfDigitBits, &carry); 301 302 *high = (rMid1 >> HalfDigitBits) + (rMid2 >> HalfDigitBits) + rHigh + carry; 303 304 return low; 305 #endif 306 } 307 308 BigInt::Digit BigInt::digitDiv(Digit high, Digit low, Digit divisor, 309 Digit* remainder) { 310 MOZ_ASSERT(high < divisor, "division must not overflow"); 311 #if defined(__x86_64__) 312 Digit quotient; 313 Digit rem; 314 __asm__("divq %[divisor]" 315 // Outputs: `quotient` will be in rax, `rem` in rdx. 316 : "=a"(quotient), "=d"(rem) 317 // Inputs: put `high` into rdx, `low` into rax, and `divisor` into 318 // any register or stack slot. 319 : "d"(high), "a"(low), [divisor] "rm"(divisor)); 320 *remainder = rem; 321 return quotient; 322 #elif defined(__i386__) 323 Digit quotient; 324 Digit rem; 325 __asm__("divl %[divisor]" 326 // Outputs: `quotient` will be in eax, `rem` in edx. 327 : "=a"(quotient), "=d"(rem) 328 // Inputs: put `high` into edx, `low` into eax, and `divisor` into 329 // any register or stack slot. 330 : "d"(high), "a"(low), [divisor] "rm"(divisor)); 331 *remainder = rem; 332 return quotient; 333 #else 334 static constexpr Digit HalfDigitBase = 1ull << HalfDigitBits; 335 // Adapted from Warren, Hacker's Delight, p. 152. 336 unsigned s = DigitLeadingZeroes(divisor); 337 // If `s` is DigitBits here, it causes an undefined behavior. 338 // But `s` is never DigitBits since `divisor` is never zero here. 339 MOZ_ASSERT(s != DigitBits); 340 divisor <<= s; 341 342 Digit vn1 = divisor >> HalfDigitBits; 343 Digit vn0 = divisor & HalfDigitMask; 344 345 // `sZeroMask` which is 0 if s == 0 and all 1-bits otherwise. 346 // 347 // `s` can be 0. If `s` is 0, performing "low >> (DigitBits - s)" must not 348 // be done since it causes an undefined behavior since `>> DigitBits` is 349 // undefined in C++. Quoted from C++ spec, "The type of the result is that of 350 // the promoted left operand. 351 // 352 // The behavior is undefined if the right operand is negative, or greater 353 // than or equal to the length in bits of the promoted left operand". We 354 // mask the right operand of the shift by `shiftMask` (`DigitBits - 1`), 355 // which makes `DigitBits - 0` zero. 356 // 357 // This shifting produces a value which covers 0 < `s` <= (DigitBits - 1) 358 // cases. `s` == DigitBits never happen as we asserted. Since `sZeroMask` 359 // clears the value in the case of `s` == 0, `s` == 0 case is also covered. 360 static_assert(sizeof(intptr_t) == sizeof(Digit), 361 "unexpected size of BigInt::Digit"); 362 Digit sZeroMask = 363 static_cast<Digit>((-static_cast<intptr_t>(s)) >> (DigitBits - 1)); 364 static constexpr unsigned shiftMask = DigitBits - 1; 365 Digit un32 = 366 (high << s) | ((low >> ((DigitBits - s) & shiftMask)) & sZeroMask); 367 368 Digit un10 = low << s; 369 Digit un1 = un10 >> HalfDigitBits; 370 Digit un0 = un10 & HalfDigitMask; 371 Digit q1 = un32 / vn1; 372 Digit rhat = un32 - q1 * vn1; 373 374 while (q1 >= HalfDigitBase || q1 * vn0 > rhat * HalfDigitBase + un1) { 375 q1--; 376 rhat += vn1; 377 if (rhat >= HalfDigitBase) { 378 break; 379 } 380 } 381 382 Digit un21 = un32 * HalfDigitBase + un1 - q1 * divisor; 383 Digit q0 = un21 / vn1; 384 rhat = un21 - q0 * vn1; 385 386 while (q0 >= HalfDigitBase || q0 * vn0 > rhat * HalfDigitBase + un0) { 387 q0--; 388 rhat += vn1; 389 if (rhat >= HalfDigitBase) { 390 break; 391 } 392 } 393 394 *remainder = (un21 * HalfDigitBase + un0 - q0 * divisor) >> s; 395 return q1 * HalfDigitBase + q0; 396 #endif 397 } 398 399 // Multiplies `source` with `factor` and adds `summand` to the result. 400 // `result` and `source` may be the same BigInt for inplace modification. 401 void BigInt::internalMultiplyAdd(const BigInt* source, Digit factor, 402 Digit summand, unsigned n, BigInt* result) { 403 MOZ_ASSERT(source->digitLength() >= n); 404 MOZ_ASSERT(result->digitLength() >= n); 405 406 Digit carry = summand; 407 Digit high = 0; 408 for (unsigned i = 0; i < n; i++) { 409 Digit current = source->digit(i); 410 Digit newCarry = 0; 411 412 // Compute this round's multiplication. 413 Digit newHigh = 0; 414 current = digitMul(current, factor, &newHigh); 415 416 // Add last round's carryovers. 417 current = digitAdd(current, high, &newCarry); 418 current = digitAdd(current, carry, &newCarry); 419 420 // Store result and prepare for next round. 421 result->setDigit(i, current); 422 carry = newCarry; 423 high = newHigh; 424 } 425 426 if (result->digitLength() > n) { 427 result->setDigit(n++, carry + high); 428 429 // Current callers don't pass in such large results, but let's be robust. 430 while (n < result->digitLength()) { 431 result->setDigit(n++, 0); 432 } 433 } else { 434 MOZ_ASSERT(!(carry + high)); 435 } 436 } 437 438 // Multiplies `this` with `factor` and adds `summand` to the result. 439 void BigInt::inplaceMultiplyAdd(Digit factor, Digit summand) { 440 internalMultiplyAdd(this, factor, summand, digitLength(), this); 441 } 442 443 // Multiplies `multiplicand` with `multiplier` and adds the result to 444 // `accumulator`, starting at `accumulatorIndex` for the least-significant 445 // digit. Callers must ensure that `accumulator`'s digitLength and 446 // corresponding digit storage is long enough to hold the result. 447 void BigInt::multiplyAccumulate(const BigInt* multiplicand, Digit multiplier, 448 BigInt* accumulator, 449 unsigned accumulatorIndex) { 450 MOZ_ASSERT(accumulator->digitLength() > 451 multiplicand->digitLength() + accumulatorIndex); 452 if (!multiplier) { 453 return; 454 } 455 456 Digit carry = 0; 457 Digit high = 0; 458 for (unsigned i = 0; i < multiplicand->digitLength(); 459 i++, accumulatorIndex++) { 460 Digit acc = accumulator->digit(accumulatorIndex); 461 Digit newCarry = 0; 462 463 // Add last round's carryovers. 464 acc = digitAdd(acc, high, &newCarry); 465 acc = digitAdd(acc, carry, &newCarry); 466 467 // Compute this round's multiplication. 468 Digit multiplicandDigit = multiplicand->digit(i); 469 Digit low = digitMul(multiplier, multiplicandDigit, &high); 470 acc = digitAdd(acc, low, &newCarry); 471 472 // Store result and prepare for next round. 473 accumulator->setDigit(accumulatorIndex, acc); 474 carry = newCarry; 475 } 476 477 while (carry || high) { 478 MOZ_ASSERT(accumulatorIndex < accumulator->digitLength()); 479 Digit acc = accumulator->digit(accumulatorIndex); 480 Digit newCarry = 0; 481 acc = digitAdd(acc, high, &newCarry); 482 high = 0; 483 acc = digitAdd(acc, carry, &newCarry); 484 accumulator->setDigit(accumulatorIndex, acc); 485 carry = newCarry; 486 accumulatorIndex++; 487 } 488 } 489 490 inline int8_t BigInt::absoluteCompare(const BigInt* x, const BigInt* y) { 491 MOZ_ASSERT(!HasLeadingZeroes(x)); 492 MOZ_ASSERT(!HasLeadingZeroes(y)); 493 494 // Sanity checks to catch negative zeroes escaping to the wild. 495 MOZ_ASSERT(!x->isNegative() || !x->isZero()); 496 MOZ_ASSERT(!y->isNegative() || !y->isZero()); 497 498 int diff = x->digitLength() - y->digitLength(); 499 if (diff) { 500 return diff < 0 ? -1 : 1; 501 } 502 503 int i = x->digitLength() - 1; 504 while (i >= 0 && x->digit(i) == y->digit(i)) { 505 i--; 506 } 507 508 if (i < 0) { 509 return 0; 510 } 511 512 return x->digit(i) > y->digit(i) ? 1 : -1; 513 } 514 515 BigInt* BigInt::absoluteAdd(JSContext* cx, HandleBigInt x, HandleBigInt y, 516 bool resultNegative) { 517 bool swap = x->digitLength() < y->digitLength(); 518 // Ensure `left` has at least as many digits as `right`. 519 HandleBigInt& left = swap ? y : x; 520 HandleBigInt& right = swap ? x : y; 521 522 if (left->isZero()) { 523 MOZ_ASSERT(right->isZero()); 524 return left; 525 } 526 527 if (right->isZero()) { 528 return resultNegative == left->isNegative() ? left : neg(cx, left); 529 } 530 531 // Fast path for the likely-common case of up to a uint64_t of magnitude. 532 if (left->absFitsInUint64()) { 533 MOZ_ASSERT(right->absFitsInUint64()); 534 535 uint64_t lhs = left->uint64FromAbsNonZero(); 536 uint64_t rhs = right->uint64FromAbsNonZero(); 537 538 uint64_t res = lhs + rhs; 539 bool overflow = res < lhs; 540 MOZ_ASSERT(res != 0 || overflow); 541 542 size_t resultLength = 1; 543 if (DigitBits == 32) { 544 if (overflow) { 545 resultLength = 3; 546 } else if (res >> 32) { 547 resultLength = 2; 548 } 549 } else { 550 if (overflow) { 551 resultLength = 2; 552 } 553 } 554 BigInt* result = createUninitialized(cx, resultLength, resultNegative); 555 if (!result) { 556 return nullptr; 557 } 558 result->setDigit(0, res); 559 if (DigitBits == 32 && resultLength > 1) { 560 result->setDigit(1, res >> 32); 561 } 562 if (overflow) { 563 constexpr size_t overflowIndex = DigitBits == 32 ? 2 : 1; 564 result->setDigit(overflowIndex, 1); 565 } 566 567 MOZ_ASSERT(!HasLeadingZeroes(result)); 568 return result; 569 } 570 571 BigInt* result = 572 createUninitialized(cx, left->digitLength() + 1, resultNegative); 573 if (!result) { 574 return nullptr; 575 } 576 Digit carry = 0; 577 unsigned i = 0; 578 for (; i < right->digitLength(); i++) { 579 Digit newCarry = 0; 580 Digit sum = digitAdd(left->digit(i), right->digit(i), &newCarry); 581 sum = digitAdd(sum, carry, &newCarry); 582 result->setDigit(i, sum); 583 carry = newCarry; 584 } 585 586 for (; i < left->digitLength(); i++) { 587 Digit newCarry = 0; 588 Digit sum = digitAdd(left->digit(i), carry, &newCarry); 589 result->setDigit(i, sum); 590 carry = newCarry; 591 } 592 593 result->setDigit(i, carry); 594 595 return destructivelyTrimHighZeroDigits(cx, result); 596 } 597 598 BigInt* BigInt::absoluteSub(JSContext* cx, HandleBigInt x, HandleBigInt y, 599 bool resultNegative) { 600 MOZ_ASSERT(x->digitLength() >= y->digitLength()); 601 MOZ_ASSERT(absoluteCompare(x, y) > 0); 602 MOZ_ASSERT(!x->isZero()); 603 604 if (y->isZero()) { 605 return resultNegative == x->isNegative() ? x : neg(cx, x); 606 } 607 608 // Fast path for the likely-common case of up to a uint64_t of magnitude. 609 if (x->absFitsInUint64()) { 610 MOZ_ASSERT(y->absFitsInUint64()); 611 612 uint64_t lhs = x->uint64FromAbsNonZero(); 613 uint64_t rhs = y->uint64FromAbsNonZero(); 614 MOZ_ASSERT(lhs > rhs); 615 616 uint64_t res = lhs - rhs; 617 MOZ_ASSERT(res != 0); 618 619 return createFromNonZeroRawUint64(cx, res, resultNegative); 620 } 621 622 BigInt* result = createUninitialized(cx, x->digitLength(), resultNegative); 623 if (!result) { 624 return nullptr; 625 } 626 Digit borrow = 0; 627 unsigned i = 0; 628 for (; i < y->digitLength(); i++) { 629 Digit newBorrow = 0; 630 Digit difference = digitSub(x->digit(i), y->digit(i), &newBorrow); 631 difference = digitSub(difference, borrow, &newBorrow); 632 result->setDigit(i, difference); 633 borrow = newBorrow; 634 } 635 636 for (; i < x->digitLength(); i++) { 637 Digit newBorrow = 0; 638 Digit difference = digitSub(x->digit(i), borrow, &newBorrow); 639 result->setDigit(i, difference); 640 borrow = newBorrow; 641 } 642 643 MOZ_ASSERT(!borrow); 644 return destructivelyTrimHighZeroDigits(cx, result); 645 } 646 647 // Divides `x` by `divisor`, returning the result in `quotient` and `remainder`. 648 // Mathematically, the contract is: 649 // 650 // quotient = (x - remainder) / divisor, with 0 <= remainder < divisor. 651 // 652 // If `quotient` is an empty handle, an appropriately sized BigInt will be 653 // allocated for it; otherwise the caller must ensure that it is big enough. 654 // `quotient` can be the same as `x` for an in-place division. `quotient` can 655 // also be `Nothing()` if the caller is only interested in the remainder. 656 // 657 // This function returns false if `quotient` is an empty handle, but allocating 658 // the quotient failed. Otherwise it returns true, indicating success. 659 bool BigInt::absoluteDivWithDigitDivisor( 660 JSContext* cx, HandleBigInt x, Digit divisor, 661 const Maybe<MutableHandleBigInt>& quotient, Digit* remainder, 662 bool quotientNegative) { 663 MOZ_ASSERT(divisor); 664 665 MOZ_ASSERT(!x->isZero()); 666 *remainder = 0; 667 if (divisor == 1) { 668 if (quotient) { 669 BigInt* q; 670 if (x->isNegative() == quotientNegative) { 671 q = x; 672 } else { 673 q = neg(cx, x); 674 if (!q) { 675 return false; 676 } 677 } 678 quotient.value().set(q); 679 } 680 return true; 681 } 682 683 unsigned length = x->digitLength(); 684 if (quotient) { 685 if (!quotient.value()) { 686 BigInt* q = createUninitialized(cx, length, quotientNegative); 687 if (!q) { 688 return false; 689 } 690 quotient.value().set(q); 691 } 692 693 for (int i = length - 1; i >= 0; i--) { 694 Digit q = digitDiv(*remainder, x->digit(i), divisor, remainder); 695 quotient.value()->setDigit(i, q); 696 } 697 } else { 698 for (int i = length - 1; i >= 0; i--) { 699 digitDiv(*remainder, x->digit(i), divisor, remainder); 700 } 701 } 702 703 return true; 704 } 705 706 // Adds `summand` onto `this`, starting with `summand`'s 0th digit 707 // at `this`'s `startIndex`'th digit. Returns the "carry" (0 or 1). 708 BigInt::Digit BigInt::absoluteInplaceAdd(const BigInt* summand, 709 unsigned startIndex) { 710 Digit carry = 0; 711 unsigned n = summand->digitLength(); 712 MOZ_ASSERT(digitLength() > startIndex, 713 "must start adding at an in-range digit"); 714 MOZ_ASSERT(digitLength() - startIndex >= n, 715 "digits being added to must not extend above the digits in " 716 "this (except for the returned carry digit)"); 717 for (unsigned i = 0; i < n; i++) { 718 Digit newCarry = 0; 719 Digit sum = digitAdd(digit(startIndex + i), summand->digit(i), &newCarry); 720 sum = digitAdd(sum, carry, &newCarry); 721 setDigit(startIndex + i, sum); 722 carry = newCarry; 723 } 724 725 return carry; 726 } 727 728 // Subtracts `subtrahend` from this, starting with `subtrahend`'s 0th digit 729 // at `this`'s `startIndex`-th digit. Returns the "borrow" (0 or 1). 730 BigInt::Digit BigInt::absoluteInplaceSub(const BigInt* subtrahend, 731 unsigned startIndex) { 732 Digit borrow = 0; 733 unsigned n = subtrahend->digitLength(); 734 MOZ_ASSERT(digitLength() > startIndex, 735 "must start subtracting from an in-range digit"); 736 MOZ_ASSERT(digitLength() - startIndex >= n, 737 "digits being subtracted from must not extend above the " 738 "digits in this (except for the returned borrow digit)"); 739 for (unsigned i = 0; i < n; i++) { 740 Digit newBorrow = 0; 741 Digit difference = 742 digitSub(digit(startIndex + i), subtrahend->digit(i), &newBorrow); 743 difference = digitSub(difference, borrow, &newBorrow); 744 setDigit(startIndex + i, difference); 745 borrow = newBorrow; 746 } 747 748 return borrow; 749 } 750 751 // Returns whether (factor1 * factor2) > (high << kDigitBits) + low. 752 inline bool BigInt::productGreaterThan(Digit factor1, Digit factor2, Digit high, 753 Digit low) { 754 Digit resultHigh; 755 Digit resultLow = digitMul(factor1, factor2, &resultHigh); 756 return resultHigh > high || (resultHigh == high && resultLow > low); 757 } 758 759 void BigInt::inplaceRightShiftLowZeroBits(unsigned shift) { 760 MOZ_ASSERT(shift < DigitBits); 761 MOZ_ASSERT(!(digit(0) & ((static_cast<Digit>(1) << shift) - 1)), 762 "should only be shifting away zeroes"); 763 764 if (!shift) { 765 return; 766 } 767 768 Digit carry = digit(0) >> shift; 769 unsigned last = digitLength() - 1; 770 for (unsigned i = 0; i < last; i++) { 771 Digit d = digit(i + 1); 772 setDigit(i, (d << (DigitBits - shift)) | carry); 773 carry = d >> shift; 774 } 775 setDigit(last, carry); 776 } 777 778 // Always copies the input, even when `shift` == 0. 779 BigInt* BigInt::absoluteLeftShiftAlwaysCopy(JSContext* cx, HandleBigInt x, 780 unsigned shift, 781 LeftShiftMode mode) { 782 MOZ_ASSERT(shift < DigitBits); 783 MOZ_ASSERT(!x->isZero()); 784 785 unsigned n = x->digitLength(); 786 unsigned resultLength = mode == LeftShiftMode::AlwaysAddOneDigit ? n + 1 : n; 787 BigInt* result = createUninitialized(cx, resultLength, x->isNegative()); 788 if (!result) { 789 return nullptr; 790 } 791 792 if (!shift) { 793 for (unsigned i = 0; i < n; i++) { 794 result->setDigit(i, x->digit(i)); 795 } 796 if (mode == LeftShiftMode::AlwaysAddOneDigit) { 797 result->setDigit(n, 0); 798 } 799 800 return result; 801 } 802 803 Digit carry = 0; 804 for (unsigned i = 0; i < n; i++) { 805 Digit d = x->digit(i); 806 result->setDigit(i, (d << shift) | carry); 807 carry = d >> (DigitBits - shift); 808 } 809 810 if (mode == LeftShiftMode::AlwaysAddOneDigit) { 811 result->setDigit(n, carry); 812 } else { 813 MOZ_ASSERT(mode == LeftShiftMode::SameSizeResult); 814 MOZ_ASSERT(!carry); 815 } 816 817 return result; 818 } 819 820 // Divides `dividend` by `divisor`, returning the result in `quotient` and 821 // `remainder`. Mathematically, the contract is: 822 // 823 // quotient = (dividend - remainder) / divisor, with 0 <= remainder < divisor. 824 // 825 // Both `quotient` and `remainder` are optional, for callers that are only 826 // interested in one of them. See Knuth, Volume 2, section 4.3.1, Algorithm D. 827 // Also see the overview of the algorithm by Jan Marthedal Rasmussen over at 828 // https://janmr.com/blog/2014/04/basic-multiple-precision-long-division/. 829 bool BigInt::absoluteDivWithBigIntDivisor( 830 JSContext* cx, HandleBigInt dividend, HandleBigInt divisor, 831 const Maybe<MutableHandleBigInt>& quotient, 832 const Maybe<MutableHandleBigInt>& remainder, bool isNegative) { 833 MOZ_ASSERT(divisor->digitLength() >= 2); 834 MOZ_ASSERT(dividend->digitLength() >= divisor->digitLength()); 835 836 // Any early error return is detectable by checking the quotient and/or 837 // remainder output values. 838 MOZ_ASSERT(!quotient || !quotient.value()); 839 MOZ_ASSERT(!remainder || !remainder.value()); 840 841 // The unusual variable names inside this function are consistent with 842 // Knuth's book, as well as with Go's implementation of this algorithm. 843 // Maintaining this consistency is probably more useful than trying to 844 // come up with more descriptive names for them. 845 const unsigned n = divisor->digitLength(); 846 const unsigned m = dividend->digitLength() - n; 847 848 RootedTuple<BigInt*, BigInt*, BigInt*, BigInt*> roots(cx); 849 850 // The quotient to be computed. 851 RootedField<BigInt*, 0> q(roots); 852 if (quotient) { 853 q = createUninitialized(cx, m + 1, isNegative); 854 if (!q) { 855 return false; 856 } 857 } 858 859 // In each iteration, `qhatv` holds `divisor` * `current quotient digit`. 860 // "v" is the book's name for `divisor`, `qhat` the current quotient digit. 861 RootedField<BigInt*, 1> qhatv(roots, 862 createUninitialized(cx, n + 1, isNegative)); 863 if (!qhatv) { 864 return false; 865 } 866 867 // D1. 868 // Left-shift inputs so that the divisor's MSB is set. This is necessary to 869 // prevent the digit-wise divisions (see digitDiv call below) from 870 // overflowing (they take a two digits wide input, and return a one digit 871 // result). 872 Digit lastDigit = divisor->digit(n - 1); 873 unsigned shift = DigitLeadingZeroes(lastDigit); 874 875 RootedField<BigInt*, 2> shiftedDivisor(roots); 876 if (shift > 0) { 877 shiftedDivisor = absoluteLeftShiftAlwaysCopy(cx, divisor, shift, 878 LeftShiftMode::SameSizeResult); 879 if (!shiftedDivisor) { 880 return false; 881 } 882 } else { 883 shiftedDivisor = divisor; 884 } 885 886 // Holds the (continuously updated) remaining part of the dividend, which 887 // eventually becomes the remainder. 888 RootedField<BigInt*, 3> u( 889 roots, absoluteLeftShiftAlwaysCopy(cx, dividend, shift, 890 LeftShiftMode::AlwaysAddOneDigit)); 891 if (!u) { 892 return false; 893 } 894 895 // D2. 896 // Iterate over the dividend's digit (like the "grade school" algorithm). 897 // `vn1` is the divisor's most significant digit. 898 Digit vn1 = shiftedDivisor->digit(n - 1); 899 for (int j = m; j >= 0; j--) { 900 // D3. 901 // Estimate the current iteration's quotient digit (see Knuth for details). 902 // `qhat` is the current quotient digit. 903 Digit qhat = std::numeric_limits<Digit>::max(); 904 905 // `ujn` is the dividend's most significant remaining digit. 906 Digit ujn = u->digit(j + n); 907 if (ujn != vn1) { 908 // `rhat` is the current iteration's remainder. 909 Digit rhat = 0; 910 // Estimate the current quotient digit by dividing the most significant 911 // digits of dividend and divisor. The result will not be too small, 912 // but could be a bit too large. 913 qhat = digitDiv(ujn, u->digit(j + n - 1), vn1, &rhat); 914 915 // Decrement the quotient estimate as needed by looking at the next 916 // digit, i.e. by testing whether 917 // qhat * v_{n-2} > (rhat << DigitBits) + u_{j+n-2}. 918 Digit vn2 = shiftedDivisor->digit(n - 2); 919 Digit ujn2 = u->digit(j + n - 2); 920 while (productGreaterThan(qhat, vn2, rhat, ujn2)) { 921 qhat--; 922 Digit prevRhat = rhat; 923 rhat += vn1; 924 // v[n-1] >= 0, so this tests for overflow. 925 if (rhat < prevRhat) { 926 break; 927 } 928 } 929 } 930 931 // D4. 932 // Multiply the divisor with the current quotient digit, and subtract 933 // it from the dividend. If there was "borrow", then the quotient digit 934 // was one too high, so we must correct it and undo one subtraction of 935 // the (shifted) divisor. 936 internalMultiplyAdd(shiftedDivisor, qhat, 0, n, qhatv); 937 Digit c = u->absoluteInplaceSub(qhatv, j); 938 if (c) { 939 c = u->absoluteInplaceAdd(shiftedDivisor, j); 940 u->setDigit(j + n, u->digit(j + n) + c); 941 qhat--; 942 } 943 944 if (quotient) { 945 q->setDigit(j, qhat); 946 } 947 } 948 949 if (quotient) { 950 BigInt* bi = destructivelyTrimHighZeroDigits(cx, q); 951 if (!bi) { 952 return false; 953 } 954 quotient.value().set(q); 955 } 956 957 if (remainder) { 958 u->inplaceRightShiftLowZeroBits(shift); 959 remainder.value().set(u); 960 } 961 962 return true; 963 } 964 965 // Helper for Absolute{And,AndNot,Or,Xor}. 966 // Performs the given binary `op` on digit pairs of `x` and `y`; when the 967 // end of the shorter of the two is reached, `kind` configures how 968 // remaining digits are handled. 969 // Example: 970 // y: [ y2 ][ y1 ][ y0 ] 971 // x: [ x3 ][ x2 ][ x1 ][ x0 ] 972 // | | | | 973 // (Fill) (op) (op) (op) 974 // | | | | 975 // v v v v 976 // result: [ 0 ][ x3 ][ r2 ][ r1 ][ r0 ] 977 template <BigInt::BitwiseOpKind kind, typename BitwiseOp> 978 inline BigInt* BigInt::absoluteBitwiseOp(JSContext* cx, HandleBigInt x, 979 HandleBigInt y, BitwiseOp&& op) { 980 unsigned xLength = x->digitLength(); 981 unsigned yLength = y->digitLength(); 982 unsigned numPairs = std::min(xLength, yLength); 983 unsigned resultLength; 984 if (kind == BitwiseOpKind::SymmetricTrim) { 985 resultLength = numPairs; 986 } else if (kind == BitwiseOpKind::SymmetricFill) { 987 resultLength = std::max(xLength, yLength); 988 } else { 989 MOZ_ASSERT(kind == BitwiseOpKind::AsymmetricFill); 990 resultLength = xLength; 991 } 992 bool resultNegative = false; 993 994 BigInt* result = createUninitialized(cx, resultLength, resultNegative); 995 if (!result) { 996 return nullptr; 997 } 998 999 unsigned i = 0; 1000 for (; i < numPairs; i++) { 1001 result->setDigit(i, op(x->digit(i), y->digit(i))); 1002 } 1003 1004 if (kind != BitwiseOpKind::SymmetricTrim) { 1005 BigInt* source = kind == BitwiseOpKind::AsymmetricFill ? x 1006 : xLength == i ? y 1007 : x; 1008 for (; i < resultLength; i++) { 1009 result->setDigit(i, source->digit(i)); 1010 } 1011 } 1012 1013 MOZ_ASSERT(i == resultLength); 1014 1015 return destructivelyTrimHighZeroDigits(cx, result); 1016 } 1017 1018 BigInt* BigInt::absoluteAnd(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1019 return absoluteBitwiseOp<BitwiseOpKind::SymmetricTrim>(cx, x, y, 1020 std::bit_and<Digit>()); 1021 } 1022 1023 BigInt* BigInt::absoluteOr(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1024 return absoluteBitwiseOp<BitwiseOpKind::SymmetricFill>(cx, x, y, 1025 std::bit_or<Digit>()); 1026 } 1027 1028 BigInt* BigInt::absoluteAndNot(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1029 auto digitOperation = [](Digit a, Digit b) { return a & ~b; }; 1030 return absoluteBitwiseOp<BitwiseOpKind::AsymmetricFill>(cx, x, y, 1031 digitOperation); 1032 } 1033 1034 BigInt* BigInt::absoluteXor(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1035 return absoluteBitwiseOp<BitwiseOpKind::SymmetricFill>(cx, x, y, 1036 std::bit_xor<Digit>()); 1037 } 1038 1039 BigInt* BigInt::absoluteAddOne(JSContext* cx, HandleBigInt x, 1040 bool resultNegative) { 1041 unsigned inputLength = x->digitLength(); 1042 // The addition will overflow into a new digit if all existing digits are 1043 // at maximum. 1044 bool willOverflow = true; 1045 for (unsigned i = 0; i < inputLength; i++) { 1046 if (std::numeric_limits<Digit>::max() != x->digit(i)) { 1047 willOverflow = false; 1048 break; 1049 } 1050 } 1051 1052 unsigned resultLength = inputLength + willOverflow; 1053 BigInt* result = createUninitialized(cx, resultLength, resultNegative); 1054 if (!result) { 1055 return nullptr; 1056 } 1057 1058 Digit carry = 1; 1059 for (unsigned i = 0; i < inputLength; i++) { 1060 Digit newCarry = 0; 1061 result->setDigit(i, digitAdd(x->digit(i), carry, &newCarry)); 1062 carry = newCarry; 1063 } 1064 if (resultLength > inputLength) { 1065 MOZ_ASSERT(carry == 1); 1066 result->setDigit(inputLength, 1); 1067 } else { 1068 MOZ_ASSERT(!carry); 1069 } 1070 1071 return destructivelyTrimHighZeroDigits(cx, result); 1072 } 1073 1074 BigInt* BigInt::absoluteSubOne(JSContext* cx, HandleBigInt x, 1075 bool resultNegative) { 1076 MOZ_ASSERT(!x->isZero()); 1077 1078 unsigned length = x->digitLength(); 1079 1080 if (length == 1) { 1081 Digit d = x->digit(0); 1082 if (d == 1) { 1083 // Ignore resultNegative. 1084 return zero(cx); 1085 } 1086 return createFromDigit(cx, d - 1, resultNegative); 1087 } 1088 1089 BigInt* result = createUninitialized(cx, length, resultNegative); 1090 if (!result) { 1091 return nullptr; 1092 } 1093 1094 Digit borrow = 1; 1095 for (unsigned i = 0; i < length; i++) { 1096 Digit newBorrow = 0; 1097 result->setDigit(i, digitSub(x->digit(i), borrow, &newBorrow)); 1098 borrow = newBorrow; 1099 } 1100 MOZ_ASSERT(!borrow); 1101 1102 return destructivelyTrimHighZeroDigits(cx, result); 1103 } 1104 1105 BigInt* BigInt::inc(JSContext* cx, HandleBigInt x) { 1106 if (x->isZero()) { 1107 return one(cx); 1108 } 1109 1110 bool isNegative = x->isNegative(); 1111 if (isNegative) { 1112 return absoluteSubOne(cx, x, isNegative); 1113 } 1114 1115 return absoluteAddOne(cx, x, isNegative); 1116 } 1117 1118 BigInt* BigInt::dec(JSContext* cx, HandleBigInt x) { 1119 if (x->isZero()) { 1120 return negativeOne(cx); 1121 } 1122 1123 bool isNegative = x->isNegative(); 1124 if (isNegative) { 1125 return absoluteAddOne(cx, x, isNegative); 1126 } 1127 1128 return absoluteSubOne(cx, x, isNegative); 1129 } 1130 1131 // Lookup table for the maximum number of bits required per character of a 1132 // base-N string representation of a number. To increase accuracy, the array 1133 // value is the actual value multiplied by 32. To generate this table: 1134 // for (var i = 0; i <= 36; i++) { print(Math.ceil(Math.log2(i) * 32) + ","); } 1135 static constexpr uint8_t maxBitsPerCharTable[] = { 1136 0, 0, 32, 51, 64, 75, 83, 90, 96, // 0..8 1137 102, 107, 111, 115, 119, 122, 126, 128, // 9..16 1138 131, 134, 136, 139, 141, 143, 145, 147, // 17..24 1139 149, 151, 153, 154, 156, 158, 159, 160, // 25..32 1140 162, 163, 165, 166, // 33..36 1141 }; 1142 1143 static constexpr unsigned bitsPerCharTableShift = 5; 1144 static constexpr size_t bitsPerCharTableMultiplier = 1u 1145 << bitsPerCharTableShift; 1146 static constexpr char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 1147 1148 static inline uint64_t CeilDiv(uint64_t numerator, uint64_t denominator) { 1149 MOZ_ASSERT(numerator != 0); 1150 return 1 + (numerator - 1) / denominator; 1151 }; 1152 1153 // Compute (an overapproximation of) the length of the string representation of 1154 // a BigInt. In base B an X-digit number has maximum value: 1155 // 1156 // B**X - 1 1157 // 1158 // We're trying to find N for an N-digit number in base |radix| full 1159 // representing a |bitLength|-digit number in base 2, so we have: 1160 // 1161 // radix**N - 1 ≥ 2**bitLength - 1 1162 // radix**N ≥ 2**bitLength 1163 // N ≥ log2(2**bitLength) / log2(radix) 1164 // N ≥ bitLength / log2(radix) 1165 // 1166 // so the smallest N is: 1167 // 1168 // N = ⌈bitLength / log2(radix)⌉ 1169 // 1170 // We want to avoid floating-point computations and precompute the logarithm, so 1171 // we multiply both sides of the division by |bitsPerCharTableMultiplier|: 1172 // 1173 // N = ⌈(bPCTM * bitLength) / (bPCTM * log2(radix))⌉ 1174 // 1175 // and then because |maxBitsPerChar| representing the denominator may have been 1176 // rounded *up* -- which could produce an overall under-computation -- we reduce 1177 // by one to undo any rounding and conservatively compute: 1178 // 1179 // N ≥ ⌈(bPCTM * bitLength) / (maxBitsPerChar - 1)⌉ 1180 // 1181 size_t BigInt::calculateMaximumCharactersRequired(HandleBigInt x, 1182 unsigned radix) { 1183 MOZ_ASSERT(!x->isZero()); 1184 MOZ_ASSERT(radix >= 2 && radix <= 36); 1185 1186 size_t length = x->digitLength(); 1187 Digit lastDigit = x->digit(length - 1); 1188 size_t bitLength = length * DigitBits - DigitLeadingZeroes(lastDigit); 1189 1190 uint8_t maxBitsPerChar = maxBitsPerCharTable[radix]; 1191 uint64_t maximumCharactersRequired = 1192 CeilDiv(static_cast<uint64_t>(bitsPerCharTableMultiplier) * bitLength, 1193 maxBitsPerChar - 1); 1194 maximumCharactersRequired += x->isNegative(); 1195 1196 return AssertedCast<size_t>(maximumCharactersRequired); 1197 } 1198 1199 template <AllowGC allowGC> 1200 JSLinearString* BigInt::toStringBasePowerOfTwo(JSContext* cx, HandleBigInt x, 1201 unsigned radix) { 1202 MOZ_ASSERT(mozilla::IsPowerOfTwo(radix)); 1203 MOZ_ASSERT(radix >= 2 && radix <= 32); 1204 MOZ_ASSERT(!x->isZero()); 1205 MOZ_ASSERT(x->digitLength() > 1); 1206 1207 const unsigned length = x->digitLength(); 1208 const bool sign = x->isNegative(); 1209 const unsigned bitsPerChar = mozilla::CountTrailingZeroes32(radix); 1210 const unsigned charMask = radix - 1; 1211 // Compute the length of the resulting string: divide the bit length of the 1212 // BigInt by the number of bits representable per character (rounding up). 1213 const Digit msd = x->digit(length - 1); 1214 1215 const size_t bitLength = length * DigitBits - DigitLeadingZeroes(msd); 1216 const size_t charsRequired = CeilDiv(bitLength, bitsPerChar) + sign; 1217 1218 static_assert(MaxBitLength + 1 <= JSString::MAX_LENGTH, 1219 "Base 2 representation (including leading sign) of the largest " 1220 "possible BigInt fits into a string"); 1221 1222 MOZ_RELEASE_ASSERT(charsRequired <= JSString::MAX_LENGTH); 1223 1224 StringChars<JS::Latin1Char> stringChars(cx); 1225 if (!stringChars.maybeAlloc(cx, charsRequired)) { 1226 if constexpr (!allowGC) { 1227 cx->recoverFromOutOfMemory(); 1228 } 1229 return nullptr; 1230 } 1231 1232 { 1233 JS::AutoCheckCannotGC nogc; 1234 auto* resultChars = stringChars.data(nogc); 1235 1236 Digit digit = 0; 1237 // Keeps track of how many unprocessed bits there are in |digit|. 1238 unsigned availableBits = 0; 1239 size_t pos = charsRequired; 1240 for (unsigned i = 0; i < length - 1; i++) { 1241 Digit newDigit = x->digit(i); 1242 // Take any leftover bits from the last iteration into account. 1243 unsigned current = (digit | (newDigit << availableBits)) & charMask; 1244 MOZ_ASSERT(pos); 1245 resultChars[--pos] = radixDigits[current]; 1246 unsigned consumedBits = bitsPerChar - availableBits; 1247 digit = newDigit >> consumedBits; 1248 availableBits = DigitBits - consumedBits; 1249 while (availableBits >= bitsPerChar) { 1250 MOZ_ASSERT(pos); 1251 resultChars[--pos] = radixDigits[digit & charMask]; 1252 digit >>= bitsPerChar; 1253 availableBits -= bitsPerChar; 1254 } 1255 } 1256 1257 // Write out the character containing the lowest-order bit of |msd|. 1258 // 1259 // This character may include leftover bits from the Digit below |msd|. For 1260 // example, if |x === 2n**64n| and |radix == 32|: the preceding loop writes 1261 // twelve zeroes for low-order bits 0-59 in |x->digit(0)| (and |x->digit(1)| 1262 // on 32-bit); then the highest 4 bits of of |x->digit(0)| (or |x->digit(1)| 1263 // on 32-bit) and bit 0 of |x->digit(1)| (|x->digit(2)| on 32-bit) will 1264 // comprise the |current == 0b1'0000| computed below for the high-order 'g' 1265 // character. 1266 unsigned current = (digit | (msd << availableBits)) & charMask; 1267 MOZ_ASSERT(pos); 1268 resultChars[--pos] = radixDigits[current]; 1269 1270 // Write out remaining characters represented by |msd|. (There may be none, 1271 // as in the example above.) 1272 digit = msd >> (bitsPerChar - availableBits); 1273 while (digit != 0) { 1274 MOZ_ASSERT(pos); 1275 resultChars[--pos] = radixDigits[digit & charMask]; 1276 digit >>= bitsPerChar; 1277 } 1278 1279 if (sign) { 1280 MOZ_ASSERT(pos); 1281 resultChars[--pos] = '-'; 1282 } 1283 MOZ_ASSERT(pos == 0); 1284 } 1285 1286 return stringChars.toStringDontDeflateNonStatic<allowGC>(cx, charsRequired); 1287 } 1288 1289 template <AllowGC allowGC> 1290 JSLinearString* BigInt::toStringSingleDigit(JSContext* cx, Digit digit, 1291 bool isNegative, unsigned radix) { 1292 MOZ_ASSERT(digit != 0, "zero case should have been handled in toString"); 1293 1294 if (digit <= Digit(INT32_MAX)) { 1295 int32_t val = AssertedCast<int32_t>(digit); 1296 return Int32ToStringWithBase<allowGC>(cx, isNegative ? -val : val, radix, 1297 /* lowerCase = */ true); 1298 } 1299 1300 // Plus one to include the sign. 1301 constexpr size_t maxLength = std::numeric_limits<Digit>::digits + 1; 1302 static_assert(maxLength == 33 || maxLength == 65, 1303 "unexpected single digit string length"); 1304 1305 char resultChars[maxLength]; 1306 1307 char* chars = resultChars; 1308 if (isNegative) { 1309 *chars++ = '-'; 1310 } 1311 1312 auto result = std::to_chars(chars, std::end(resultChars), digit, radix); 1313 MOZ_ASSERT(result.ec == std::errc()); 1314 1315 size_t length = result.ptr - resultChars; 1316 MOZ_ASSERT(length <= maxLength); 1317 1318 return NewStringCopyN<allowGC>(cx, resultChars, length); 1319 } 1320 1321 static constexpr BigInt::Digit MaxPowerInDigit(uint8_t radix) { 1322 BigInt::Digit result = 1; 1323 while (result < BigInt::Digit(-1) / radix) { 1324 result *= radix; 1325 } 1326 return result; 1327 } 1328 1329 static constexpr uint8_t MaxExponentInDigit(uint8_t radix) { 1330 uint8_t exp = 0; 1331 BigInt::Digit result = 1; 1332 while (result < BigInt::Digit(-1) / radix) { 1333 result *= radix; 1334 exp += 1; 1335 } 1336 return exp; 1337 } 1338 1339 struct RadixInfo { 1340 BigInt::Digit maxPowerInDigit; 1341 uint8_t maxExponentInDigit; 1342 1343 constexpr RadixInfo(BigInt::Digit maxPower, uint8_t maxExponent) 1344 : maxPowerInDigit(maxPower), maxExponentInDigit(maxExponent) {} 1345 1346 explicit constexpr RadixInfo(uint8_t radix) 1347 : RadixInfo(MaxPowerInDigit(radix), MaxExponentInDigit(radix)) {} 1348 }; 1349 1350 static constexpr const RadixInfo toStringInfo[37] = { 1351 {0, 0}, {0, 0}, RadixInfo(2), RadixInfo(3), RadixInfo(4), 1352 RadixInfo(5), RadixInfo(6), RadixInfo(7), RadixInfo(8), RadixInfo(9), 1353 RadixInfo(10), RadixInfo(11), RadixInfo(12), RadixInfo(13), RadixInfo(14), 1354 RadixInfo(15), RadixInfo(16), RadixInfo(17), RadixInfo(18), RadixInfo(19), 1355 RadixInfo(20), RadixInfo(21), RadixInfo(22), RadixInfo(23), RadixInfo(24), 1356 RadixInfo(25), RadixInfo(26), RadixInfo(27), RadixInfo(28), RadixInfo(29), 1357 RadixInfo(30), RadixInfo(31), RadixInfo(32), RadixInfo(33), RadixInfo(34), 1358 RadixInfo(35), RadixInfo(36), 1359 }; 1360 1361 JSLinearString* BigInt::toStringGeneric(JSContext* cx, HandleBigInt x, 1362 unsigned radix) { 1363 MOZ_ASSERT(radix >= 2 && radix <= 36); 1364 MOZ_ASSERT(!x->isZero()); 1365 MOZ_ASSERT(x->digitLength() > 1); 1366 MOZ_ASSERT(!mozilla::IsPowerOfTwo(radix)); 1367 1368 size_t maximumCharactersRequired = 1369 calculateMaximumCharactersRequired(x, radix); 1370 if (maximumCharactersRequired > JSString::MAX_LENGTH) { 1371 ReportAllocationOverflow(cx); 1372 return nullptr; 1373 } 1374 1375 auto resultString = cx->make_pod_array<char>(maximumCharactersRequired); 1376 if (!resultString) { 1377 return nullptr; 1378 } 1379 1380 size_t writePos = maximumCharactersRequired; 1381 1382 unsigned chunkChars = toStringInfo[radix].maxExponentInDigit; 1383 Digit chunkDivisor = toStringInfo[radix].maxPowerInDigit; 1384 1385 unsigned length = x->digitLength(); 1386 unsigned nonZeroDigit = length - 1; 1387 MOZ_ASSERT(x->digit(nonZeroDigit) != 0); 1388 1389 // `rest` holds the part of the BigInt that we haven't looked at yet. 1390 // Not to be confused with "remainder"! 1391 RootedBigInt rest(cx); 1392 1393 // In the first round, divide the input, allocating a new BigInt for 1394 // the result == rest; from then on divide the rest in-place. 1395 // 1396 // FIXME: absoluteDivWithDigitDivisor doesn't 1397 // destructivelyTrimHighZeroDigits for in-place divisions, leading to 1398 // worse constant factors. See 1399 // https://bugzilla.mozilla.org/show_bug.cgi?id=1510213. 1400 RootedBigInt dividend(cx, x); 1401 do { 1402 Digit chunk; 1403 if (!absoluteDivWithDigitDivisor(cx, dividend, chunkDivisor, Some(&rest), 1404 &chunk, dividend->isNegative())) { 1405 return nullptr; 1406 } 1407 1408 dividend = rest; 1409 for (unsigned i = 0; i < chunkChars; i++) { 1410 MOZ_ASSERT(writePos > 0); 1411 resultString[--writePos] = radixDigits[chunk % radix]; 1412 chunk /= radix; 1413 } 1414 MOZ_ASSERT(!chunk); 1415 1416 if (!rest->digit(nonZeroDigit)) { 1417 nonZeroDigit--; 1418 } 1419 1420 MOZ_ASSERT(rest->digit(nonZeroDigit) != 0, 1421 "division by a single digit can't remove more than one " 1422 "digit from a number"); 1423 } while (nonZeroDigit > 0); 1424 1425 Digit lastDigit = rest->digit(0); 1426 do { 1427 MOZ_ASSERT(writePos > 0); 1428 resultString[--writePos] = radixDigits[lastDigit % radix]; 1429 lastDigit /= radix; 1430 } while (lastDigit > 0); 1431 MOZ_ASSERT(writePos < maximumCharactersRequired); 1432 MOZ_ASSERT(maximumCharactersRequired - writePos <= 1433 static_cast<size_t>(maximumCharactersRequired)); 1434 1435 // Remove leading zeroes. 1436 while (writePos + 1 < maximumCharactersRequired && 1437 resultString[writePos] == '0') { 1438 writePos++; 1439 } 1440 1441 if (x->isNegative()) { 1442 MOZ_ASSERT(writePos > 0); 1443 resultString[--writePos] = '-'; 1444 } 1445 1446 MOZ_ASSERT(writePos < maximumCharactersRequired); 1447 // Would be better to somehow adopt resultString directly. 1448 return NewStringCopyN<CanGC>(cx, resultString.get() + writePos, 1449 maximumCharactersRequired - writePos); 1450 } 1451 1452 BigInt* BigInt::destructivelyTrimHighZeroDigits(JSContext* cx, BigInt* x) { 1453 if (x->isZero()) { 1454 MOZ_ASSERT(!x->isNegative()); 1455 return x; 1456 } 1457 MOZ_ASSERT(x->digitLength()); 1458 1459 int nonZeroIndex = x->digitLength() - 1; 1460 while (nonZeroIndex >= 0 && x->digit(nonZeroIndex) == 0) { 1461 nonZeroIndex--; 1462 } 1463 1464 if (nonZeroIndex < 0) { 1465 return zero(cx); 1466 } 1467 1468 if (nonZeroIndex == static_cast<int>(x->digitLength() - 1)) { 1469 return x; 1470 } 1471 1472 unsigned newLength = nonZeroIndex + 1; 1473 1474 if (newLength > InlineDigitsLength) { 1475 MOZ_ASSERT(x->hasHeapDigits()); 1476 1477 size_t oldLength = x->digitLength(); 1478 Digit* newdigits = ReallocateCellBuffer<Digit>(cx, x, x->heapDigits_, 1479 oldLength, newLength); 1480 if (!newdigits) { 1481 return nullptr; 1482 } 1483 x->heapDigits_ = newdigits; 1484 } else { 1485 if (x->hasHeapDigits()) { 1486 Digit digits[InlineDigitsLength]; 1487 std::copy_n(x->heapDigits_, InlineDigitsLength, digits); 1488 if (!cx->nursery().isInside(x->heapDigits_)) { 1489 FreeBuffer(x->zone(), x->heapDigits_); 1490 } 1491 std::copy_n(digits, InlineDigitsLength, x->inlineDigits_); 1492 } 1493 } 1494 1495 x->setLengthAndFlags(newLength, x->isNegative() ? SignBit : 0); 1496 1497 return x; 1498 } 1499 1500 // The maximum value `radix**charCount - 1` must be represented as a max number 1501 // `2**(N * DigitBits) - 1` for `N` digits, so 1502 // 1503 // 2**(N * DigitBits) - 1 ≥ radix**charcount - 1 1504 // 2**(N * DigitBits) ≥ radix**charcount 1505 // N * DigitBits ≥ log2(radix**charcount) 1506 // N * DigitBits ≥ charcount * log2(radix) 1507 // N ≥ ⌈charcount * log2(radix) / DigitBits⌉ (conservatively) 1508 // 1509 // or in the code's terms (all numbers promoted to exact mathematical values), 1510 // 1511 // N ≥ ⌈charcount * bitsPerChar / (DigitBits * bitsPerCharTableMultiplier)⌉ 1512 // 1513 // Note that `N` is computed even more conservatively here because `bitsPerChar` 1514 // is rounded up. 1515 bool BigInt::calculateMaximumDigitsRequired(JSContext* cx, uint8_t radix, 1516 size_t charcount, size_t* result) { 1517 MOZ_ASSERT(2 <= radix && radix <= 36); 1518 1519 uint8_t bitsPerChar = maxBitsPerCharTable[radix]; 1520 1521 MOZ_ASSERT(charcount > 0); 1522 MOZ_ASSERT(charcount <= std::numeric_limits<uint64_t>::max() / bitsPerChar); 1523 static_assert( 1524 MaxDigitLength < std::numeric_limits<size_t>::max(), 1525 "can't safely cast calculateMaximumDigitsRequired result to size_t"); 1526 1527 uint64_t n = CeilDiv(static_cast<uint64_t>(charcount) * bitsPerChar, 1528 DigitBits * bitsPerCharTableMultiplier); 1529 if (n > MaxDigitLength) { 1530 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 1531 return false; 1532 } 1533 1534 *result = n; 1535 return true; 1536 } 1537 1538 static BigInt::Digit PowerOf(BigInt::Digit base, size_t n) { 1539 MOZ_ASSERT(n > 0); 1540 mozilla::CheckedInt<BigInt::Digit> result = base; 1541 for (size_t i = 1; i < n; i++) { 1542 result *= base; 1543 } 1544 MOZ_ASSERT(result.isValid(), "unexpected overflow"); 1545 return result.value(); 1546 } 1547 1548 template <typename CharT> 1549 static bool ParseLiteralDigit(Range<const CharT> chars, unsigned radix, 1550 BigInt::Digit* result) { 1551 MOZ_ASSERT(chars.length() > 0); 1552 RangedPtr<const CharT> start = chars.begin(); 1553 RangedPtr<const CharT> end = chars.end(); 1554 1555 mozilla::CheckedInt<BigInt::Digit> d = 0; 1556 for (; start < end; start++) { 1557 uint32_t digit; 1558 CharT c = *start; 1559 if (c >= '0' && c <= '9') { 1560 digit = c - '0'; 1561 } else if (c >= 'a' && c <= 'z') { 1562 digit = c - 'a' + 10; 1563 } else if (c >= 'A' && c <= 'Z') { 1564 digit = c - 'A' + 10; 1565 } else { 1566 return false; 1567 } 1568 if (MOZ_UNLIKELY(digit >= radix)) { 1569 return false; 1570 } 1571 1572 d = d * radix + digit; 1573 } 1574 MOZ_ASSERT(d.isValid(), "unexpected overflow"); 1575 1576 *result = d.value(); 1577 return true; 1578 } 1579 1580 template <typename CharT> 1581 BigInt* BigInt::parseLiteralDigits(JSContext* cx, Range<const CharT> chars, 1582 unsigned radix, bool isNegative, 1583 bool* haveParseError, gc::Heap heap) { 1584 static_assert( 1585 std::is_same_v<CharT, JS::Latin1Char> || std::is_same_v<CharT, char16_t>, 1586 "only the bare minimum character types are supported, to avoid " 1587 "excessively instantiating this template"); 1588 1589 MOZ_ASSERT(chars.length()); 1590 1591 RangedPtr<const CharT> start = chars.begin(); 1592 RangedPtr<const CharT> end = chars.end(); 1593 1594 // Skipping leading zeroes. 1595 while (start[0] == '0') { 1596 start++; 1597 if (start == end) { 1598 return zero(cx, heap); 1599 } 1600 } 1601 1602 size_t length; 1603 if (!calculateMaximumDigitsRequired(cx, radix, end - start, &length)) { 1604 return nullptr; 1605 } 1606 MOZ_ASSERT(length > 0); 1607 1608 // Fast path for the single digit case. 1609 if (length == 1) { 1610 BigInt::Digit digit = 0; 1611 if (!ParseLiteralDigit(chars, radix, &digit)) { 1612 *haveParseError = true; 1613 return nullptr; 1614 } 1615 MOZ_ASSERT(digit > 0); 1616 return BigInt::createFromDigit(cx, digit, isNegative, heap); 1617 } 1618 1619 BigInt* result = createUninitialized(cx, length, isNegative, heap); 1620 if (!result) { 1621 return nullptr; 1622 } 1623 1624 result->initializeDigitsToZero(); 1625 1626 // Numbers in radix 2, 4, and 16 can be directly stored into the result when 1627 // parsing from right to left. 1628 uint8_t log2 = mozilla::FloorLog2(radix); 1629 if (mozilla::IsPowerOfTwo(log2)) { 1630 size_t chunkChars = BigInt::DigitBits >> mozilla::FloorLog2(log2); 1631 1632 size_t i = 0; 1633 RangedPtr<const CharT> to = end; 1634 while (to > start) { 1635 RangedPtr<const CharT> from = to - std::min(to - start, chunkChars); 1636 1637 Digit chunk = 0; 1638 if (!ParseLiteralDigit(Range{from, to}, radix, &chunk)) { 1639 *haveParseError = true; 1640 return nullptr; 1641 } 1642 1643 result->setDigit(i++, chunk); 1644 to = from; 1645 } 1646 MOZ_ASSERT(i == length, "unexpected over allocation"); 1647 MOZ_ASSERT(result->digit(length - 1) > 0, "unexpected leading zero"); 1648 1649 return result; 1650 } 1651 1652 size_t chunkChars = toStringInfo[radix].maxExponentInDigit; 1653 Digit chunkMultiplier = toStringInfo[radix].maxPowerInDigit; 1654 1655 while (start < end) { 1656 RangedPtr<const CharT> limit = start + std::min(end - start, chunkChars); 1657 1658 Digit chunk = 0; 1659 if (!ParseLiteralDigit(Range{start, limit}, radix, &chunk)) { 1660 *haveParseError = true; 1661 return nullptr; 1662 } 1663 1664 BigInt::Digit multiplier = chunkMultiplier; 1665 if ((limit - start) < chunkChars) { 1666 multiplier = PowerOf(radix, limit - start); 1667 MOZ_ASSERT(multiplier < chunkMultiplier); 1668 } 1669 result->inplaceMultiplyAdd(multiplier, chunk); 1670 start = limit; 1671 } 1672 1673 return destructivelyTrimHighZeroDigits(cx, result); 1674 } 1675 1676 // BigInt proposal section 7.2 1677 template <typename CharT> 1678 BigInt* BigInt::parseLiteral(JSContext* cx, Range<const CharT> chars, 1679 bool* haveParseError, js::gc::Heap heap) { 1680 RangedPtr<const CharT> start = chars.begin(); 1681 const RangedPtr<const CharT> end = chars.end(); 1682 bool isNegative = false; 1683 1684 MOZ_ASSERT(chars.length()); 1685 1686 if (end - start > 2 && start[0] == '0') { 1687 if (start[1] == 'b' || start[1] == 'B') { 1688 // StringNumericLiteral ::: BinaryIntegerLiteral 1689 return parseLiteralDigits(cx, Range<const CharT>(start + 2, end), 2, 1690 isNegative, haveParseError, heap); 1691 } 1692 if (start[1] == 'x' || start[1] == 'X') { 1693 // StringNumericLiteral ::: HexIntegerLiteral 1694 return parseLiteralDigits(cx, Range<const CharT>(start + 2, end), 16, 1695 isNegative, haveParseError, heap); 1696 } 1697 if (start[1] == 'o' || start[1] == 'O') { 1698 // StringNumericLiteral ::: OctalIntegerLiteral 1699 return parseLiteralDigits(cx, Range<const CharT>(start + 2, end), 8, 1700 isNegative, haveParseError, heap); 1701 } 1702 } 1703 1704 return parseLiteralDigits(cx, Range<const CharT>(start, end), 10, isNegative, 1705 haveParseError, heap); 1706 } 1707 1708 BigInt* BigInt::createFromDouble(JSContext* cx, double d) { 1709 MOZ_ASSERT(IsInteger(d), "Only integer-valued doubles can convert to BigInt"); 1710 1711 if (d == 0) { 1712 return zero(cx); 1713 } 1714 1715 int exponent = mozilla::ExponentComponent(d); 1716 MOZ_ASSERT(exponent >= 0); 1717 int length = exponent / DigitBits + 1; 1718 BigInt* result = createUninitialized(cx, length, d < 0); 1719 if (!result) { 1720 return nullptr; 1721 } 1722 1723 // We construct a BigInt from the double `d` by shifting its mantissa 1724 // according to its exponent and mapping the bit pattern onto digits. 1725 // 1726 // <----------- bitlength = exponent + 1 -----------> 1727 // <----- 52 ------> <------ trailing zeroes ------> 1728 // mantissa: 1yyyyyyyyyyyyyyyyy 0000000000000000000000000000000 1729 // digits: 0001xxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 1730 // <--> <------> 1731 // msdTopBits DigitBits 1732 // 1733 using Double = mozilla::FloatingPoint<double>; 1734 uint64_t mantissa = 1735 mozilla::BitwiseCast<uint64_t>(d) & Double::kSignificandBits; 1736 // Add implicit high bit. 1737 mantissa |= 1ull << Double::kSignificandWidth; 1738 1739 const int mantissaTopBit = Double::kSignificandWidth; // 0-indexed. 1740 1741 // 0-indexed position of `d`'s most significant bit within the `msd`. 1742 int msdTopBit = exponent % DigitBits; 1743 1744 // Next digit under construction. 1745 Digit digit; 1746 1747 // First, build the MSD by shifting the mantissa appropriately. 1748 if (msdTopBit < mantissaTopBit) { 1749 int remainingMantissaBits = mantissaTopBit - msdTopBit; 1750 digit = mantissa >> remainingMantissaBits; 1751 mantissa = mantissa << (64 - remainingMantissaBits); 1752 } else { 1753 MOZ_ASSERT(msdTopBit >= mantissaTopBit); 1754 digit = mantissa << (msdTopBit - mantissaTopBit); 1755 mantissa = 0; 1756 } 1757 MOZ_ASSERT(digit != 0, "most significant digit should not be zero"); 1758 result->setDigit(--length, digit); 1759 1760 // Fill in digits containing mantissa contributions. 1761 while (mantissa) { 1762 MOZ_ASSERT(length > 0, 1763 "double bits were all non-fractional, so there must be " 1764 "digits present to hold them"); 1765 1766 if (DigitBits == 64) { 1767 result->setDigit(--length, mantissa); 1768 break; 1769 } 1770 1771 MOZ_ASSERT(DigitBits == 32); 1772 Digit current = mantissa >> 32; 1773 mantissa = mantissa << 32; 1774 result->setDigit(--length, current); 1775 } 1776 1777 // Fill in low-order zeroes. 1778 for (int i = length - 1; i >= 0; i--) { 1779 result->setDigit(i, 0); 1780 } 1781 1782 return result; 1783 } 1784 1785 BigInt* BigInt::createFromUint64(JSContext* cx, uint64_t n, gc::Heap heap) { 1786 if (n == 0) { 1787 return zero(cx, heap); 1788 } 1789 1790 const bool isNegative = false; 1791 1792 if (DigitBits == 32) { 1793 Digit low = n; 1794 Digit high = n >> 32; 1795 size_t length = high ? 2 : 1; 1796 1797 BigInt* res = createUninitialized(cx, length, isNegative, heap); 1798 if (!res) { 1799 return nullptr; 1800 } 1801 res->setDigit(0, low); 1802 if (high) { 1803 res->setDigit(1, high); 1804 } 1805 return res; 1806 } 1807 1808 return createFromDigit(cx, n, isNegative, heap); 1809 } 1810 1811 BigInt* BigInt::createFromInt64(JSContext* cx, int64_t n, gc::Heap heap) { 1812 BigInt* res = createFromUint64(cx, Abs(n), heap); 1813 if (!res) { 1814 return nullptr; 1815 } 1816 1817 if (n < 0) { 1818 res->setHeaderFlagBit(SignBit); 1819 } 1820 MOZ_ASSERT(res->isNegative() == (n < 0)); 1821 1822 return res; 1823 } 1824 1825 BigInt* BigInt::createFromIntPtr(JSContext* cx, intptr_t n) { 1826 static_assert(sizeof(intptr_t) == sizeof(BigInt::Digit)); 1827 1828 if (n == 0) { 1829 return BigInt::zero(cx); 1830 } 1831 return BigInt::createFromDigit(cx, BigInt::Digit(Abs(n)), n < 0); 1832 } 1833 1834 // BigInt proposal section 5.1.2 1835 BigInt* js::NumberToBigInt(JSContext* cx, double d) { 1836 // Step 1 is an assertion checked by the caller. 1837 // Step 2. 1838 if (!IsInteger(d)) { 1839 ToCStringBuf cbuf; 1840 const char* str = NumberToCString(&cbuf, d); 1841 MOZ_ASSERT(str); 1842 1843 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 1844 JSMSG_NONINTEGER_NUMBER_TO_BIGINT, str); 1845 return nullptr; 1846 } 1847 1848 // Step 3. 1849 return BigInt::createFromDouble(cx, d); 1850 } 1851 1852 BigInt* BigInt::copy(JSContext* cx, HandleBigInt x, gc::Heap heap) { 1853 if (x->isZero()) { 1854 return zero(cx, heap); 1855 } 1856 1857 BigInt* result = 1858 createUninitialized(cx, x->digitLength(), x->isNegative(), heap); 1859 if (!result) { 1860 return nullptr; 1861 } 1862 for (size_t i = 0; i < x->digitLength(); i++) { 1863 result->setDigit(i, x->digit(i)); 1864 } 1865 return result; 1866 } 1867 1868 // BigInt proposal section 1.1.7 1869 BigInt* BigInt::add(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1870 bool xNegative = x->isNegative(); 1871 1872 // x + y == x + y 1873 // -x + -y == -(x + y) 1874 if (xNegative == y->isNegative()) { 1875 return absoluteAdd(cx, x, y, xNegative); 1876 } 1877 1878 // x + -y == x - y == -(y - x) 1879 // -x + y == y - x == -(x - y) 1880 int8_t compare = absoluteCompare(x, y); 1881 if (compare == 0) { 1882 return zero(cx); 1883 } 1884 1885 if (compare > 0) { 1886 return absoluteSub(cx, x, y, xNegative); 1887 } 1888 1889 return absoluteSub(cx, y, x, !xNegative); 1890 } 1891 1892 // BigInt proposal section 1.1.8 1893 BigInt* BigInt::sub(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1894 bool xNegative = x->isNegative(); 1895 if (xNegative != y->isNegative()) { 1896 // x - (-y) == x + y 1897 // (-x) - y == -(x + y) 1898 return absoluteAdd(cx, x, y, xNegative); 1899 } 1900 1901 // x - y == -(y - x) 1902 // (-x) - (-y) == y - x == -(x - y) 1903 int8_t compare = absoluteCompare(x, y); 1904 if (compare == 0) { 1905 return zero(cx); 1906 } 1907 1908 if (compare > 0) { 1909 return absoluteSub(cx, x, y, xNegative); 1910 } 1911 1912 return absoluteSub(cx, y, x, !xNegative); 1913 } 1914 1915 // BigInt proposal section 1.1.4 1916 BigInt* BigInt::mul(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1917 if (x->isZero()) { 1918 return x; 1919 } 1920 if (y->isZero()) { 1921 return y; 1922 } 1923 1924 bool resultNegative = x->isNegative() != y->isNegative(); 1925 1926 // Fast path for the likely-common case of up to a uint64_t of magnitude. 1927 if (x->absFitsInUint64() && y->absFitsInUint64()) { 1928 uint64_t lhs = x->uint64FromAbsNonZero(); 1929 uint64_t rhs = y->uint64FromAbsNonZero(); 1930 1931 uint64_t res; 1932 if (mozilla::SafeMul(lhs, rhs, &res)) { 1933 MOZ_ASSERT(res != 0); 1934 return createFromNonZeroRawUint64(cx, res, resultNegative); 1935 } 1936 } 1937 1938 unsigned resultLength = x->digitLength() + y->digitLength(); 1939 BigInt* result = createUninitialized(cx, resultLength, resultNegative); 1940 if (!result) { 1941 return nullptr; 1942 } 1943 result->initializeDigitsToZero(); 1944 1945 // Reorder operands to minimize calls to multiplyAccumulate. 1946 BigInt* left = x; 1947 BigInt* right = y; 1948 if (left->digitLength() < right->digitLength()) { 1949 std::swap(left, right); 1950 } 1951 1952 for (size_t i = 0; i < right->digitLength(); i++) { 1953 multiplyAccumulate(left, right->digit(i), result, i); 1954 } 1955 1956 return destructivelyTrimHighZeroDigits(cx, result); 1957 } 1958 1959 // BigInt proposal section 1.1.5 1960 BigInt* BigInt::div(JSContext* cx, HandleBigInt x, HandleBigInt y) { 1961 // 1. If y is 0n, throw a RangeError exception. 1962 if (y->isZero()) { 1963 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 1964 JSMSG_BIGINT_DIVISION_BY_ZERO); 1965 return nullptr; 1966 } 1967 1968 // 2. Let quotient be the mathematical value of x divided by y. 1969 // 3. Return a BigInt representing quotient rounded towards 0 to the next 1970 // integral value. 1971 if (x->isZero()) { 1972 return x; 1973 } 1974 1975 if (absoluteCompare(x, y) < 0) { 1976 return zero(cx); 1977 } 1978 1979 RootedBigInt quotient(cx); 1980 bool resultNegative = x->isNegative() != y->isNegative(); 1981 if (y->digitLength() == 1) { 1982 Digit divisor = y->digit(0); 1983 if (divisor == 1) { 1984 return resultNegative == x->isNegative() ? x : neg(cx, x); 1985 } 1986 1987 Digit remainder; 1988 if (!absoluteDivWithDigitDivisor(cx, x, divisor, Some("ient), 1989 &remainder, resultNegative)) { 1990 return nullptr; 1991 } 1992 } else { 1993 if (!absoluteDivWithBigIntDivisor(cx, x, y, Some("ient), Nothing(), 1994 resultNegative)) { 1995 return nullptr; 1996 } 1997 } 1998 1999 return destructivelyTrimHighZeroDigits(cx, quotient); 2000 } 2001 2002 // BigInt proposal section 1.1.6 2003 BigInt* BigInt::mod(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2004 // 1. If y is 0n, throw a RangeError exception. 2005 if (y->isZero()) { 2006 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 2007 JSMSG_BIGINT_DIVISION_BY_ZERO); 2008 return nullptr; 2009 } 2010 2011 // 2. If x is 0n, return x. 2012 if (x->isZero()) { 2013 return x; 2014 } 2015 // 3. Let r be the BigInt defined by the mathematical relation r = x - (y × 2016 // q) where q is a BigInt that is negative only if x/y is negative and 2017 // positive only if x/y is positive, and whose magnitude is as large as 2018 // possible without exceeding the magnitude of the true mathematical 2019 // quotient of x and y. 2020 if (absoluteCompare(x, y) < 0) { 2021 return x; 2022 } 2023 2024 if (y->digitLength() == 1) { 2025 Digit divisor = y->digit(0); 2026 if (divisor == 1) { 2027 return zero(cx); 2028 } 2029 2030 Digit remainderDigit; 2031 bool unusedQuotientNegative = false; 2032 if (!absoluteDivWithDigitDivisor(cx, x, divisor, Nothing(), &remainderDigit, 2033 unusedQuotientNegative)) { 2034 MOZ_CRASH("BigInt div by digit failed unexpectedly"); 2035 } 2036 2037 if (!remainderDigit) { 2038 return zero(cx); 2039 } 2040 2041 return createFromDigit(cx, remainderDigit, x->isNegative()); 2042 } else { 2043 RootedBigInt remainder(cx); 2044 if (!absoluteDivWithBigIntDivisor(cx, x, y, Nothing(), Some(&remainder), 2045 x->isNegative())) { 2046 return nullptr; 2047 } 2048 MOZ_ASSERT(remainder); 2049 return destructivelyTrimHighZeroDigits(cx, remainder); 2050 } 2051 } 2052 2053 bool BigInt::divmod(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y, 2054 MutableHandle<BigInt*> quotient, 2055 MutableHandle<BigInt*> remainder) { 2056 // 1. If y is 0n, throw a RangeError exception. 2057 if (y->isZero()) { 2058 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 2059 JSMSG_BIGINT_DIVISION_BY_ZERO); 2060 return false; 2061 } 2062 2063 // 2. If x is 0n, quotient and remainder are zero, too. 2064 if (x->isZero()) { 2065 quotient.set(x); 2066 remainder.set(x); 2067 return true; 2068 } 2069 2070 // 3. Let r be the BigInt defined by the mathematical relation r = x - (y × 2071 // q) where q is a BigInt that is negative only if x/y is negative and 2072 // positive only if x/y is positive, and whose magnitude is as large as 2073 // possible without exceeding the magnitude of the true mathematical 2074 // quotient of x and y. 2075 if (absoluteCompare(x, y) < 0) { 2076 auto* zero = BigInt::zero(cx); 2077 if (!zero) { 2078 return false; 2079 } 2080 2081 quotient.set(zero); 2082 remainder.set(x); 2083 return true; 2084 } 2085 2086 bool resultNegative = x->isNegative() != y->isNegative(); 2087 2088 if (y->digitLength() == 1) { 2089 Digit divisor = y->digit(0); 2090 if (divisor == 1) { 2091 quotient.set(resultNegative == x->isNegative() ? x : neg(cx, x)); 2092 if (!quotient) { 2093 return false; 2094 } 2095 2096 remainder.set(BigInt::zero(cx)); 2097 if (!remainder) { 2098 return false; 2099 } 2100 } else { 2101 Rooted<BigInt*> quot(cx); 2102 Digit remainderDigit; 2103 if (!absoluteDivWithDigitDivisor(cx, x, divisor, Some("), 2104 &remainderDigit, resultNegative)) { 2105 return false; 2106 } 2107 2108 quotient.set(destructivelyTrimHighZeroDigits(cx, quot)); 2109 if (!quotient) { 2110 return false; 2111 } 2112 2113 if (!remainderDigit) { 2114 remainder.set(zero(cx)); 2115 } else { 2116 remainder.set(createFromDigit(cx, remainderDigit, x->isNegative())); 2117 } 2118 if (!remainder) { 2119 return false; 2120 } 2121 } 2122 } else { 2123 RootedBigInt quot(cx); 2124 RootedBigInt rem(cx); 2125 if (!absoluteDivWithBigIntDivisor(cx, x, y, Some("), Some(&rem), 2126 resultNegative)) { 2127 return false; 2128 } 2129 2130 quotient.set(destructivelyTrimHighZeroDigits(cx, quot)); 2131 if (!quotient) { 2132 return false; 2133 } 2134 2135 remainder.set(destructivelyTrimHighZeroDigits(cx, rem)); 2136 if (!remainder) { 2137 return false; 2138 } 2139 } 2140 2141 MOZ_ASSERT(quotient && remainder, 2142 "quotient and remainder are computed on return"); 2143 MOZ_ASSERT(!quotient->isZero(), "zero quotient is handled earlier"); 2144 MOZ_ASSERT(quotient->isNegative() == resultNegative, 2145 "quotient has the correct sign"); 2146 MOZ_ASSERT( 2147 remainder->isZero() || (x->isNegative() == remainder->isNegative()), 2148 "remainder has the correct sign"); 2149 2150 return true; 2151 } 2152 2153 // BigInt proposal section 1.1.3 2154 BigInt* BigInt::pow(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2155 // 1. If exponent is < 0, throw a RangeError exception. 2156 if (y->isNegative()) { 2157 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 2158 JSMSG_BIGINT_NEGATIVE_EXPONENT); 2159 return nullptr; 2160 } 2161 2162 // 2. If base is 0n and exponent is 0n, return 1n. 2163 if (y->isZero()) { 2164 return one(cx); 2165 } 2166 2167 if (x->isZero()) { 2168 return x; 2169 } 2170 2171 // 3. Return a BigInt representing the mathematical value of base raised 2172 // to the power exponent. 2173 if (x->digitLength() == 1 && x->digit(0) == 1) { 2174 // (-1) ** even_number == 1. 2175 if (x->isNegative() && (y->digit(0) & 1) == 0) { 2176 return neg(cx, x); 2177 } 2178 // (-1) ** odd_number == -1; 1 ** anything == 1. 2179 return x; 2180 } 2181 2182 // For all bases >= 2, very large exponents would lead to unrepresentable 2183 // results. 2184 static_assert(MaxBitLength < std::numeric_limits<Digit>::max(), 2185 "unexpectedly large MaxBitLength"); 2186 if (y->digitLength() > 1) { 2187 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 2188 return nullptr; 2189 } 2190 Digit exponent = y->digit(0); 2191 if (exponent == 1) { 2192 return x; 2193 } 2194 if (exponent >= MaxBitLength) { 2195 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 2196 return nullptr; 2197 } 2198 2199 static_assert( 2200 MaxBitLength <= static_cast<unsigned>(std::numeric_limits<int>::max()), 2201 "unexpectedly large MaxBitLength"); 2202 int n = static_cast<int>(exponent); 2203 bool isOddPower = n & 1; 2204 2205 if (x->digitLength() == 1 && mozilla::IsPowerOfTwo(x->digit(0))) { 2206 // Fast path for (2^m)^n. 2207 2208 // Result is negative for odd powers. 2209 bool resultNegative = x->isNegative() && isOddPower; 2210 2211 unsigned m = mozilla::FloorLog2(x->digit(0)); 2212 MOZ_ASSERT(m < DigitBits); 2213 2214 static_assert(MaxBitLength * DigitBits > MaxBitLength, 2215 "n * m can't overflow"); 2216 n *= int(m); 2217 2218 int length = 1 + (n / DigitBits); 2219 BigInt* result = createUninitialized(cx, length, resultNegative); 2220 if (!result) { 2221 return nullptr; 2222 } 2223 result->initializeDigitsToZero(); 2224 result->setDigit(length - 1, static_cast<Digit>(1) << (n % DigitBits)); 2225 return result; 2226 } 2227 2228 RootedBigInt runningSquare(cx, x); 2229 RootedBigInt result(cx, isOddPower ? x : nullptr); 2230 n /= 2; 2231 2232 // Fast path for the likely-common case of up to a uint64_t of magnitude. 2233 if (x->absFitsInUint64()) { 2234 bool resultNegative = x->isNegative() && isOddPower; 2235 2236 uint64_t runningSquareInt = x->uint64FromAbsNonZero(); 2237 uint64_t resultInt = isOddPower ? runningSquareInt : 1; 2238 while (true) { 2239 uint64_t runningSquareStart = runningSquareInt; 2240 uint64_t r; 2241 if (!mozilla::SafeMul(runningSquareInt, runningSquareInt, &r)) { 2242 break; 2243 } 2244 runningSquareInt = r; 2245 2246 if (n & 1) { 2247 if (!mozilla::SafeMul(resultInt, runningSquareInt, &r)) { 2248 // Recover |runningSquare| before we restart the loop. 2249 runningSquareInt = runningSquareStart; 2250 break; 2251 } 2252 resultInt = r; 2253 } 2254 2255 n /= 2; 2256 if (n == 0) { 2257 return createFromNonZeroRawUint64(cx, resultInt, resultNegative); 2258 } 2259 } 2260 2261 runningSquare = createFromNonZeroRawUint64(cx, runningSquareInt, false); 2262 if (!runningSquare) { 2263 return nullptr; 2264 } 2265 2266 result = createFromNonZeroRawUint64(cx, resultInt, resultNegative); 2267 if (!result) { 2268 return nullptr; 2269 } 2270 } 2271 2272 // This implicitly sets the result's sign correctly. 2273 while (true) { 2274 runningSquare = mul(cx, runningSquare, runningSquare); 2275 if (!runningSquare) { 2276 return nullptr; 2277 } 2278 2279 if (n & 1) { 2280 if (!result) { 2281 result = runningSquare; 2282 } else { 2283 result = mul(cx, result, runningSquare); 2284 if (!result) { 2285 return nullptr; 2286 } 2287 } 2288 } 2289 2290 n /= 2; 2291 if (n == 0) { 2292 return result; 2293 } 2294 } 2295 } 2296 2297 bool BigInt::powIntPtr(intptr_t x, intptr_t y, intptr_t* result) { 2298 if (y < 0) { 2299 return false; 2300 } 2301 uintptr_t n = uintptr_t(y); 2302 2303 // x^y where x == 1 returns 1 for any y. 2304 if (x == 1) { 2305 *result = 1; 2306 return true; 2307 } 2308 2309 // x^y where x == -1 returns 1 for even y, and -1 for odd y. 2310 if (x == -1) { 2311 *result = (y & 1) ? -1 : 1; 2312 return true; 2313 } 2314 2315 using CheckedIntPtr = mozilla::CheckedInt<intptr_t>; 2316 2317 CheckedIntPtr runningSquare = x; 2318 CheckedIntPtr res = 1; 2319 while (true) { 2320 if ((n & 1) != 0) { 2321 res *= runningSquare; 2322 if (!res.isValid()) { 2323 return false; 2324 } 2325 } 2326 2327 n >>= 1; 2328 if (n == 0) { 2329 *result = res.value(); 2330 return true; 2331 } 2332 2333 runningSquare *= runningSquare; 2334 if (!runningSquare.isValid()) { 2335 return false; 2336 } 2337 } 2338 } 2339 2340 BigInt* BigInt::lshByAbsolute(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2341 if (x->isZero() || y->isZero()) { 2342 return x; 2343 } 2344 2345 if (y->digitLength() > 1 || y->digit(0) > MaxBitLength) { 2346 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 2347 if (js::SupportDifferentialTesting()) { 2348 fprintf(stderr, "ReportOutOfMemory called\n"); 2349 } 2350 return nullptr; 2351 } 2352 Digit shift = y->digit(0); 2353 int digitShift = static_cast<int>(shift / DigitBits); 2354 int bitsShift = static_cast<int>(shift % DigitBits); 2355 int length = x->digitLength(); 2356 bool grow = bitsShift && (x->digit(length - 1) >> (DigitBits - bitsShift)); 2357 int resultLength = length + digitShift + grow; 2358 BigInt* result = createUninitialized(cx, resultLength, x->isNegative()); 2359 if (!result) { 2360 return nullptr; 2361 } 2362 2363 int i = 0; 2364 for (; i < digitShift; i++) { 2365 result->setDigit(i, 0); 2366 } 2367 2368 if (bitsShift == 0) { 2369 for (int j = 0; i < resultLength; i++, j++) { 2370 result->setDigit(i, x->digit(j)); 2371 } 2372 } else { 2373 Digit carry = 0; 2374 for (int j = 0; j < length; i++, j++) { 2375 Digit d = x->digit(j); 2376 result->setDigit(i, (d << bitsShift) | carry); 2377 carry = d >> (DigitBits - bitsShift); 2378 } 2379 if (grow) { 2380 result->setDigit(i, carry); 2381 } else { 2382 MOZ_ASSERT(!carry); 2383 } 2384 } 2385 return result; 2386 } 2387 2388 BigInt* BigInt::rshByMaximum(JSContext* cx, bool isNegative) { 2389 return isNegative ? negativeOne(cx) : zero(cx); 2390 } 2391 2392 BigInt* BigInt::rshByAbsolute(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2393 if (x->isZero() || y->isZero()) { 2394 return x; 2395 } 2396 2397 if (y->digitLength() > 1 || y->digit(0) >= MaxBitLength) { 2398 return rshByMaximum(cx, x->isNegative()); 2399 } 2400 Digit shift = y->digit(0); 2401 int length = x->digitLength(); 2402 int digitShift = static_cast<int>(shift / DigitBits); 2403 int bitsShift = static_cast<int>(shift % DigitBits); 2404 int resultLength = length - digitShift; 2405 if (resultLength <= 0) { 2406 return rshByMaximum(cx, x->isNegative()); 2407 } 2408 // For negative numbers, round down if any bit was shifted out (so that e.g. 2409 // -5n >> 1n == -3n and not -2n). Check now whether this will happen and 2410 // whether it can cause overflow into a new digit. If we allocate the result 2411 // large enough up front, it avoids having to do a second allocation later. 2412 bool mustRoundDown = false; 2413 if (x->isNegative()) { 2414 const Digit mask = (static_cast<Digit>(1) << bitsShift) - 1; 2415 if ((x->digit(digitShift) & mask)) { 2416 mustRoundDown = true; 2417 } else { 2418 for (int i = 0; i < digitShift; i++) { 2419 if (x->digit(i)) { 2420 mustRoundDown = true; 2421 break; 2422 } 2423 } 2424 } 2425 } 2426 // If bits_shift is non-zero, it frees up bits, preventing overflow. 2427 if (mustRoundDown && bitsShift == 0) { 2428 // Overflow cannot happen if the most significant digit has unset bits. 2429 Digit msd = x->digit(length - 1); 2430 bool roundingCanOverflow = msd == std::numeric_limits<Digit>::max(); 2431 if (roundingCanOverflow) { 2432 resultLength++; 2433 } 2434 } 2435 2436 MOZ_ASSERT(resultLength <= length); 2437 RootedBigInt result(cx, 2438 createUninitialized(cx, resultLength, x->isNegative())); 2439 if (!result) { 2440 return nullptr; 2441 } 2442 if (!bitsShift) { 2443 // If roundingCanOverflow, manually initialize the overflow digit. 2444 result->setDigit(resultLength - 1, 0); 2445 for (int i = digitShift; i < length; i++) { 2446 result->setDigit(i - digitShift, x->digit(i)); 2447 } 2448 } else { 2449 Digit carry = x->digit(digitShift) >> bitsShift; 2450 int last = length - digitShift - 1; 2451 for (int i = 0; i < last; i++) { 2452 Digit d = x->digit(i + digitShift + 1); 2453 result->setDigit(i, (d << (DigitBits - bitsShift)) | carry); 2454 carry = d >> bitsShift; 2455 } 2456 result->setDigit(last, carry); 2457 } 2458 2459 if (mustRoundDown) { 2460 MOZ_ASSERT(x->isNegative()); 2461 // Since the result is negative, rounding down means adding one to 2462 // its absolute value. This cannot overflow. TODO: modify the result in 2463 // place. 2464 return absoluteAddOne(cx, result, x->isNegative()); 2465 } 2466 return destructivelyTrimHighZeroDigits(cx, result); 2467 } 2468 2469 // BigInt proposal section 1.1.9. BigInt::leftShift ( x, y ) 2470 BigInt* BigInt::lsh(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2471 if (y->isNegative()) { 2472 return rshByAbsolute(cx, x, y); 2473 } 2474 return lshByAbsolute(cx, x, y); 2475 } 2476 2477 // BigInt proposal section 1.1.10. BigInt::signedRightShift ( x, y ) 2478 BigInt* BigInt::rsh(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2479 if (y->isNegative()) { 2480 return lshByAbsolute(cx, x, y); 2481 } 2482 return rshByAbsolute(cx, x, y); 2483 } 2484 2485 // BigInt proposal section 1.1.17. BigInt::bitwiseAND ( x, y ) 2486 BigInt* BigInt::bitAnd(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2487 if (x->isZero()) { 2488 return x; 2489 } 2490 2491 if (y->isZero()) { 2492 return y; 2493 } 2494 2495 if (!x->isNegative() && !y->isNegative()) { 2496 return absoluteAnd(cx, x, y); 2497 } 2498 2499 if (x->isNegative() && y->isNegative()) { 2500 // (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) 2501 // == -(((x-1) | (y-1)) + 1) 2502 RootedBigInt x1(cx, absoluteSubOne(cx, x)); 2503 if (!x1) { 2504 return nullptr; 2505 } 2506 RootedBigInt y1(cx, absoluteSubOne(cx, y)); 2507 if (!y1) { 2508 return nullptr; 2509 } 2510 RootedBigInt result(cx, absoluteOr(cx, x1, y1)); 2511 if (!result) { 2512 return nullptr; 2513 } 2514 bool resultNegative = true; 2515 return absoluteAddOne(cx, result, resultNegative); 2516 } 2517 2518 MOZ_ASSERT(x->isNegative() != y->isNegative()); 2519 HandleBigInt& pos = x->isNegative() ? y : x; 2520 HandleBigInt& neg = x->isNegative() ? x : y; 2521 2522 RootedBigInt neg1(cx, absoluteSubOne(cx, neg)); 2523 if (!neg1) { 2524 return nullptr; 2525 } 2526 2527 // x & (-y) == x & ~(y-1) == x & ~(y-1) 2528 return absoluteAndNot(cx, pos, neg1); 2529 } 2530 2531 // BigInt proposal section 1.1.18. BigInt::bitwiseXOR ( x, y ) 2532 BigInt* BigInt::bitXor(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2533 if (x->isZero()) { 2534 return y; 2535 } 2536 2537 if (y->isZero()) { 2538 return x; 2539 } 2540 2541 if (!x->isNegative() && !y->isNegative()) { 2542 return absoluteXor(cx, x, y); 2543 } 2544 2545 if (x->isNegative() && y->isNegative()) { 2546 // (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1) 2547 RootedBigInt x1(cx, absoluteSubOne(cx, x)); 2548 if (!x1) { 2549 return nullptr; 2550 } 2551 RootedBigInt y1(cx, absoluteSubOne(cx, y)); 2552 if (!y1) { 2553 return nullptr; 2554 } 2555 return absoluteXor(cx, x1, y1); 2556 } 2557 MOZ_ASSERT(x->isNegative() != y->isNegative()); 2558 2559 HandleBigInt& pos = x->isNegative() ? y : x; 2560 HandleBigInt& neg = x->isNegative() ? x : y; 2561 2562 // x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1) 2563 RootedBigInt result(cx, absoluteSubOne(cx, neg)); 2564 if (!result) { 2565 return nullptr; 2566 } 2567 result = absoluteXor(cx, result, pos); 2568 if (!result) { 2569 return nullptr; 2570 } 2571 bool resultNegative = true; 2572 return absoluteAddOne(cx, result, resultNegative); 2573 } 2574 2575 // BigInt proposal section 1.1.19. BigInt::bitwiseOR ( x, y ) 2576 BigInt* BigInt::bitOr(JSContext* cx, HandleBigInt x, HandleBigInt y) { 2577 if (x->isZero()) { 2578 return y; 2579 } 2580 2581 if (y->isZero()) { 2582 return x; 2583 } 2584 2585 bool resultNegative = x->isNegative() || y->isNegative(); 2586 2587 if (!resultNegative) { 2588 return absoluteOr(cx, x, y); 2589 } 2590 2591 if (x->isNegative() && y->isNegative()) { 2592 // (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) 2593 // == -(((x-1) & (y-1)) + 1) 2594 RootedBigInt result(cx, absoluteSubOne(cx, x)); 2595 if (!result) { 2596 return nullptr; 2597 } 2598 RootedBigInt y1(cx, absoluteSubOne(cx, y)); 2599 if (!y1) { 2600 return nullptr; 2601 } 2602 result = absoluteAnd(cx, result, y1); 2603 if (!result) { 2604 return nullptr; 2605 } 2606 return absoluteAddOne(cx, result, resultNegative); 2607 } 2608 2609 MOZ_ASSERT(x->isNegative() != y->isNegative()); 2610 HandleBigInt& pos = x->isNegative() ? y : x; 2611 HandleBigInt& neg = x->isNegative() ? x : y; 2612 2613 // x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1) 2614 RootedBigInt result(cx, absoluteSubOne(cx, neg)); 2615 if (!result) { 2616 return nullptr; 2617 } 2618 result = absoluteAndNot(cx, result, pos); 2619 if (!result) { 2620 return nullptr; 2621 } 2622 return absoluteAddOne(cx, result, resultNegative); 2623 } 2624 2625 // BigInt proposal section 1.1.2. BigInt::bitwiseNOT ( x ) 2626 BigInt* BigInt::bitNot(JSContext* cx, HandleBigInt x) { 2627 if (x->isNegative()) { 2628 // ~(-x) == ~(~(x-1)) == x-1 2629 return absoluteSubOne(cx, x); 2630 } else { 2631 // ~x == -x-1 == -(x+1) 2632 bool resultNegative = true; 2633 return absoluteAddOne(cx, x, resultNegative); 2634 } 2635 } 2636 2637 int64_t BigInt::toInt64(const BigInt* x) { return WrapToSigned(toUint64(x)); } 2638 2639 uint64_t BigInt::toUint64(const BigInt* x) { 2640 if (x->isZero()) { 2641 return 0; 2642 } 2643 2644 uint64_t digit = x->uint64FromAbsNonZero(); 2645 2646 // Return the two's complement if x is negative. 2647 if (x->isNegative()) { 2648 return ~(digit - 1); 2649 } 2650 2651 return digit; 2652 } 2653 2654 bool BigInt::isInt32(const BigInt* x, int32_t* result) { 2655 MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result)); 2656 2657 int64_t r; 2658 if (!BigInt::isInt64(x, &r)) { 2659 return false; 2660 } 2661 2662 if (std::numeric_limits<int32_t>::min() <= r && 2663 r <= std::numeric_limits<int32_t>::max()) { 2664 *result = AssertedCast<int32_t>(r); 2665 return true; 2666 } 2667 return false; 2668 } 2669 2670 bool BigInt::isInt64(const BigInt* x, int64_t* result) { 2671 MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result)); 2672 2673 if (!x->absFitsInUint64()) { 2674 return false; 2675 } 2676 2677 if (x->isZero()) { 2678 *result = 0; 2679 return true; 2680 } 2681 2682 uint64_t magnitude = x->uint64FromAbsNonZero(); 2683 2684 if (x->isNegative()) { 2685 constexpr uint64_t Int64MinMagnitude = uint64_t(1) << 63; 2686 if (magnitude <= Int64MinMagnitude) { 2687 *result = magnitude == Int64MinMagnitude 2688 ? std::numeric_limits<int64_t>::min() 2689 : -AssertedCast<int64_t>(magnitude); 2690 return true; 2691 } 2692 } else { 2693 if (magnitude <= 2694 static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { 2695 *result = AssertedCast<int64_t>(magnitude); 2696 return true; 2697 } 2698 } 2699 2700 return false; 2701 } 2702 2703 bool BigInt::isUint64(const BigInt* x, uint64_t* result) { 2704 MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result)); 2705 2706 if (!x->absFitsInUint64() || x->isNegative()) { 2707 return false; 2708 } 2709 2710 if (x->isZero()) { 2711 *result = 0; 2712 return true; 2713 } 2714 2715 *result = x->uint64FromAbsNonZero(); 2716 return true; 2717 } 2718 2719 bool BigInt::isIntPtr(const BigInt* x, intptr_t* result) { 2720 MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result)); 2721 2722 static_assert(sizeof(intptr_t) == sizeof(BigInt::Digit)); 2723 2724 if (x->digitLength() > 1) { 2725 return false; 2726 } 2727 2728 if (x->isZero()) { 2729 *result = 0; 2730 return true; 2731 } 2732 2733 uintptr_t magnitude = x->digit(0); 2734 2735 if (x->isNegative()) { 2736 constexpr uintptr_t IntPtrMinMagnitude = uintptr_t(1) << (DigitBits - 1); 2737 if (magnitude <= IntPtrMinMagnitude) { 2738 *result = magnitude == IntPtrMinMagnitude 2739 ? std::numeric_limits<intptr_t>::min() 2740 : -AssertedCast<intptr_t>(magnitude); 2741 return true; 2742 } 2743 } else { 2744 if (magnitude <= 2745 static_cast<uintptr_t>(std::numeric_limits<intptr_t>::max())) { 2746 *result = AssertedCast<intptr_t>(magnitude); 2747 return true; 2748 } 2749 } 2750 2751 return false; 2752 } 2753 2754 bool BigInt::isNumber(const BigInt* x, double* result) { 2755 MOZ_MAKE_MEM_UNDEFINED(result, sizeof(*result)); 2756 2757 if (!x->absFitsInUint64()) { 2758 return false; 2759 } 2760 2761 if (x->isZero()) { 2762 *result = 0; 2763 return true; 2764 } 2765 2766 uint64_t magnitude = x->uint64FromAbsNonZero(); 2767 if (magnitude < uint64_t(DOUBLE_INTEGRAL_PRECISION_LIMIT)) { 2768 *result = x->isNegative() ? -double(magnitude) : double(magnitude); 2769 return true; 2770 } 2771 2772 return false; 2773 } 2774 2775 // Compute `2**bits - (x & (2**bits - 1))`. Used when treating BigInt values as 2776 // arbitrary-precision two's complement signed integers. 2777 BigInt* BigInt::truncateAndSubFromPowerOfTwo(JSContext* cx, HandleBigInt x, 2778 uint64_t bits, 2779 bool resultNegative) { 2780 MOZ_ASSERT(bits != 0); 2781 MOZ_ASSERT(!x->isZero()); 2782 2783 if (bits > MaxBitLength) { 2784 ReportOversizedAllocation(cx, JSMSG_BIGINT_TOO_LARGE); 2785 return nullptr; 2786 } 2787 2788 size_t resultLength = CeilDiv(bits, DigitBits); 2789 BigInt* result = createUninitialized(cx, resultLength, resultNegative); 2790 if (!result) { 2791 return nullptr; 2792 } 2793 2794 // Process all digits except the MSD. 2795 size_t xLength = x->digitLength(); 2796 Digit borrow = 0; 2797 // Take digits from `x` until its length is exhausted. 2798 for (size_t i = 0; i < std::min(resultLength - 1, xLength); i++) { 2799 Digit newBorrow = 0; 2800 Digit difference = digitSub(0, x->digit(i), &newBorrow); 2801 difference = digitSub(difference, borrow, &newBorrow); 2802 result->setDigit(i, difference); 2803 borrow = newBorrow; 2804 } 2805 // Then simulate leading zeroes in `x` as needed. 2806 for (size_t i = xLength; i < resultLength - 1; i++) { 2807 Digit newBorrow = 0; 2808 Digit difference = digitSub(0, borrow, &newBorrow); 2809 result->setDigit(i, difference); 2810 borrow = newBorrow; 2811 } 2812 2813 // The MSD might contain extra bits that we don't want. 2814 Digit xMSD = resultLength <= xLength ? x->digit(resultLength - 1) : 0; 2815 Digit resultMSD; 2816 if (bits % DigitBits == 0) { 2817 Digit newBorrow = 0; 2818 resultMSD = digitSub(0, xMSD, &newBorrow); 2819 resultMSD = digitSub(resultMSD, borrow, &newBorrow); 2820 } else { 2821 size_t drop = DigitBits - (bits % DigitBits); 2822 xMSD = (xMSD << drop) >> drop; 2823 Digit minuendMSD = Digit(1) << (DigitBits - drop); 2824 Digit newBorrow = 0; 2825 resultMSD = digitSub(minuendMSD, xMSD, &newBorrow); 2826 resultMSD = digitSub(resultMSD, borrow, &newBorrow); 2827 MOZ_ASSERT(newBorrow == 0, "result < 2^bits"); 2828 // If all subtracted bits were zero, we have to get rid of the 2829 // materialized minuendMSD again. 2830 resultMSD &= (minuendMSD - 1); 2831 } 2832 result->setDigit(resultLength - 1, resultMSD); 2833 2834 return destructivelyTrimHighZeroDigits(cx, result); 2835 } 2836 2837 BigInt* BigInt::asUintN(JSContext* cx, HandleBigInt x, uint64_t bits) { 2838 if (x->isZero()) { 2839 return x; 2840 } 2841 2842 if (bits == 0) { 2843 return zero(cx); 2844 } 2845 2846 // When truncating a negative number, simulate two's complement. 2847 if (x->isNegative()) { 2848 bool resultNegative = false; 2849 return truncateAndSubFromPowerOfTwo(cx, x, bits, resultNegative); 2850 } 2851 2852 if (bits <= 64) { 2853 uint64_t u64 = toUint64(x); 2854 uint64_t mask = uint64_t(-1) >> (64 - bits); 2855 uint64_t n = u64 & mask; 2856 if (u64 == n && x->absFitsInUint64()) { 2857 return x; 2858 } 2859 return createFromUint64(cx, n); 2860 } 2861 2862 if (bits >= MaxBitLength) { 2863 return x; 2864 } 2865 2866 Digit msd = x->digit(x->digitLength() - 1); 2867 size_t msdBits = DigitBits - DigitLeadingZeroes(msd); 2868 size_t bitLength = msdBits + (x->digitLength() - 1) * DigitBits; 2869 2870 if (bits >= bitLength) { 2871 return x; 2872 } 2873 2874 size_t length = CeilDiv(bits, DigitBits); 2875 MOZ_ASSERT(length >= 2, "single-digit cases should be handled above"); 2876 MOZ_ASSERT(length <= x->digitLength()); 2877 2878 // Eagerly trim high zero digits. 2879 const size_t highDigitBits = ((bits - 1) % DigitBits) + 1; 2880 const Digit highDigitMask = Digit(-1) >> (DigitBits - highDigitBits); 2881 Digit mask = highDigitMask; 2882 while (length > 0) { 2883 if (x->digit(length - 1) & mask) { 2884 break; 2885 } 2886 2887 mask = Digit(-1); 2888 length--; 2889 } 2890 2891 const bool isNegative = false; 2892 BigInt* res = createUninitialized(cx, length, isNegative); 2893 if (res == nullptr) { 2894 return nullptr; 2895 } 2896 2897 while (length-- > 0) { 2898 res->setDigit(length, x->digit(length) & mask); 2899 mask = Digit(-1); 2900 } 2901 MOZ_ASSERT_IF(length == 0, res->isZero()); 2902 2903 return res; 2904 } 2905 2906 BigInt* BigInt::asIntN(JSContext* cx, HandleBigInt x, uint64_t bits) { 2907 if (x->isZero()) { 2908 return x; 2909 } 2910 2911 if (bits == 0) { 2912 return zero(cx); 2913 } 2914 2915 if (bits == 64) { 2916 int64_t n = toInt64(x); 2917 if (((n < 0) == x->isNegative()) && x->absFitsInUint64()) { 2918 return x; 2919 } 2920 return createFromInt64(cx, n); 2921 } 2922 2923 if (bits > MaxBitLength) { 2924 return x; 2925 } 2926 2927 Digit msd = x->digit(x->digitLength() - 1); 2928 size_t msdBits = DigitBits - DigitLeadingZeroes(msd); 2929 size_t bitLength = msdBits + (x->digitLength() - 1) * DigitBits; 2930 2931 if (bits > bitLength) { 2932 return x; 2933 } 2934 2935 Digit signBit = Digit(1) << ((bits - 1) % DigitBits); 2936 if (bits == bitLength && msd < signBit) { 2937 return x; 2938 } 2939 2940 // All the cases above were the trivial cases: truncating zero, or to zero 2941 // bits, or to more bits than are in `x` (so we return `x` directly), or we 2942 // already have the 64-bit fast path. If we get here, follow the textbook 2943 // algorithm from the specification. 2944 2945 // BigInt.asIntN step 3: Let `mod` be `x` modulo `2**bits`. 2946 RootedBigInt mod(cx, asUintN(cx, x, bits)); 2947 if (!mod) { 2948 return nullptr; 2949 } 2950 2951 // Step 4: If `mod >= 2**(bits - 1)`, return `mod - 2**bits`; otherwise, 2952 // return `mod`. 2953 if (mod->digitLength() == CeilDiv(bits, DigitBits)) { 2954 MOZ_ASSERT(!mod->isZero(), 2955 "nonzero bits implies nonzero digit length which implies " 2956 "nonzero overall"); 2957 2958 if ((mod->digit(mod->digitLength() - 1) & signBit) != 0) { 2959 bool resultNegative = true; 2960 return truncateAndSubFromPowerOfTwo(cx, mod, bits, resultNegative); 2961 } 2962 } 2963 2964 return mod; 2965 } 2966 2967 static bool ValidBigIntOperands(JSContext* cx, HandleValue lhs, 2968 HandleValue rhs) { 2969 MOZ_ASSERT(lhs.isBigInt() || rhs.isBigInt()); 2970 2971 if (!lhs.isBigInt() || !rhs.isBigInt()) { 2972 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 2973 JSMSG_BIGINT_TO_NUMBER); 2974 return false; 2975 } 2976 2977 return true; 2978 } 2979 2980 bool BigInt::addValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 2981 MutableHandleValue res) { 2982 if (!ValidBigIntOperands(cx, lhs, rhs)) { 2983 return false; 2984 } 2985 2986 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 2987 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 2988 BigInt* resBigInt = BigInt::add(cx, lhsBigInt, rhsBigInt); 2989 if (!resBigInt) { 2990 return false; 2991 } 2992 res.setBigInt(resBigInt); 2993 return true; 2994 } 2995 2996 bool BigInt::subValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 2997 MutableHandleValue res) { 2998 if (!ValidBigIntOperands(cx, lhs, rhs)) { 2999 return false; 3000 } 3001 3002 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3003 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3004 BigInt* resBigInt = BigInt::sub(cx, lhsBigInt, rhsBigInt); 3005 if (!resBigInt) { 3006 return false; 3007 } 3008 res.setBigInt(resBigInt); 3009 return true; 3010 } 3011 3012 bool BigInt::mulValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3013 MutableHandleValue res) { 3014 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3015 return false; 3016 } 3017 3018 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3019 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3020 BigInt* resBigInt = BigInt::mul(cx, lhsBigInt, rhsBigInt); 3021 if (!resBigInt) { 3022 return false; 3023 } 3024 res.setBigInt(resBigInt); 3025 return true; 3026 } 3027 3028 bool BigInt::divValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3029 MutableHandleValue res) { 3030 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3031 return false; 3032 } 3033 3034 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3035 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3036 BigInt* resBigInt = BigInt::div(cx, lhsBigInt, rhsBigInt); 3037 if (!resBigInt) { 3038 return false; 3039 } 3040 res.setBigInt(resBigInt); 3041 return true; 3042 } 3043 3044 bool BigInt::modValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3045 MutableHandleValue res) { 3046 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3047 return false; 3048 } 3049 3050 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3051 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3052 BigInt* resBigInt = BigInt::mod(cx, lhsBigInt, rhsBigInt); 3053 if (!resBigInt) { 3054 return false; 3055 } 3056 res.setBigInt(resBigInt); 3057 return true; 3058 } 3059 3060 bool BigInt::powValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3061 MutableHandleValue res) { 3062 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3063 return false; 3064 } 3065 3066 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3067 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3068 BigInt* resBigInt = BigInt::pow(cx, lhsBigInt, rhsBigInt); 3069 if (!resBigInt) { 3070 return false; 3071 } 3072 res.setBigInt(resBigInt); 3073 return true; 3074 } 3075 3076 bool BigInt::negValue(JSContext* cx, HandleValue operand, 3077 MutableHandleValue res) { 3078 MOZ_ASSERT(operand.isBigInt()); 3079 3080 RootedBigInt operandBigInt(cx, operand.toBigInt()); 3081 BigInt* resBigInt = BigInt::neg(cx, operandBigInt); 3082 if (!resBigInt) { 3083 return false; 3084 } 3085 res.setBigInt(resBigInt); 3086 return true; 3087 } 3088 3089 bool BigInt::incValue(JSContext* cx, HandleValue operand, 3090 MutableHandleValue res) { 3091 MOZ_ASSERT(operand.isBigInt()); 3092 3093 RootedBigInt operandBigInt(cx, operand.toBigInt()); 3094 BigInt* resBigInt = BigInt::inc(cx, operandBigInt); 3095 if (!resBigInt) { 3096 return false; 3097 } 3098 res.setBigInt(resBigInt); 3099 return true; 3100 } 3101 3102 bool BigInt::decValue(JSContext* cx, HandleValue operand, 3103 MutableHandleValue res) { 3104 MOZ_ASSERT(operand.isBigInt()); 3105 3106 RootedBigInt operandBigInt(cx, operand.toBigInt()); 3107 BigInt* resBigInt = BigInt::dec(cx, operandBigInt); 3108 if (!resBigInt) { 3109 return false; 3110 } 3111 res.setBigInt(resBigInt); 3112 return true; 3113 } 3114 3115 bool BigInt::lshValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3116 MutableHandleValue res) { 3117 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3118 return false; 3119 } 3120 3121 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3122 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3123 BigInt* resBigInt = BigInt::lsh(cx, lhsBigInt, rhsBigInt); 3124 if (!resBigInt) { 3125 return false; 3126 } 3127 res.setBigInt(resBigInt); 3128 return true; 3129 } 3130 3131 bool BigInt::rshValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3132 MutableHandleValue res) { 3133 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3134 return false; 3135 } 3136 3137 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3138 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3139 BigInt* resBigInt = BigInt::rsh(cx, lhsBigInt, rhsBigInt); 3140 if (!resBigInt) { 3141 return false; 3142 } 3143 res.setBigInt(resBigInt); 3144 return true; 3145 } 3146 3147 bool BigInt::bitAndValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3148 MutableHandleValue res) { 3149 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3150 return false; 3151 } 3152 3153 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3154 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3155 BigInt* resBigInt = BigInt::bitAnd(cx, lhsBigInt, rhsBigInt); 3156 if (!resBigInt) { 3157 return false; 3158 } 3159 res.setBigInt(resBigInt); 3160 return true; 3161 } 3162 3163 bool BigInt::bitXorValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3164 MutableHandleValue res) { 3165 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3166 return false; 3167 } 3168 3169 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3170 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3171 BigInt* resBigInt = BigInt::bitXor(cx, lhsBigInt, rhsBigInt); 3172 if (!resBigInt) { 3173 return false; 3174 } 3175 res.setBigInt(resBigInt); 3176 return true; 3177 } 3178 3179 bool BigInt::bitOrValue(JSContext* cx, HandleValue lhs, HandleValue rhs, 3180 MutableHandleValue res) { 3181 if (!ValidBigIntOperands(cx, lhs, rhs)) { 3182 return false; 3183 } 3184 3185 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3186 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3187 BigInt* resBigInt = BigInt::bitOr(cx, lhsBigInt, rhsBigInt); 3188 if (!resBigInt) { 3189 return false; 3190 } 3191 res.setBigInt(resBigInt); 3192 return true; 3193 } 3194 3195 bool BigInt::bitNotValue(JSContext* cx, HandleValue operand, 3196 MutableHandleValue res) { 3197 MOZ_ASSERT(operand.isBigInt()); 3198 3199 RootedBigInt operandBigInt(cx, operand.toBigInt()); 3200 BigInt* resBigInt = BigInt::bitNot(cx, operandBigInt); 3201 if (!resBigInt) { 3202 return false; 3203 } 3204 res.setBigInt(resBigInt); 3205 return true; 3206 } 3207 3208 // BigInt proposal section 7.3 3209 BigInt* js::ToBigInt(JSContext* cx, HandleValue val) { 3210 RootedValue v(cx, val); 3211 3212 // Step 1. 3213 if (!ToPrimitive(cx, JSTYPE_NUMBER, &v)) { 3214 return nullptr; 3215 } 3216 3217 // Step 2. 3218 if (v.isBigInt()) { 3219 return v.toBigInt(); 3220 } 3221 3222 if (v.isBoolean()) { 3223 return v.toBoolean() ? BigInt::one(cx) : BigInt::zero(cx); 3224 } 3225 3226 if (v.isString()) { 3227 RootedString str(cx, v.toString()); 3228 BigInt* bi; 3229 JS_TRY_VAR_OR_RETURN_NULL(cx, bi, StringToBigInt(cx, str)); 3230 if (!bi) { 3231 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 3232 JSMSG_BIGINT_INVALID_SYNTAX); 3233 return nullptr; 3234 } 3235 return bi; 3236 } 3237 3238 ReportValueError(cx, JSMSG_CANT_CONVERT_TO, JSDVG_IGNORE_STACK, v, nullptr, 3239 "BigInt"); 3240 return nullptr; 3241 } 3242 3243 JS::Result<int64_t> js::ToBigInt64(JSContext* cx, HandleValue v) { 3244 BigInt* bi = js::ToBigInt(cx, v); 3245 if (!bi) { 3246 return cx->alreadyReportedError(); 3247 } 3248 return BigInt::toInt64(bi); 3249 } 3250 3251 JS::Result<uint64_t> js::ToBigUint64(JSContext* cx, HandleValue v) { 3252 BigInt* bi = js::ToBigInt(cx, v); 3253 if (!bi) { 3254 return cx->alreadyReportedError(); 3255 } 3256 return BigInt::toUint64(bi); 3257 } 3258 3259 double BigInt::numberValue(const BigInt* x) { 3260 if (x->isZero()) { 3261 return 0.0; 3262 } 3263 3264 using Double = mozilla::FloatingPoint<double>; 3265 constexpr uint8_t ExponentShift = Double::kExponentShift; 3266 constexpr uint8_t SignificandWidth = Double::kSignificandWidth; 3267 constexpr unsigned ExponentBias = Double::kExponentBias; 3268 constexpr uint8_t SignShift = Double::kExponentWidth + SignificandWidth; 3269 3270 MOZ_ASSERT(x->digitLength() > 0); 3271 3272 // Fast path for the likely-common case of up to a uint64_t of magnitude not 3273 // exceeding integral precision in IEEE-754. (Note that we *depend* on this 3274 // optimization being performed further down.) 3275 if (x->absFitsInUint64()) { 3276 uint64_t magnitude = x->uint64FromAbsNonZero(); 3277 const uint64_t MaxIntegralPrecisionDouble = uint64_t(1) 3278 << (SignificandWidth + 1); 3279 if (magnitude <= MaxIntegralPrecisionDouble) { 3280 return x->isNegative() ? -double(magnitude) : +double(magnitude); 3281 } 3282 } 3283 3284 size_t length = x->digitLength(); 3285 Digit msd = x->digit(length - 1); 3286 uint8_t msdLeadingZeroes = DigitLeadingZeroes(msd); 3287 3288 // `2**ExponentBias` is the largest power of two in a finite IEEE-754 3289 // double. If this bigint has a greater power of two, it'll round to 3290 // infinity. 3291 uint64_t exponent = length * DigitBits - msdLeadingZeroes - 1; 3292 if (exponent > ExponentBias) { 3293 return x->isNegative() ? mozilla::NegativeInfinity<double>() 3294 : mozilla::PositiveInfinity<double>(); 3295 } 3296 3297 // Otherwise munge the most significant bits of the number into proper 3298 // position in an IEEE-754 double and go to town. 3299 3300 // Omit the most significant bit: the IEEE-754 format includes this bit 3301 // implicitly for all double-precision integers. 3302 const uint8_t msdIgnoredBits = msdLeadingZeroes + 1; 3303 const uint8_t msdIncludedBits = DigitBits - msdIgnoredBits; 3304 3305 // We compute the final mantissa of the result, shifted upward to the top of 3306 // the `uint64_t` space -- plus an extra bit to detect potential rounding. 3307 constexpr uint8_t BitsNeededForShiftedMantissa = SignificandWidth + 1; 3308 3309 // Shift `msd`'s contributed bits upward to remove high-order zeroes and the 3310 // highest set bit (which is implicit in IEEE-754 integral values so must be 3311 // removed) and to add low-order zeroes. (Lower-order garbage bits are 3312 // discarded when `shiftedMantissa` is converted to a real mantissa.) 3313 uint64_t shiftedMantissa = 3314 msdIncludedBits == 0 ? 0 : uint64_t(msd) << (64 - msdIncludedBits); 3315 3316 // If the extra bit is set, correctly rounding the result may require 3317 // examining all lower-order bits. Also compute 1) the index of the Digit 3318 // storing the extra bit, and 2) whether bits beneath the extra bit in that 3319 // Digit are nonzero so we can round if needed. 3320 size_t digitContainingExtraBit; 3321 Digit bitsBeneathExtraBitInDigitContainingExtraBit; 3322 3323 // Add shifted bits to `shiftedMantissa` until we have a complete mantissa and 3324 // an extra bit. 3325 if (msdIncludedBits >= BitsNeededForShiftedMantissa) { 3326 // DigitBits=64 (necessarily for msdIncludedBits ≥ SignificandWidth+1; 3327 // | C++ compiler range analysis ought eliminate this 3328 // | check on 32-bit) 3329 // _________|__________ 3330 // / | 3331 // msdIncludedBits 3332 // ________|________ 3333 // / | 3334 // [001···················| 3335 // \_/\_____________/\__| 3336 // | | | 3337 // msdIgnoredBits | bits below the extra bit (may be no bits) 3338 // BitsNeededForShiftedMantissa=SignificandWidth+1 3339 digitContainingExtraBit = length - 1; 3340 3341 const uint8_t countOfBitsInDigitBelowExtraBit = 3342 DigitBits - BitsNeededForShiftedMantissa - msdIgnoredBits; 3343 bitsBeneathExtraBitInDigitContainingExtraBit = 3344 msd & ((Digit(1) << countOfBitsInDigitBelowExtraBit) - 1); 3345 } else { 3346 MOZ_ASSERT(length >= 2, 3347 "single-Digit numbers with this few bits should have been " 3348 "handled by the fast-path above"); 3349 3350 Digit second = x->digit(length - 2); 3351 if (DigitBits == 64) { 3352 shiftedMantissa |= second >> msdIncludedBits; 3353 3354 digitContainingExtraBit = length - 2; 3355 3356 // msdIncludedBits + DigitBits 3357 // ________|_________ 3358 // / | 3359 // DigitBits=64 3360 // msdIncludedBits | 3361 // __|___ _____|___ 3362 // / \ / | 3363 // [001········|···········| 3364 // \_/\_____________/\___| 3365 // | | | 3366 // msdIgnoredBits | bits below the extra bit (always more than one) 3367 // | 3368 // BitsNeededForShiftedMantissa=SignificandWidth+1 3369 const uint8_t countOfBitsInSecondDigitBelowExtraBit = 3370 (msdIncludedBits + DigitBits) - BitsNeededForShiftedMantissa; 3371 3372 bitsBeneathExtraBitInDigitContainingExtraBit = 3373 second << (DigitBits - countOfBitsInSecondDigitBelowExtraBit); 3374 } else { 3375 shiftedMantissa |= uint64_t(second) << msdIgnoredBits; 3376 3377 if (msdIncludedBits + DigitBits >= BitsNeededForShiftedMantissa) { 3378 digitContainingExtraBit = length - 2; 3379 3380 // msdIncludedBits + DigitBits 3381 // ______|________ 3382 // / | 3383 // DigitBits=32 3384 // msdIncludedBits | 3385 // _|_ _____|___ 3386 // / \ / | 3387 // [001·····|···········| 3388 // \___________/\__| 3389 // | | 3390 // | bits below the extra bit (may be no bits) 3391 // BitsNeededForShiftedMantissa=SignificandWidth+1 3392 const uint8_t countOfBitsInSecondDigitBelowExtraBit = 3393 (msdIncludedBits + DigitBits) - BitsNeededForShiftedMantissa; 3394 3395 bitsBeneathExtraBitInDigitContainingExtraBit = 3396 second & ((Digit(1) << countOfBitsInSecondDigitBelowExtraBit) - 1); 3397 } else { 3398 MOZ_ASSERT(length >= 3, 3399 "we must have at least three digits here, because " 3400 "`msdIncludedBits + 32 < BitsNeededForShiftedMantissa` " 3401 "guarantees `x < 2**53` -- and therefore the " 3402 "MaxIntegralPrecisionDouble optimization above will have " 3403 "handled two-digit cases"); 3404 3405 Digit third = x->digit(length - 3); 3406 shiftedMantissa |= uint64_t(third) >> msdIncludedBits; 3407 3408 digitContainingExtraBit = length - 3; 3409 3410 // msdIncludedBits + DigitBits + DigitBits 3411 // ____________|______________ 3412 // / | 3413 // DigitBits=32 3414 // msdIncludedBits | DigitBits=32 3415 // _|_ _____|___ ____|____ 3416 // / \ / \ / | 3417 // [001·····|···········|···········| 3418 // \____________________/\_____| 3419 // | | 3420 // | bits below the extra bit 3421 // BitsNeededForShiftedMantissa=SignificandWidth+1 3422 static_assert(2 * DigitBits > BitsNeededForShiftedMantissa, 3423 "two 32-bit digits should more than fill a mantissa"); 3424 const uint8_t countOfBitsInThirdDigitBelowExtraBit = 3425 msdIncludedBits + 2 * DigitBits - BitsNeededForShiftedMantissa; 3426 3427 // Shift out the mantissa bits and the extra bit. 3428 bitsBeneathExtraBitInDigitContainingExtraBit = 3429 third << (DigitBits - countOfBitsInThirdDigitBelowExtraBit); 3430 } 3431 } 3432 } 3433 3434 constexpr uint64_t LeastSignificantBit = uint64_t(1) 3435 << (64 - SignificandWidth); 3436 constexpr uint64_t ExtraBit = LeastSignificantBit >> 1; 3437 3438 // The extra bit must be set for rounding to change the mantissa. 3439 if ((shiftedMantissa & ExtraBit) != 0) { 3440 bool shouldRoundUp; 3441 if (shiftedMantissa & LeastSignificantBit) { 3442 // If the lowest mantissa bit is set, it doesn't matter what lower bits 3443 // are: nearest-even rounds up regardless. 3444 shouldRoundUp = true; 3445 } else { 3446 // If the lowest mantissa bit is unset, *all* lower bits are relevant. 3447 // All-zero bits below the extra bit situates `x` halfway between two 3448 // values, and the nearest *even* value lies downward. But if any bit 3449 // below the extra bit is set, `x` is closer to the rounded-up value. 3450 shouldRoundUp = bitsBeneathExtraBitInDigitContainingExtraBit != 0; 3451 if (!shouldRoundUp) { 3452 while (digitContainingExtraBit-- > 0) { 3453 if (x->digit(digitContainingExtraBit) != 0) { 3454 shouldRoundUp = true; 3455 break; 3456 } 3457 } 3458 } 3459 } 3460 3461 if (shouldRoundUp) { 3462 // Add one to the significand bits. If they overflow, the exponent must 3463 // also be increased. If *that* overflows, return the correct infinity. 3464 uint64_t before = shiftedMantissa; 3465 shiftedMantissa += ExtraBit; 3466 if (shiftedMantissa < before) { 3467 exponent++; 3468 if (exponent > ExponentBias) { 3469 return x->isNegative() ? NegativeInfinity<double>() 3470 : PositiveInfinity<double>(); 3471 } 3472 } 3473 } 3474 } 3475 3476 uint64_t significandBits = shiftedMantissa >> (64 - SignificandWidth); 3477 uint64_t signBit = uint64_t(x->isNegative() ? 1 : 0) << SignShift; 3478 uint64_t exponentBits = (exponent + ExponentBias) << ExponentShift; 3479 return mozilla::BitwiseCast<double>(signBit | exponentBits | significandBits); 3480 } 3481 3482 int8_t BigInt::compare(const BigInt* x, const BigInt* y) { 3483 // Sanity checks to catch negative zeroes escaping to the wild. 3484 MOZ_ASSERT(!x->isNegative() || !x->isZero()); 3485 MOZ_ASSERT(!y->isNegative() || !y->isZero()); 3486 3487 bool xSign = x->isNegative(); 3488 3489 if (xSign != y->isNegative()) { 3490 return xSign ? -1 : 1; 3491 } 3492 3493 if (xSign) { 3494 std::swap(x, y); 3495 } 3496 3497 return absoluteCompare(x, y); 3498 } 3499 3500 bool BigInt::equal(const BigInt* lhs, const BigInt* rhs) { 3501 if (lhs == rhs) { 3502 return true; 3503 } 3504 if (lhs->digitLength() != rhs->digitLength()) { 3505 return false; 3506 } 3507 if (lhs->isNegative() != rhs->isNegative()) { 3508 return false; 3509 } 3510 for (size_t i = 0; i < lhs->digitLength(); i++) { 3511 if (lhs->digit(i) != rhs->digit(i)) { 3512 return false; 3513 } 3514 } 3515 return true; 3516 } 3517 3518 int8_t BigInt::compare(const BigInt* x, double y) { 3519 MOZ_ASSERT(!std::isnan(y)); 3520 3521 constexpr int LessThan = -1, Equal = 0, GreaterThan = 1; 3522 3523 // ±Infinity exceeds a finite bigint value. 3524 if (!std::isfinite(y)) { 3525 return y > 0 ? LessThan : GreaterThan; 3526 } 3527 3528 // Handle `x === 0n` and `y == 0` special cases. 3529 if (x->isZero()) { 3530 if (y == 0) { 3531 // -0 and +0 are treated identically. 3532 return Equal; 3533 } 3534 3535 return y > 0 ? LessThan : GreaterThan; 3536 } 3537 3538 const bool xNegative = x->isNegative(); 3539 if (y == 0) { 3540 return xNegative ? LessThan : GreaterThan; 3541 } 3542 3543 // Nonzero `x` and `y` with different signs are trivially compared. 3544 const bool yNegative = y < 0; 3545 if (xNegative != yNegative) { 3546 return xNegative ? LessThan : GreaterThan; 3547 } 3548 3549 // `x` and `y` are same-signed. Determine which has greater magnitude, 3550 // then combine that with the signedness just computed to reach a result. 3551 const int exponent = mozilla::ExponentComponent(y); 3552 if (exponent < 0) { 3553 // `y` is a nonzero fraction of magnitude less than 1. 3554 return xNegative ? LessThan : GreaterThan; 3555 } 3556 3557 size_t xLength = x->digitLength(); 3558 MOZ_ASSERT(xLength > 0); 3559 3560 Digit xMSD = x->digit(xLength - 1); 3561 const int shift = DigitLeadingZeroes(xMSD); 3562 int xBitLength = xLength * DigitBits - shift; 3563 3564 // Differing bit-length makes for a simple comparison. 3565 int yBitLength = exponent + 1; 3566 if (xBitLength < yBitLength) { 3567 return xNegative ? GreaterThan : LessThan; 3568 } 3569 if (xBitLength > yBitLength) { 3570 return xNegative ? LessThan : GreaterThan; 3571 } 3572 3573 // Compare the high 64 bits of both numbers. (Lower-order bits not present 3574 // in either number are zeroed.) Either that distinguishes `x` and `y`, or 3575 // `x` and `y` differ only if a subsequent nonzero bit in `x` means `x` has 3576 // larger magnitude. 3577 3578 using Double = mozilla::FloatingPoint<double>; 3579 constexpr uint8_t SignificandWidth = Double::kSignificandWidth; 3580 constexpr uint64_t SignificandBits = Double::kSignificandBits; 3581 3582 const uint64_t doubleBits = mozilla::BitwiseCast<uint64_t>(y); 3583 const uint64_t significandBits = doubleBits & SignificandBits; 3584 3585 // Readd the implicit-one bit when constructing `y`'s high 64 bits. 3586 const uint64_t yHigh64Bits = 3587 ((uint64_t(1) << SignificandWidth) | significandBits) 3588 << (64 - SignificandWidth - 1); 3589 3590 // Cons up `x`'s high 64 bits, backfilling zeroes for binary fractions of 1 3591 // if `x` doesn't have 64 bits. 3592 uint8_t xBitsFilled = DigitBits - shift; 3593 uint64_t xHigh64Bits = uint64_t(xMSD) << (64 - xBitsFilled); 3594 3595 // At this point we no longer need to look at the most significant digit. 3596 xLength--; 3597 3598 // The high 64 bits from `x` will probably not align to a digit boundary. 3599 // `xHasNonZeroLeftoverBits` will be set to true if any remaining 3600 // least-significant bit from the digit holding xHigh64Bits's 3601 // least-significant bit is nonzero. 3602 bool xHasNonZeroLeftoverBits = false; 3603 3604 if (xBitsFilled < std::min(xBitLength, 64)) { 3605 MOZ_ASSERT(xLength >= 1, 3606 "If there are more bits to fill, there should be " 3607 "more digits to fill them from"); 3608 3609 Digit second = x->digit(--xLength); 3610 if (DigitBits == 32) { 3611 xBitsFilled += 32; 3612 xHigh64Bits |= uint64_t(second) << (64 - xBitsFilled); 3613 if (xBitsFilled < 64 && xLength >= 1) { 3614 Digit third = x->digit(--xLength); 3615 const uint8_t neededBits = 64 - xBitsFilled; 3616 xHigh64Bits |= uint64_t(third) >> (DigitBits - neededBits); 3617 xHasNonZeroLeftoverBits = (third << neededBits) != 0; 3618 } 3619 } else { 3620 const uint8_t neededBits = 64 - xBitsFilled; 3621 xHigh64Bits |= uint64_t(second) >> (DigitBits - neededBits); 3622 xHasNonZeroLeftoverBits = (second << neededBits) != 0; 3623 } 3624 } 3625 3626 // If high bits are unequal, the larger one has greater magnitude. 3627 if (yHigh64Bits > xHigh64Bits) { 3628 return xNegative ? GreaterThan : LessThan; 3629 } 3630 if (xHigh64Bits > yHigh64Bits) { 3631 return xNegative ? LessThan : GreaterThan; 3632 } 3633 3634 // Otherwise the top 64 bits of both are equal. If the values differ, a 3635 // lower-order bit in `x` is nonzero and `x` has greater magnitude than 3636 // `y`; otherwise `x == y`. 3637 if (xHasNonZeroLeftoverBits) { 3638 return xNegative ? LessThan : GreaterThan; 3639 } 3640 while (xLength != 0) { 3641 if (x->digit(--xLength) != 0) { 3642 return xNegative ? LessThan : GreaterThan; 3643 } 3644 } 3645 3646 return Equal; 3647 } 3648 3649 bool BigInt::equal(const BigInt* lhs, double rhs) { 3650 if (std::isnan(rhs)) { 3651 return false; 3652 } 3653 return compare(lhs, rhs) == 0; 3654 } 3655 3656 JS::Result<bool> BigInt::equal(JSContext* cx, Handle<BigInt*> lhs, 3657 HandleString rhs) { 3658 BigInt* rhsBigInt = MOZ_TRY(StringToBigInt(cx, rhs)); 3659 if (!rhsBigInt) { 3660 return false; 3661 } 3662 return equal(lhs, rhsBigInt); 3663 } 3664 3665 // BigInt proposal section 1.1.12. BigInt::lessThan ( x, y ) 3666 bool BigInt::lessThan(const BigInt* x, const BigInt* y) { 3667 return compare(x, y) < 0; 3668 } 3669 3670 Maybe<bool> BigInt::lessThan(const BigInt* lhs, double rhs) { 3671 if (std::isnan(rhs)) { 3672 return Maybe<bool>(Nothing()); 3673 } 3674 return Some(compare(lhs, rhs) < 0); 3675 } 3676 3677 Maybe<bool> BigInt::lessThan(double lhs, const BigInt* rhs) { 3678 if (std::isnan(lhs)) { 3679 return Maybe<bool>(Nothing()); 3680 } 3681 return Some(-compare(rhs, lhs) < 0); 3682 } 3683 3684 bool BigInt::lessThan(JSContext* cx, HandleBigInt lhs, HandleString rhs, 3685 Maybe<bool>& res) { 3686 BigInt* rhsBigInt; 3687 JS_TRY_VAR_OR_RETURN_FALSE(cx, rhsBigInt, StringToBigInt(cx, rhs)); 3688 if (!rhsBigInt) { 3689 res = Nothing(); 3690 return true; 3691 } 3692 res = Some(lessThan(lhs, rhsBigInt)); 3693 return true; 3694 } 3695 3696 bool BigInt::lessThan(JSContext* cx, HandleString lhs, HandleBigInt rhs, 3697 Maybe<bool>& res) { 3698 BigInt* lhsBigInt; 3699 JS_TRY_VAR_OR_RETURN_FALSE(cx, lhsBigInt, StringToBigInt(cx, lhs)); 3700 if (!lhsBigInt) { 3701 res = Nothing(); 3702 return true; 3703 } 3704 res = Some(lessThan(lhsBigInt, rhs)); 3705 return true; 3706 } 3707 3708 bool BigInt::lessThan(JSContext* cx, HandleValue lhs, HandleValue rhs, 3709 Maybe<bool>& res) { 3710 if (lhs.isBigInt()) { 3711 if (rhs.isString()) { 3712 RootedBigInt lhsBigInt(cx, lhs.toBigInt()); 3713 RootedString rhsString(cx, rhs.toString()); 3714 return lessThan(cx, lhsBigInt, rhsString, res); 3715 } 3716 3717 if (rhs.isNumber()) { 3718 res = lessThan(lhs.toBigInt(), rhs.toNumber()); 3719 return true; 3720 } 3721 3722 MOZ_ASSERT(rhs.isBigInt()); 3723 res = Some(lessThan(lhs.toBigInt(), rhs.toBigInt())); 3724 return true; 3725 } 3726 3727 MOZ_ASSERT(rhs.isBigInt()); 3728 if (lhs.isString()) { 3729 RootedString lhsString(cx, lhs.toString()); 3730 RootedBigInt rhsBigInt(cx, rhs.toBigInt()); 3731 return lessThan(cx, lhsString, rhsBigInt, res); 3732 } 3733 3734 MOZ_ASSERT(lhs.isNumber()); 3735 res = lessThan(lhs.toNumber(), rhs.toBigInt()); 3736 return true; 3737 } 3738 3739 template <js::AllowGC allowGC> 3740 JSLinearString* BigInt::toString(JSContext* cx, HandleBigInt x, uint8_t radix) { 3741 MOZ_ASSERT(2 <= radix && radix <= 36); 3742 3743 if (x->isZero()) { 3744 return cx->staticStrings().getInt(0); 3745 } 3746 3747 if (x->digitLength() == 1) { 3748 return toStringSingleDigit<allowGC>(cx, x->digit(0), x->isNegative(), 3749 radix); 3750 } 3751 3752 if (mozilla::IsPowerOfTwo(radix)) { 3753 return toStringBasePowerOfTwo<allowGC>(cx, x, radix); 3754 } 3755 3756 // Punt on doing generic toString without GC. 3757 if (!allowGC) { 3758 return nullptr; 3759 } 3760 3761 return toStringGeneric(cx, x, radix); 3762 } 3763 3764 template JSLinearString* BigInt::toString<js::CanGC>(JSContext* cx, 3765 HandleBigInt x, 3766 uint8_t radix); 3767 template JSLinearString* BigInt::toString<js::NoGC>(JSContext* cx, 3768 HandleBigInt x, 3769 uint8_t radix); 3770 3771 template <typename CharT> 3772 static inline BigInt* ParseStringBigIntLiteral(JSContext* cx, 3773 Range<const CharT> range, 3774 bool* haveParseError) { 3775 auto start = range.begin(); 3776 auto end = range.end(); 3777 3778 while (start < end && unicode::IsSpace(start[0])) { 3779 start++; 3780 } 3781 3782 while (start < end && unicode::IsSpace(end[-1])) { 3783 end--; 3784 } 3785 3786 if (start == end) { 3787 return BigInt::zero(cx); 3788 } 3789 3790 // StringNumericLiteral ::: StrDecimalLiteral, but without Infinity, decimal 3791 // points, or exponents. Note that the raw '+' or '-' cases fall through 3792 // because the string is too short, and eventually signal a parse error. 3793 if (end - start > 1) { 3794 if (start[0] == '+') { 3795 bool isNegative = false; 3796 start++; 3797 return BigInt::parseLiteralDigits(cx, Range<const CharT>(start, end), 10, 3798 isNegative, haveParseError); 3799 } 3800 if (start[0] == '-') { 3801 bool isNegative = true; 3802 start++; 3803 return BigInt::parseLiteralDigits(cx, Range<const CharT>(start, end), 10, 3804 isNegative, haveParseError); 3805 } 3806 } 3807 3808 return BigInt::parseLiteral(cx, Range<const CharT>(start, end), 3809 haveParseError); 3810 } 3811 3812 // Called from BigInt constructor. 3813 JS::Result<BigInt*> js::StringToBigInt(JSContext* cx, HandleString str) { 3814 JSLinearString* linear = str->ensureLinear(cx); 3815 if (!linear) { 3816 return cx->alreadyReportedOOM(); 3817 } 3818 3819 AutoStableStringChars chars(cx); 3820 if (!chars.init(cx, str)) { 3821 return cx->alreadyReportedOOM(); 3822 } 3823 3824 BigInt* res; 3825 bool parseError = false; 3826 if (chars.isLatin1()) { 3827 res = ParseStringBigIntLiteral(cx, chars.latin1Range(), &parseError); 3828 } else { 3829 res = ParseStringBigIntLiteral(cx, chars.twoByteRange(), &parseError); 3830 } 3831 3832 // A nullptr result can indicate either a parse error or generic error. 3833 if (!res && !parseError) { 3834 return cx->alreadyReportedError(); 3835 } 3836 3837 return res; 3838 } 3839 3840 // Called from parser with already trimmed and validated token. 3841 BigInt* js::ParseBigIntLiteral(JSContext* cx, 3842 const Range<const char16_t>& chars) { 3843 // This function is only called from the frontend when parsing BigInts. Parsed 3844 // BigInts are stored in the script's data vector and therefore need to be 3845 // allocated in the tenured heap. 3846 constexpr gc::Heap heap = gc::Heap::Tenured; 3847 3848 bool parseError = false; 3849 BigInt* res = BigInt::parseLiteral(cx, chars, &parseError, heap); 3850 if (!res) { 3851 return nullptr; 3852 } 3853 MOZ_ASSERT(res->isTenured()); 3854 MOZ_RELEASE_ASSERT(!parseError); 3855 return res; 3856 } 3857 3858 mozilla::Maybe<int64_t> js::ParseBigInt64Literal( 3859 mozilla::Range<const char16_t> chars) { 3860 size_t length = chars.length(); 3861 MOZ_ASSERT(length > 0); 3862 3863 int32_t radix = 10; 3864 if (length > 2 && chars[0] == '0') { 3865 if (chars[1] == 'b' || chars[1] == 'B') { 3866 // StringNumericLiteral ::: BinaryIntegerLiteral 3867 radix = 2; 3868 } else if (chars[1] == 'x' || chars[1] == 'X') { 3869 // StringNumericLiteral ::: HexIntegerLiteral 3870 radix = 16; 3871 } else if (chars[1] == 'o' || chars[1] == 'O') { 3872 // StringNumericLiteral ::: OctalIntegerLiteral 3873 radix = 8; 3874 } 3875 } 3876 3877 auto start = chars.begin(); 3878 const auto end = chars.end(); 3879 3880 // Skip over prefix. 3881 if (radix != 10) { 3882 start += 2; 3883 } 3884 3885 // Skipping leading zeroes. 3886 while (*start == '0') { 3887 start++; 3888 if (start == end) { 3889 return mozilla::Some(0); 3890 } 3891 } 3892 3893 mozilla::CheckedInt<int64_t> r = 0; 3894 while (start < end) { 3895 char16_t c = *start++; 3896 MOZ_ASSERT(mozilla::IsAsciiAlphanumeric(c)); 3897 3898 int32_t digit = mozilla::AsciiAlphanumericToNumber(c); 3899 MOZ_ASSERT(digit < radix); 3900 3901 r *= radix; 3902 r += digit; 3903 if (!r.isValid()) { 3904 return mozilla::Nothing(); 3905 } 3906 } 3907 3908 return mozilla::Some(r.value()); 3909 } 3910 3911 template <js::AllowGC allowGC> 3912 JSAtom* js::BigIntToAtom(JSContext* cx, HandleBigInt bi) { 3913 JSString* str = BigInt::toString<allowGC>(cx, bi, 10); 3914 if (!str) { 3915 return nullptr; 3916 } 3917 JSAtom* atom = AtomizeString(cx, str); 3918 if (!atom) { 3919 if constexpr (!allowGC) { 3920 // NOTE: AtomizeString can call ReportAllocationOverflow other than 3921 // ReportOutOfMemory, but ReportAllocationOverflow cannot happen 3922 // because the length is guarded by BigInt::toString. 3923 cx->recoverFromOutOfMemory(); 3924 } 3925 return nullptr; 3926 } 3927 return atom; 3928 } 3929 3930 template JSAtom* js::BigIntToAtom<js::CanGC>(JSContext* cx, HandleBigInt bi); 3931 template JSAtom* js::BigIntToAtom<js::NoGC>(JSContext* cx, HandleBigInt bi); 3932 3933 #if defined(DEBUG) || defined(JS_JITSPEW) 3934 void BigInt::dump() const { 3935 js::Fprinter out(stderr); 3936 dump(out); 3937 } 3938 3939 void BigInt::dump(js::GenericPrinter& out) const { 3940 js::JSONPrinter json(out); 3941 dump(json); 3942 out.put("\n"); 3943 } 3944 3945 void BigInt::dump(js::JSONPrinter& json) const { 3946 json.beginObject(); 3947 dumpFields(json); 3948 json.endObject(); 3949 } 3950 3951 void BigInt::dumpFields(js::JSONPrinter& json) const { 3952 json.formatProperty("address", "(JS::BigInt*)0x%p", this); 3953 3954 json.property("digitLength", digitLength()); 3955 3956 js::GenericPrinter& out = json.beginStringProperty("value"); 3957 dumpLiteral(out); 3958 json.endStringProperty(); 3959 } 3960 3961 void BigInt::dumpStringContent(js::GenericPrinter& out) const { 3962 dumpLiteral(out); 3963 3964 out.printf(" @ (JS::BigInt*)0x%p", this); 3965 } 3966 3967 void BigInt::dumpLiteral(js::GenericPrinter& out) const { 3968 if (isNegative()) { 3969 out.putChar('-'); 3970 } 3971 3972 if (digitLength() == 0) { 3973 out.put("0"); 3974 } else if (digitLength() == 1) { 3975 uint64_t d = digit(0); 3976 out.printf("%" PRIu64, d); 3977 } else { 3978 out.put("0x"); 3979 for (size_t i = 0; i < digitLength(); i++) { 3980 uint64_t d = digit(digitLength() - i - 1); 3981 if (sizeof(Digit) == 4) { 3982 out.printf("%.8" PRIX32, uint32_t(d)); 3983 } else { 3984 out.printf("%.16" PRIX64, d); 3985 } 3986 } 3987 } 3988 3989 out.putChar('n'); 3990 } 3991 #endif 3992 3993 JS::ubi::Node::Size JS::ubi::Concrete<BigInt>::size( 3994 mozilla::MallocSizeOf mallocSizeOf) const { 3995 BigInt& bi = get(); 3996 size_t size = sizeof(JS::BigInt); 3997 if (IsInsideNursery(&bi)) { 3998 size += Nursery::nurseryCellHeaderSize(); 3999 size += bi.sizeOfExcludingThisInNursery(mallocSizeOf); 4000 } else { 4001 size += bi.sizeOfExcludingThis(mallocSizeOf); 4002 } 4003 return size; 4004 } 4005 4006 // Public API 4007 4008 BigInt* JS::NumberToBigInt(JSContext* cx, double num) { 4009 return js::NumberToBigInt(cx, num); 4010 } 4011 4012 template <typename CharT> 4013 static inline BigInt* StringToBigIntHelper(JSContext* cx, 4014 const Range<const CharT>& chars) { 4015 bool parseError = false; 4016 BigInt* bi = ParseStringBigIntLiteral(cx, chars, &parseError); 4017 if (!bi) { 4018 if (parseError) { 4019 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 4020 JSMSG_BIGINT_INVALID_SYNTAX); 4021 } 4022 return nullptr; 4023 } 4024 MOZ_RELEASE_ASSERT(!parseError); 4025 return bi; 4026 } 4027 4028 BigInt* JS::StringToBigInt(JSContext* cx, 4029 const Range<const Latin1Char>& chars) { 4030 return StringToBigIntHelper(cx, chars); 4031 } 4032 4033 BigInt* JS::StringToBigInt(JSContext* cx, const Range<const char16_t>& chars) { 4034 return StringToBigIntHelper(cx, chars); 4035 } 4036 4037 BigInt* JS::SimpleStringToBigInt(JSContext* cx, mozilla::Span<const char> chars, 4038 uint8_t radix) { 4039 if (chars.empty()) { 4040 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 4041 JSMSG_BIGINT_INVALID_SYNTAX); 4042 return nullptr; 4043 } 4044 if (radix < 2 || radix > 36) { 4045 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_RADIX); 4046 return nullptr; 4047 } 4048 4049 mozilla::Span<const Latin1Char> latin1{ 4050 reinterpret_cast<const Latin1Char*>(chars.data()), chars.size()}; 4051 4052 bool isNegative = false; 4053 if (chars.size() > 1 && (chars[0] == '-' || chars[0] == '+')) { 4054 isNegative = chars[0] == '-'; 4055 latin1 = latin1.From(1); 4056 } 4057 4058 bool haveParseError = false; 4059 BigInt* bi = BigInt::parseLiteralDigits(cx, mozilla::Range{latin1}, radix, 4060 isNegative, &haveParseError); 4061 if (!bi) { 4062 if (haveParseError) { 4063 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 4064 JSMSG_BIGINT_INVALID_SYNTAX); 4065 } 4066 return nullptr; 4067 } 4068 MOZ_RELEASE_ASSERT(!haveParseError); 4069 return bi; 4070 } 4071 4072 BigInt* JS::ToBigInt(JSContext* cx, HandleValue val) { 4073 return js::ToBigInt(cx, val); 4074 } 4075 4076 int64_t JS::ToBigInt64(const JS::BigInt* bi) { return BigInt::toInt64(bi); } 4077 4078 uint64_t JS::ToBigUint64(const JS::BigInt* bi) { return BigInt::toUint64(bi); } 4079 4080 double JS::BigIntToNumber(const JS::BigInt* bi) { 4081 return BigInt::numberValue(bi); 4082 } 4083 4084 bool JS::BigIntIsNegative(const BigInt* bi) { 4085 return !bi->isZero() && bi->isNegative(); 4086 } 4087 4088 bool JS::BigIntFitsNumber(const BigInt* bi, double* out) { 4089 return bi->isNumber(bi, out); 4090 } 4091 4092 JSString* JS::BigIntToString(JSContext* cx, Handle<BigInt*> bi, uint8_t radix) { 4093 if (radix < 2 || radix > 36) { 4094 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_RADIX); 4095 return nullptr; 4096 } 4097 return BigInt::toString<CanGC>(cx, bi, radix); 4098 } 4099 4100 // Semi-public template details 4101 4102 BigInt* JS::detail::BigIntFromInt64(JSContext* cx, int64_t num) { 4103 return BigInt::createFromInt64(cx, num); 4104 } 4105 4106 BigInt* JS::detail::BigIntFromUint64(JSContext* cx, uint64_t num) { 4107 return BigInt::createFromUint64(cx, num); 4108 } 4109 4110 BigInt* JS::detail::BigIntFromBool(JSContext* cx, bool b) { 4111 return b ? BigInt::one(cx) : BigInt::zero(cx); 4112 } 4113 4114 bool JS::detail::BigIntIsInt64(const BigInt* bi, int64_t* result) { 4115 return BigInt::isInt64(bi, result); 4116 } 4117 4118 bool JS::detail::BigIntIsUint64(const BigInt* bi, uint64_t* result) { 4119 return BigInt::isUint64(bi, result); 4120 }