LCOV - code coverage report
Current view: top level - src/objects - bigint.h (source / functions) Hit Total Coverage
Test: app.info Lines: 17 17 100.0 %
Date: 2019-01-20 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_OBJECTS_BIGINT_H_
       6             : #define V8_OBJECTS_BIGINT_H_
       7             : 
       8             : #include "src/globals.h"
       9             : #include "src/objects.h"
      10             : #include "src/objects/heap-object.h"
      11             : #include "src/utils.h"
      12             : 
      13             : // Has to be the last include (doesn't have include guards):
      14             : #include "src/objects/object-macros.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19             : class BigInt;
      20             : class ValueDeserializer;
      21             : class ValueSerializer;
      22             : 
      23             : // BigIntBase is just the raw data object underlying a BigInt. Use with care!
      24             : // Most code should be using BigInts instead.
      25             : class BigIntBase : public HeapObject {
      26             :  public:
      27             :   inline int length() const {
      28     2535484 :     int32_t bitfield = RELAXED_READ_INT32_FIELD(this, kBitfieldOffset);
      29             :     return LengthBits::decode(static_cast<uint32_t>(bitfield));
      30             :   }
      31             : 
      32             :   // For use by the GC.
      33             :   inline int synchronized_length() const {
      34        3556 :     int32_t bitfield = ACQUIRE_READ_INT32_FIELD(this, kBitfieldOffset);
      35             :     return LengthBits::decode(static_cast<uint32_t>(bitfield));
      36             :   }
      37             : 
      38      485456 :   static inline BigIntBase unchecked_cast(Object o) {
      39      485456 :     return bit_cast<BigIntBase>(o);
      40             :   }
      41             : 
      42             :   // The maximum kMaxLengthBits that the current implementation supports
      43             :   // would be kMaxInt - kSystemPointerSize * kBitsPerByte - 1.
      44             :   // Since we want a platform independent limit, choose a nice round number
      45             :   // somewhere below that maximum.
      46             :   static const int kMaxLengthBits = 1 << 30;  // ~1 billion.
      47             :   static const int kMaxLength =
      48             :       kMaxLengthBits / (kSystemPointerSize * kBitsPerByte);
      49             : 
      50             :   // Sign and length are stored in the same bitfield.  Since the GC needs to be
      51             :   // able to read the length concurrently, the getters and setters are atomic.
      52             :   static const int kLengthFieldBits = 30;
      53             :   STATIC_ASSERT(kMaxLength <= ((1 << kLengthFieldBits) - 1));
      54             :   class SignBits : public BitField<bool, 0, 1> {};
      55             :   class LengthBits : public BitField<int, SignBits::kNext, kLengthFieldBits> {};
      56             :   STATIC_ASSERT(LengthBits::kNext <= 32);
      57             : 
      58             :   // Layout description.
      59             : #define BIGINT_FIELDS(V)                                                  \
      60             :   V(kBitfieldOffset, kInt32Size)                                          \
      61             :   V(kOptionalPaddingOffset, POINTER_SIZE_PADDING(kOptionalPaddingOffset)) \
      62             :   /* Header size. */                                                      \
      63             :   V(kHeaderSize, 0)                                                       \
      64             :   V(kDigitsOffset, 0)
      65             : 
      66             :   DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, BIGINT_FIELDS)
      67             : #undef BIGINT_FIELDS
      68             : 
      69             :  private:
      70             :   friend class ::v8::internal::BigInt;  // MSVC wants full namespace.
      71             :   friend class MutableBigInt;
      72             : 
      73             :   typedef uintptr_t digit_t;
      74             :   static const int kDigitSize = sizeof(digit_t);
      75             :   // kMaxLength definition assumes this:
      76             :   STATIC_ASSERT(kDigitSize == kSystemPointerSize);
      77             : 
      78             :   static const int kDigitBits = kDigitSize * kBitsPerByte;
      79             :   static const int kHalfDigitBits = kDigitBits / 2;
      80             :   static const digit_t kHalfDigitMask = (1ull << kHalfDigitBits) - 1;
      81             : 
      82             :   // sign() == true means negative.
      83             :   inline bool sign() const {
      84      256974 :     int32_t bitfield = RELAXED_READ_INT32_FIELD(this, kBitfieldOffset);
      85             :     return SignBits::decode(static_cast<uint32_t>(bitfield));
      86             :   }
      87             : 
      88             :   inline digit_t digit(int n) const {
      89             :     SLOW_DCHECK(0 <= n && n < length());
      90     3422471 :     Address address = FIELD_ADDR(this, kDigitsOffset + n * kDigitSize);
      91     3422471 :     return *reinterpret_cast<digit_t*>(address);
      92             :   }
      93             : 
      94      432264 :   bool is_zero() const { return length() == 0; }
      95             : 
      96             :   // Only serves to make macros happy; other code should use IsBigInt.
      97             :   bool IsBigIntBase() const { return true; }
      98             : 
      99             :   OBJECT_CONSTRUCTORS(BigIntBase, HeapObject);
     100             : };
     101             : 
     102             : class FreshlyAllocatedBigInt : public BigIntBase {
     103             :   // This class is essentially the publicly accessible abstract version of
     104             :   // MutableBigInt (which is a hidden implementation detail). It serves as
     105             :   // the return type of Factory::NewBigInt, and makes it possible to enforce
     106             :   // casting restrictions:
     107             :   // - FreshlyAllocatedBigInt can be cast explicitly to MutableBigInt
     108             :   //   (with MutableBigInt::Cast) for initialization.
     109             :   // - MutableBigInt can be cast/converted explicitly to BigInt
     110             :   //   (with MutableBigInt::MakeImmutable); is afterwards treated as readonly.
     111             :   // - No accidental implicit casting is possible from BigInt to MutableBigInt
     112             :   //   (and no explicit operator is provided either).
     113             : 
     114             :  public:
     115             :   inline static FreshlyAllocatedBigInt cast(Object object);
     116             :   inline static FreshlyAllocatedBigInt unchecked_cast(Object o) {
     117             :     return bit_cast<FreshlyAllocatedBigInt>(o);
     118             :   }
     119             : 
     120             :   // Clear uninitialized padding space.
     121      161627 :   inline void clear_padding() {
     122             :     if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
     123             :       DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
     124      161627 :       memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
     125      161627 :              FIELD_SIZE(kOptionalPaddingOffset));
     126             :     }
     127      161627 :   }
     128             : 
     129             :  private:
     130             :   // Only serves to make macros happy; other code should use IsBigInt.
     131             :   bool IsFreshlyAllocatedBigInt() const { return true; }
     132             : 
     133             :   OBJECT_CONSTRUCTORS(FreshlyAllocatedBigInt, BigIntBase);
     134             : };
     135             : 
     136             : // Arbitrary precision integers in JavaScript.
     137             : class V8_EXPORT_PRIVATE BigInt : public BigIntBase {
     138             :  public:
     139             :   // Implementation of the Spec methods, see:
     140             :   // https://tc39.github.io/proposal-bigint/#sec-numeric-types
     141             :   // Sections 1.1.1 through 1.1.19.
     142             :   static Handle<BigInt> UnaryMinus(Isolate* isolate, Handle<BigInt> x);
     143             :   static MaybeHandle<BigInt> BitwiseNot(Isolate* isolate, Handle<BigInt> x);
     144             :   static MaybeHandle<BigInt> Exponentiate(Isolate* isolate, Handle<BigInt> base,
     145             :                                           Handle<BigInt> exponent);
     146             :   static MaybeHandle<BigInt> Multiply(Isolate* isolate, Handle<BigInt> x,
     147             :                                       Handle<BigInt> y);
     148             :   static MaybeHandle<BigInt> Divide(Isolate* isolate, Handle<BigInt> x,
     149             :                                     Handle<BigInt> y);
     150             :   static MaybeHandle<BigInt> Remainder(Isolate* isolate, Handle<BigInt> x,
     151             :                                        Handle<BigInt> y);
     152             :   static MaybeHandle<BigInt> Add(Isolate* isolate, Handle<BigInt> x,
     153             :                                  Handle<BigInt> y);
     154             :   static MaybeHandle<BigInt> Subtract(Isolate* isolate, Handle<BigInt> x,
     155             :                                       Handle<BigInt> y);
     156             :   static MaybeHandle<BigInt> LeftShift(Isolate* isolate, Handle<BigInt> x,
     157             :                                        Handle<BigInt> y);
     158             :   static MaybeHandle<BigInt> SignedRightShift(Isolate* isolate,
     159             :                                               Handle<BigInt> x,
     160             :                                               Handle<BigInt> y);
     161             :   static MaybeHandle<BigInt> UnsignedRightShift(Isolate* isolate,
     162             :                                                 Handle<BigInt> x,
     163             :                                                 Handle<BigInt> y);
     164             :   // More convenient version of "bool LessThan(x, y)".
     165             :   static ComparisonResult CompareToBigInt(Handle<BigInt> x, Handle<BigInt> y);
     166             :   static bool EqualToBigInt(BigInt x, BigInt y);
     167             :   static MaybeHandle<BigInt> BitwiseAnd(Isolate* isolate, Handle<BigInt> x,
     168             :                                         Handle<BigInt> y);
     169             :   static MaybeHandle<BigInt> BitwiseXor(Isolate* isolate, Handle<BigInt> x,
     170             :                                         Handle<BigInt> y);
     171             :   static MaybeHandle<BigInt> BitwiseOr(Isolate* isolate, Handle<BigInt> x,
     172             :                                        Handle<BigInt> y);
     173             : 
     174             :   // Other parts of the public interface.
     175             :   static MaybeHandle<BigInt> Increment(Isolate* isolate, Handle<BigInt> x);
     176             :   static MaybeHandle<BigInt> Decrement(Isolate* isolate, Handle<BigInt> x);
     177             : 
     178        2737 :   bool ToBoolean() { return !is_zero(); }
     179         288 :   uint32_t Hash() {
     180             :     // TODO(jkummerow): Improve this. At least use length and sign.
     181         576 :     return is_zero() ? 0 : ComputeLongHash(static_cast<uint64_t>(digit(0)));
     182             :   }
     183             : 
     184             :   static bool EqualToString(Isolate* isolate, Handle<BigInt> x,
     185             :                             Handle<String> y);
     186             :   static bool EqualToNumber(Handle<BigInt> x, Handle<Object> y);
     187             :   static ComparisonResult CompareToString(Isolate* isolate, Handle<BigInt> x,
     188             :                                           Handle<String> y);
     189             :   static ComparisonResult CompareToNumber(Handle<BigInt> x, Handle<Object> y);
     190             :   // Exposed for tests, do not call directly. Use CompareToNumber() instead.
     191             :   static ComparisonResult CompareToDouble(Handle<BigInt> x, double y);
     192             : 
     193             :   static Handle<BigInt> AsIntN(Isolate* isolate, uint64_t n, Handle<BigInt> x);
     194             :   static MaybeHandle<BigInt> AsUintN(Isolate* isolate, uint64_t n,
     195             :                                      Handle<BigInt> x);
     196             : 
     197             :   static Handle<BigInt> FromInt64(Isolate* isolate, int64_t n);
     198             :   static Handle<BigInt> FromUint64(Isolate* isolate, uint64_t n);
     199             :   static MaybeHandle<BigInt> FromWords64(Isolate* isolate, int sign_bit,
     200             :                                          int words64_count,
     201             :                                          const uint64_t* words);
     202             :   int64_t AsInt64(bool* lossless = nullptr);
     203             :   uint64_t AsUint64(bool* lossless = nullptr);
     204             :   int Words64Count();
     205             :   void ToWordsArray64(int* sign_bit, int* words64_count, uint64_t* words);
     206             : 
     207             :   DECL_CAST(BigInt)
     208             :   DECL_VERIFIER(BigInt)
     209             :   DECL_PRINTER(BigInt)
     210             :   void BigIntShortPrint(std::ostream& os);
     211             : 
     212             :   inline static int SizeFor(int length) {
     213      268466 :     return kHeaderSize + length * kDigitSize;
     214             :   }
     215             : 
     216             :   static MaybeHandle<String> ToString(Isolate* isolate, Handle<BigInt> bigint,
     217             :                                       int radix = 10,
     218             :                                       ShouldThrow should_throw = kThrowOnError);
     219             :   // "The Number value for x", see:
     220             :   // https://tc39.github.io/ecma262/#sec-ecmascript-language-types-number-type
     221             :   // Returns a Smi or HeapNumber.
     222             :   static Handle<Object> ToNumber(Isolate* isolate, Handle<BigInt> x);
     223             : 
     224             :   // ECMAScript's NumberToBigInt
     225             :   static MaybeHandle<BigInt> FromNumber(Isolate* isolate,
     226             :                                         Handle<Object> number);
     227             : 
     228             :   // ECMAScript's ToBigInt (throws for Number input)
     229             :   static MaybeHandle<BigInt> FromObject(Isolate* isolate, Handle<Object> obj);
     230             : 
     231             :   class BodyDescriptor;
     232             : 
     233             :  private:
     234             :   friend class StringToBigIntHelper;
     235             :   friend class ValueDeserializer;
     236             :   friend class ValueSerializer;
     237             : 
     238             :   // Special functions for StringToBigIntHelper:
     239             :   static Handle<BigInt> Zero(Isolate* isolate);
     240             :   static MaybeHandle<FreshlyAllocatedBigInt> AllocateFor(
     241             :       Isolate* isolate, int radix, int charcount, ShouldThrow should_throw,
     242             :       PretenureFlag pretenure);
     243             :   static void InplaceMultiplyAdd(Handle<FreshlyAllocatedBigInt> x,
     244             :                                  uintptr_t factor, uintptr_t summand);
     245             :   static Handle<BigInt> Finalize(Handle<FreshlyAllocatedBigInt> x, bool sign);
     246             : 
     247             :   // Special functions for ValueSerializer/ValueDeserializer:
     248             :   uint32_t GetBitfieldForSerialization() const;
     249             :   static int DigitsByteLengthForBitfield(uint32_t bitfield);
     250             :   // Expects {storage} to have a length of at least
     251             :   // {DigitsByteLengthForBitfield(GetBitfieldForSerialization())}.
     252             :   void SerializeDigits(uint8_t* storage);
     253             :   V8_WARN_UNUSED_RESULT static MaybeHandle<BigInt> FromSerializedDigits(
     254             :       Isolate* isolate, uint32_t bitfield, Vector<const uint8_t> digits_storage,
     255             :       PretenureFlag pretenure);
     256             : 
     257        2537 :   OBJECT_CONSTRUCTORS(BigInt, BigIntBase);
     258             : };
     259             : 
     260             : }  // namespace internal
     261             : }  // namespace v8
     262             : 
     263             : #include "src/objects/object-macros-undef.h"
     264             : 
     265             : #endif  // V8_OBJECTS_BIGINT_H_

Generated by: LCOV version 1.10