| // Copyright 2017 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_OBJECTS_BIGINT_H_ |
| #define V8_OBJECTS_BIGINT_H_ |
| |
| #include "src/globals.h" |
| #include "src/objects.h" |
| #include "src/utils.h" |
| |
| // Has to be the last include (doesn't have include guards): |
| #include "src/objects/object-macros.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| // UNDER CONSTRUCTION! |
| // Arbitrary precision integers in JavaScript. |
| class BigInt : public HeapObject { |
| public: |
| // Implementation of the Spec methods, see: |
| // https://tc39.github.io/proposal-bigint/#sec-numeric-types |
| // Sections 1.1.1 through 1.1.19. |
| static Handle<BigInt> UnaryMinus(Handle<BigInt> x); |
| static Handle<BigInt> BitwiseNot(Handle<BigInt> x); |
| static MaybeHandle<BigInt> Exponentiate(Handle<BigInt> base, |
| Handle<BigInt> exponent); |
| static Handle<BigInt> Multiply(Handle<BigInt> x, Handle<BigInt> y); |
| static MaybeHandle<BigInt> Divide(Handle<BigInt> x, Handle<BigInt> y); |
| static MaybeHandle<BigInt> Remainder(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> Add(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> Subtract(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> LeftShift(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> SignedRightShift(Handle<BigInt> x, Handle<BigInt> y); |
| static MaybeHandle<BigInt> UnsignedRightShift(Handle<BigInt> x, |
| Handle<BigInt> y); |
| static bool LessThan(Handle<BigInt> x, Handle<BigInt> y); |
| static bool Equal(BigInt* x, BigInt* y); |
| static Handle<BigInt> BitwiseAnd(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> BitwiseXor(Handle<BigInt> x, Handle<BigInt> y); |
| static Handle<BigInt> BitwiseOr(Handle<BigInt> x, Handle<BigInt> y); |
| |
| // Other parts of the public interface. |
| bool ToBoolean() { return !is_zero(); } |
| uint32_t Hash() { |
| // TODO(jkummerow): Improve this. At least use length and sign. |
| return is_zero() ? 0 : ComputeIntegerHash(static_cast<uint32_t>(digit(0))); |
| } |
| |
| DECL_CAST(BigInt) |
| DECL_VERIFIER(BigInt) |
| DECL_PRINTER(BigInt) |
| |
| // TODO(jkummerow): Do we need {synchronized_length} for GC purposes? |
| DECL_INT_ACCESSORS(length) |
| |
| inline static int SizeFor(int length) { |
| return kHeaderSize + length * kDigitSize; |
| } |
| void Initialize(int length, bool zero_initialize); |
| |
| static MaybeHandle<String> ToString(Handle<BigInt> bigint, int radix); |
| |
| // Temporarily exposed helper, pending proper initialization. |
| void set_value(int value) { |
| DCHECK(length() == 1); |
| if (value > 0) { |
| set_digit(0, value); |
| } else { |
| set_digit(0, -value); // This can overflow. We don't care. |
| set_sign(true); |
| } |
| } |
| |
| // The maximum length that the current implementation supports would be |
| // kMaxInt / kDigitBits. However, we use a lower limit for now, because |
| // raising it later is easier than lowering it. |
| static const int kMaxLengthBits = 20; |
| static const int kMaxLength = (1 << kMaxLengthBits) - 1; |
| |
| class BodyDescriptor; |
| |
| private: |
| friend class BigIntParseIntHelper; |
| |
| typedef uintptr_t digit_t; |
| static const int kDigitSize = sizeof(digit_t); |
| static const int kDigitBits = kDigitSize * kBitsPerByte; |
| static const int kHalfDigitBits = kDigitBits / 2; |
| static const digit_t kHalfDigitMask = (1ull << kHalfDigitBits) - 1; |
| |
| // Private helpers for public methods. |
| static Handle<BigInt> Copy(Handle<BigInt> source); |
| static MaybeHandle<BigInt> AllocateFor(Isolate* isolate, int radix, |
| int charcount); |
| void RightTrim(); |
| |
| static Handle<BigInt> AbsoluteAdd(Handle<BigInt> x, Handle<BigInt> y, |
| bool result_sign); |
| static Handle<BigInt> AbsoluteSub(Handle<BigInt> x, Handle<BigInt> y, |
| bool result_sign); |
| // Returns a positive value if abs(x) > abs(y), a negative value if |
| // abs(x) < abs(y), or zero if abs(x) == abs(y). |
| static int AbsoluteCompare(Handle<BigInt> x, Handle<BigInt> y); |
| |
| static void MultiplyAccumulate(Handle<BigInt> multiplicand, |
| digit_t multiplier, Handle<BigInt> accumulator, |
| int accumulator_index); |
| static void InternalMultiplyAdd(BigInt* source, digit_t factor, |
| digit_t summand, int n, BigInt* result); |
| void InplaceMultiplyAdd(uintptr_t factor, uintptr_t summand); |
| |
| // Specialized helpers for Divide/Remainder. |
| static void AbsoluteDivSmall(Handle<BigInt> x, digit_t divisor, |
| Handle<BigInt>* quotient, digit_t* remainder); |
| static void AbsoluteDivLarge(Handle<BigInt> dividend, Handle<BigInt> divisor, |
| Handle<BigInt>* quotient, |
| Handle<BigInt>* remainder); |
| static bool ProductGreaterThan(digit_t factor1, digit_t factor2, digit_t high, |
| digit_t low); |
| digit_t InplaceAdd(BigInt* summand, int start_index); |
| digit_t InplaceSub(BigInt* subtrahend, int start_index); |
| void InplaceRightShift(int shift); |
| enum SpecialLeftShiftMode { |
| kSameSizeResult, |
| kAlwaysAddOneDigit, |
| }; |
| static Handle<BigInt> SpecialLeftShift(Handle<BigInt> x, int shift, |
| SpecialLeftShiftMode mode); |
| |
| static MaybeHandle<String> ToStringBasePowerOfTwo(Handle<BigInt> x, |
| int radix); |
| |
| // Digit arithmetic helpers. |
| static inline digit_t digit_add(digit_t a, digit_t b, digit_t* carry); |
| static inline digit_t digit_sub(digit_t a, digit_t b, digit_t* borrow); |
| static inline digit_t digit_mul(digit_t a, digit_t b, digit_t* high); |
| static inline digit_t digit_div(digit_t high, digit_t low, digit_t divisor, |
| digit_t* remainder); |
| |
| class LengthBits : public BitField<int, 0, kMaxLengthBits> {}; |
| class SignBits : public BitField<bool, LengthBits::kNext, 1> {}; |
| |
| // Low-level accessors. |
| // sign() == true means negative. |
| DECL_BOOLEAN_ACCESSORS(sign) |
| inline digit_t digit(int n) const; |
| inline void set_digit(int n, digit_t value); |
| |
| bool is_zero() { |
| DCHECK(length() > 0 || !sign()); // There is no -0n. |
| return length() == 0; |
| } |
| static const int kBitfieldOffset = HeapObject::kHeaderSize; |
| static const int kDigitsOffset = kBitfieldOffset + kPointerSize; |
| static const int kHeaderSize = kDigitsOffset; |
| DISALLOW_IMPLICIT_CONSTRUCTORS(BigInt); |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #include "src/objects/object-macros-undef.h" |
| |
| #endif // V8_OBJECTS_BIGINT_H_ |