LCOV - code coverage report
Current view: top level - include - v8-internal.h (source / functions) Hit Total Coverage
Test: app.info Lines: 29 29 100.0 %
Date: 2019-01-20 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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 INCLUDE_V8_INTERNAL_H_
       6             : #define INCLUDE_V8_INTERNAL_H_
       7             : 
       8             : #include <stddef.h>
       9             : #include <stdint.h>
      10             : #include <type_traits>
      11             : 
      12             : #include "v8-version.h"  // NOLINT(build/include)
      13             : #include "v8config.h"    // NOLINT(build/include)
      14             : 
      15             : namespace v8 {
      16             : 
      17             : class Context;
      18             : class Data;
      19             : class Isolate;
      20             : 
      21             : namespace internal {
      22             : 
      23             : class Isolate;
      24             : 
      25             : typedef uintptr_t Address;
      26             : static const Address kNullAddress = 0;
      27             : 
      28             : /**
      29             :  * Configuration of tagging scheme.
      30             :  */
      31             : const int kApiSystemPointerSize = sizeof(void*);
      32             : const int kApiTaggedSize = kApiSystemPointerSize;
      33             : const int kApiDoubleSize = sizeof(double);
      34             : const int kApiIntSize = sizeof(int);
      35             : const int kApiInt64Size = sizeof(int64_t);
      36             : 
      37             : // Tag information for HeapObject.
      38             : const int kHeapObjectTag = 1;
      39             : const int kWeakHeapObjectTag = 3;
      40             : const int kHeapObjectTagSize = 2;
      41             : const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
      42             : 
      43             : // Tag information for Smi.
      44             : const int kSmiTag = 0;
      45             : const int kSmiTagSize = 1;
      46             : const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
      47             : 
      48             : template <size_t tagged_ptr_size>
      49             : struct SmiTagging;
      50             : 
      51             : // Smi constants for systems where tagged pointer is a 32-bit value.
      52             : template <>
      53             : struct SmiTagging<4> {
      54             :   enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
      55             :   V8_INLINE static int SmiToInt(const internal::Address value) {
      56             :     int shift_bits = kSmiTagSize + kSmiShiftSize;
      57             :     // Shift down (requires >> to be sign extending).
      58             :     return static_cast<int>(static_cast<intptr_t>(value)) >> shift_bits;
      59             :   }
      60             :   V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
      61             :     // To be representable as an tagged small integer, the two
      62             :     // most-significant bits of 'value' must be either 00 or 11 due to
      63             :     // sign-extension. To check this we add 01 to the two
      64             :     // most-significant bits, and check if the most-significant bit is 0.
      65             :     //
      66             :     // CAUTION: The original code below:
      67             :     // bool result = ((value + 0x40000000) & 0x80000000) == 0;
      68             :     // may lead to incorrect results according to the C language spec, and
      69             :     // in fact doesn't work correctly with gcc4.1.1 in some cases: The
      70             :     // compiler may produce undefined results in case of signed integer
      71             :     // overflow. The computation must be done w/ unsigned ints.
      72             :     return static_cast<uintptr_t>(value) + 0x40000000U < 0x80000000U;
      73             :   }
      74             : };
      75             : 
      76             : // Smi constants for systems where tagged pointer is a 64-bit value.
      77             : template <>
      78             : struct SmiTagging<8> {
      79             :   enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
      80             :   V8_INLINE static int SmiToInt(const internal::Address value) {
      81             :     int shift_bits = kSmiTagSize + kSmiShiftSize;
      82             :     // Shift down and throw away top 32 bits.
      83  8070399941 :     return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
      84             :   }
      85             :   V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
      86             :     // To be representable as a long smi, the value must be a 32-bit integer.
      87        3307 :     return (value == static_cast<int32_t>(value));
      88             :   }
      89             : };
      90             : 
      91             : #if defined(V8_COMPRESS_POINTERS)
      92             : static_assert(
      93             :     kApiSystemPointerSize == kApiInt64Size,
      94             :     "Pointer compression can be enabled only for 64-bit architectures");
      95             : #endif
      96             : 
      97             : #if defined(V8_COMPRESS_POINTERS) || defined(V8_31BIT_SMIS_ON_64BIT_ARCH)
      98             : typedef SmiTagging<kApiIntSize> PlatformSmiTagging;
      99             : #else
     100             : typedef SmiTagging<kApiSystemPointerSize> PlatformSmiTagging;
     101             : #endif
     102             : 
     103             : const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
     104             : const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
     105             : const int kSmiMinValue = (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
     106             : const int kSmiMaxValue = -(kSmiMinValue + 1);
     107             : constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
     108             : constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
     109             : 
     110             : V8_INLINE static constexpr internal::Address IntToSmi(int value) {
     111  1498519192 :   return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
     112  1498519886 :          kSmiTag;
     113             : }
     114             : 
     115             : /**
     116             :  * This class exports constants and functionality from within v8 that
     117             :  * is necessary to implement inline functions in the v8 api.  Don't
     118             :  * depend on functions and constants defined here.
     119             :  */
     120             : class Internals {
     121             :  public:
     122             :   // These values match non-compiler-dependent values defined within
     123             :   // the implementation of v8.
     124             :   static const int kHeapObjectMapOffset = 0;
     125             :   static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiIntSize;
     126             :   static const int kStringResourceOffset = 1 * kApiTaggedSize + 2 * kApiIntSize;
     127             : 
     128             :   static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
     129             :   static const int kForeignAddressOffset = kApiTaggedSize;
     130             :   static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
     131             :   static const int kJSObjectHeaderSizeForEmbedderFields =
     132             :       (kJSObjectHeaderSize + kApiSystemPointerSize - 1) &
     133             :       -kApiSystemPointerSize;
     134             :   static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
     135             :   static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
     136             :   static const int kEmbedderDataSlotSize =
     137             : #ifdef V8_COMPRESS_POINTERS
     138             :       2 *
     139             : #endif
     140             :       kApiSystemPointerSize;
     141             :   static const int kNativeContextEmbedderDataOffset = 7 * kApiTaggedSize;
     142             :   static const int kFullStringRepresentationMask = 0x0f;
     143             :   static const int kStringEncodingMask = 0x8;
     144             :   static const int kExternalTwoByteRepresentationTag = 0x02;
     145             :   static const int kExternalOneByteRepresentationTag = 0x0a;
     146             : 
     147             :   static const uint32_t kNumIsolateDataSlots = 4;
     148             : 
     149             :   static const int kIsolateEmbedderDataOffset = 0;
     150             :   static const int kExternalMemoryOffset =
     151             :       kNumIsolateDataSlots * kApiTaggedSize;
     152             :   static const int kExternalMemoryLimitOffset =
     153             :       kExternalMemoryOffset + kApiInt64Size;
     154             :   static const int kExternalMemoryAtLastMarkCompactOffset =
     155             :       kExternalMemoryLimitOffset + kApiInt64Size;
     156             :   static const int kIsolateRootsOffset =
     157             :       kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size;
     158             : 
     159             :   static const int kUndefinedValueRootIndex = 4;
     160             :   static const int kTheHoleValueRootIndex = 5;
     161             :   static const int kNullValueRootIndex = 6;
     162             :   static const int kTrueValueRootIndex = 7;
     163             :   static const int kFalseValueRootIndex = 8;
     164             :   static const int kEmptyStringRootIndex = 9;
     165             : 
     166             :   static const int kNodeClassIdOffset = 1 * kApiTaggedSize;
     167             :   static const int kNodeFlagsOffset = 1 * kApiTaggedSize + 3;
     168             :   static const int kNodeStateMask = 0x7;
     169             :   static const int kNodeStateIsWeakValue = 2;
     170             :   static const int kNodeStateIsPendingValue = 3;
     171             :   static const int kNodeStateIsNearDeathValue = 4;
     172             :   static const int kNodeIsIndependentShift = 3;
     173             :   static const int kNodeIsActiveShift = 4;
     174             : 
     175             :   static const int kFirstNonstringType = 0x80;
     176             :   static const int kOddballType = 0x83;
     177             :   static const int kForeignType = 0x87;
     178             :   static const int kJSSpecialApiObjectType = 0x410;
     179             :   static const int kJSApiObjectType = 0x420;
     180             :   static const int kJSObjectType = 0x421;
     181             : 
     182             :   static const int kUndefinedOddballKind = 5;
     183             :   static const int kNullOddballKind = 3;
     184             : 
     185             :   // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
     186             :   // incremental GC once the external memory reaches this limit.
     187             :   static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
     188             : 
     189             :   V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
     190             :   V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
     191             : #ifdef V8_ENABLE_CHECKS
     192             :     CheckInitializedImpl(isolate);
     193             : #endif
     194             :   }
     195             : 
     196             :   V8_INLINE static bool HasHeapObjectTag(const internal::Address value) {
     197   230973419 :     return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
     198             :   }
     199             : 
     200             :   V8_INLINE static int SmiValue(const internal::Address value) {
     201             :     return PlatformSmiTagging::SmiToInt(value);
     202             :   }
     203             : 
     204             :   V8_INLINE static constexpr internal::Address IntToSmi(int value) {
     205             :     return internal::IntToSmi(value);
     206             :   }
     207             : 
     208             :   V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
     209             :     return PlatformSmiTagging::IsValidSmi(value);
     210             :   }
     211             : 
     212             :   V8_INLINE static int GetInstanceType(const internal::Address obj) {
     213             :     typedef internal::Address A;
     214             :     A map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
     215     8815106 :     return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
     216             :   }
     217             : 
     218             :   V8_INLINE static int GetOddballKind(const internal::Address obj) {
     219             :     return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
     220             :   }
     221             : 
     222             :   V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
     223          31 :     int representation = (instance_type & kFullStringRepresentationMask);
     224             :     return representation == kExternalTwoByteRepresentationTag;
     225             :   }
     226             : 
     227             :   V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) {
     228             :     uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
     229          46 :     return *addr & static_cast<uint8_t>(1U << shift);
     230             :   }
     231             : 
     232             :   V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value,
     233             :                                        int shift) {
     234             :     uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
     235             :     uint8_t mask = static_cast<uint8_t>(1U << shift);
     236      104874 :     *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
     237             :   }
     238             : 
     239             :   V8_INLINE static uint8_t GetNodeState(internal::Address* obj) {
     240             :     uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
     241          20 :     return *addr & kNodeStateMask;
     242             :   }
     243             : 
     244             :   V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) {
     245             :     uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
     246             :     *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
     247             :   }
     248             : 
     249             :   V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
     250             :                                         void* data) {
     251          50 :     internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
     252          40 :                              kIsolateEmbedderDataOffset +
     253          90 :                              slot * kApiSystemPointerSize;
     254       58961 :     *reinterpret_cast<void**>(addr) = data;
     255             :   }
     256             : 
     257             :   V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
     258             :                                          uint32_t slot) {
     259         100 :     internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
     260          60 :                              kIsolateEmbedderDataOffset +
     261         160 :                              slot * kApiSystemPointerSize;
     262      345028 :     return *reinterpret_cast<void* const*>(addr);
     263             :   }
     264             : 
     265             :   V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) {
     266             :     internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
     267     2291681 :                              kIsolateRootsOffset +
     268     6973407 :                              index * kApiSystemPointerSize;
     269     6048283 :     return reinterpret_cast<internal::Address*>(addr);
     270             :   }
     271             : 
     272             :   template <typename T>
     273             :   V8_INLINE static T ReadRawField(internal::Address heap_object_ptr,
     274             :                                   int offset) {
     275    58854791 :     internal::Address addr = heap_object_ptr + offset - kHeapObjectTag;
     276    58854791 :     return *reinterpret_cast<const T*>(addr);
     277             :   }
     278             : 
     279             :   V8_INLINE static internal::Address ReadTaggedPointerField(
     280             :       internal::Address heap_object_ptr, int offset) {
     281             : #ifdef V8_COMPRESS_POINTERS
     282             :     int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
     283             :     internal::Address root = GetRootFromOnHeapAddress(heap_object_ptr);
     284             :     return root + static_cast<internal::Address>(static_cast<intptr_t>(value));
     285             : #else
     286             :     return ReadRawField<internal::Address>(heap_object_ptr, offset);
     287             : #endif
     288             :   }
     289             : 
     290             :   V8_INLINE static internal::Address ReadTaggedSignedField(
     291             :       internal::Address heap_object_ptr, int offset) {
     292             : #ifdef V8_COMPRESS_POINTERS
     293             :     int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
     294             :     return static_cast<internal::Address>(static_cast<intptr_t>(value));
     295             : #else
     296             :     return ReadRawField<internal::Address>(heap_object_ptr, offset);
     297             : #endif
     298             :   }
     299             : 
     300             :   V8_INLINE static internal::Address ReadTaggedAnyField(
     301             :       internal::Address heap_object_ptr, int offset) {
     302             : #ifdef V8_COMPRESS_POINTERS
     303             :     int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
     304             :     internal::Address root_mask = static_cast<internal::Address>(
     305             :         -static_cast<intptr_t>(value & kSmiTagMask));
     306             :     internal::Address root_or_zero =
     307             :         root_mask & GetRootFromOnHeapAddress(heap_object_ptr);
     308             :     return root_or_zero +
     309             :            static_cast<internal::Address>(static_cast<intptr_t>(value));
     310             : #else
     311             :     return ReadRawField<internal::Address>(heap_object_ptr, offset);
     312             : #endif
     313             :   }
     314             : 
     315             : #ifdef V8_COMPRESS_POINTERS
     316             :   static constexpr size_t kPtrComprHeapReservationSize = size_t{1} << 32;
     317             :   static constexpr size_t kPtrComprIsolateRootBias =
     318             :       kPtrComprHeapReservationSize / 2;
     319             :   static constexpr size_t kPtrComprIsolateRootAlignment = size_t{1} << 32;
     320             : 
     321             :   V8_INLINE static internal::Address GetRootFromOnHeapAddress(
     322             :       internal::Address addr) {
     323             :     return (addr + kPtrComprIsolateRootBias) &
     324             :            -static_cast<intptr_t>(kPtrComprIsolateRootAlignment);
     325             :   }
     326             : 
     327             : #else
     328             : 
     329             :   template <typename T>
     330             :   V8_INLINE static T ReadEmbedderData(const v8::Context* context, int index) {
     331             :     typedef internal::Address A;
     332             :     typedef internal::Internals I;
     333      182393 :     A ctx = *reinterpret_cast<const A*>(context);
     334             :     A embedder_data =
     335             :         I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
     336             :     int value_offset =
     337         654 :         I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
     338             :     return I::ReadRawField<T>(embedder_data, value_offset);
     339             :   }
     340             : #endif  // V8_COMPRESS_POINTERS
     341             : };
     342             : 
     343             : // Only perform cast check for types derived from v8::Data since
     344             : // other types do not implement the Cast method.
     345             : template <bool PerformCheck>
     346             : struct CastCheck {
     347             :   template <class T>
     348             :   static void Perform(T* data);
     349             : };
     350             : 
     351             : template <>
     352             : template <class T>
     353          75 : void CastCheck<true>::Perform(T* data) {
     354             :   T::Cast(data);
     355          75 : }
     356             : 
     357             : template <>
     358             : template <class T>
     359           5 : void CastCheck<false>::Perform(T* data) {}
     360             : 
     361             : template <class T>
     362             : V8_INLINE void PerformCastCheck(T* data) {
     363          80 :   CastCheck<std::is_base_of<Data, T>::value>::Perform(data);
     364             : }
     365             : 
     366             : // {obj} must be the raw tagged pointer representation of a HeapObject
     367             : // that's guaranteed to never be in ReadOnlySpace.
     368             : V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
     369             : 
     370             : }  // namespace internal
     371             : }  // namespace v8
     372             : 
     373             : #endif  // INCLUDE_V8_INTERNAL_H_

Generated by: LCOV version 1.10