| | |
| | |
| | |
| |
|
| | #ifndef INCLUDE_V8_INTERNAL_H_ |
| | #define INCLUDE_V8_INTERNAL_H_ |
| |
|
| | #include <stddef.h> |
| | #include <stdint.h> |
| | #include <string.h> |
| | #include <type_traits> |
| |
|
| | #include "v8-version.h" |
| | #include "v8config.h" |
| |
|
| | namespace v8 { |
| |
|
| | class Context; |
| | class Data; |
| | class Isolate; |
| |
|
| | namespace internal { |
| |
|
| | class Isolate; |
| |
|
| | typedef uintptr_t Address; |
| | static const Address kNullAddress = 0; |
| |
|
| | |
| | |
| | |
| | const int kApiSystemPointerSize = sizeof(void*); |
| | const int kApiDoubleSize = sizeof(double); |
| | const int kApiInt32Size = sizeof(int32_t); |
| | const int kApiInt64Size = sizeof(int64_t); |
| |
|
| | |
| | const int kHeapObjectTag = 1; |
| | const int kWeakHeapObjectTag = 3; |
| | const int kHeapObjectTagSize = 2; |
| | const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1; |
| |
|
| | |
| | const int kSmiTag = 0; |
| | const int kSmiTagSize = 1; |
| | const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1; |
| |
|
| | template <size_t tagged_ptr_size> |
| | struct SmiTagging; |
| |
|
| | constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1}; |
| | constexpr uintptr_t kUintptrAllBitsSet = |
| | static_cast<uintptr_t>(kIntptrAllBitsSet); |
| |
|
| | |
| | template <> |
| | struct SmiTagging<4> { |
| | enum { kSmiShiftSize = 0, kSmiValueSize = 31 }; |
| |
|
| | static constexpr intptr_t kSmiMinValue = |
| | static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1)); |
| | static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); |
| |
|
| | V8_INLINE static int SmiToInt(const internal::Address value) { |
| | int shift_bits = kSmiTagSize + kSmiShiftSize; |
| | |
| | return static_cast<int32_t>(static_cast<uint32_t>(value)) >> shift_bits; |
| | } |
| | V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { |
| | |
| | |
| | |
| | return (static_cast<uintptr_t>(value) - |
| | static_cast<uintptr_t>(kSmiMinValue)) <= |
| | (static_cast<uintptr_t>(kSmiMaxValue) - |
| | static_cast<uintptr_t>(kSmiMinValue)); |
| | } |
| | }; |
| |
|
| | |
| | template <> |
| | struct SmiTagging<8> { |
| | enum { kSmiShiftSize = 31, kSmiValueSize = 32 }; |
| |
|
| | static constexpr intptr_t kSmiMinValue = |
| | static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1)); |
| | static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1); |
| |
|
| | V8_INLINE static int SmiToInt(const internal::Address value) { |
| | int shift_bits = kSmiTagSize + kSmiShiftSize; |
| | |
| | return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits); |
| | } |
| | V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { |
| | |
| | return (value == static_cast<int32_t>(value)); |
| | } |
| | }; |
| |
|
| | #ifdef V8_COMPRESS_POINTERS |
| | static_assert( |
| | kApiSystemPointerSize == kApiInt64Size, |
| | "Pointer compression can be enabled only for 64-bit architectures"); |
| | const int kApiTaggedSize = kApiInt32Size; |
| | #else |
| | const int kApiTaggedSize = kApiSystemPointerSize; |
| | #endif |
| |
|
| | constexpr bool PointerCompressionIsEnabled() { |
| | return kApiTaggedSize != kApiSystemPointerSize; |
| | } |
| |
|
| | constexpr bool HeapSandboxIsEnabled() { |
| | #ifdef V8_HEAP_SANDBOX |
| | return true; |
| | #else |
| | return false; |
| | #endif |
| | } |
| |
|
| | using ExternalPointer_t = Address; |
| |
|
| | #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH |
| | using PlatformSmiTagging = SmiTagging<kApiInt32Size>; |
| | #else |
| | using PlatformSmiTagging = SmiTagging<kApiTaggedSize>; |
| | #endif |
| |
|
| | |
| | |
| | const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize; |
| | const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize; |
| | const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue); |
| | const int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue); |
| | constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; } |
| | constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; } |
| |
|
| | V8_INLINE static constexpr internal::Address IntToSmi(int value) { |
| | return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) | |
| | kSmiTag; |
| | } |
| |
|
| | |
| | |
| | V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj); |
| |
|
| | |
| | |
| | |
| | V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | class Internals { |
| | public: |
| | |
| | |
| | static const int kHeapObjectMapOffset = 0; |
| | static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiInt32Size; |
| | static const int kStringResourceOffset = |
| | 1 * kApiTaggedSize + 2 * kApiInt32Size; |
| |
|
| | static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize; |
| | static const int kJSObjectHeaderSize = 3 * kApiTaggedSize; |
| | static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize; |
| | static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize; |
| | static const int kEmbedderDataSlotSize = kApiSystemPointerSize; |
| | static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize; |
| | static const int kFullStringRepresentationMask = 0x0f; |
| | static const int kStringEncodingMask = 0x8; |
| | static const int kExternalTwoByteRepresentationTag = 0x02; |
| | static const int kExternalOneByteRepresentationTag = 0x0a; |
| |
|
| | static const uint32_t kNumIsolateDataSlots = 4; |
| |
|
| | |
| | static const int kIsolateEmbedderDataOffset = 0; |
| | static const int kExternalMemoryOffset = |
| | kNumIsolateDataSlots * kApiSystemPointerSize; |
| | static const int kExternalMemoryLimitOffset = |
| | kExternalMemoryOffset + kApiInt64Size; |
| | static const int kExternalMemoryLowSinceMarkCompactOffset = |
| | kExternalMemoryLimitOffset + kApiInt64Size; |
| | static const int kIsolateFastCCallCallerFpOffset = |
| | kExternalMemoryLowSinceMarkCompactOffset + kApiInt64Size; |
| | static const int kIsolateFastCCallCallerPcOffset = |
| | kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize; |
| | static const int kIsolateStackGuardOffset = |
| | kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize; |
| | static const int kIsolateRootsOffset = |
| | kIsolateStackGuardOffset + 7 * kApiSystemPointerSize; |
| |
|
| | static const int kUndefinedValueRootIndex = 4; |
| | static const int kTheHoleValueRootIndex = 5; |
| | static const int kNullValueRootIndex = 6; |
| | static const int kTrueValueRootIndex = 7; |
| | static const int kFalseValueRootIndex = 8; |
| | static const int kEmptyStringRootIndex = 9; |
| |
|
| | static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize; |
| | static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3; |
| | static const int kNodeStateMask = 0x7; |
| | static const int kNodeStateIsWeakValue = 2; |
| | static const int kNodeStateIsPendingValue = 3; |
| |
|
| | static const int kFirstNonstringType = 0x40; |
| | static const int kOddballType = 0x43; |
| | static const int kForeignType = 0x46; |
| | static const int kJSSpecialApiObjectType = 0x410; |
| | static const int kJSApiObjectType = 0x420; |
| | static const int kJSObjectType = 0x421; |
| |
|
| | static const int kUndefinedOddballKind = 5; |
| | static const int kNullOddballKind = 3; |
| |
|
| | |
| | |
| | static const int kThrowOnError = 0; |
| | static const int kDontThrow = 1; |
| | static const int kInferShouldThrowMode = 2; |
| |
|
| | |
| | |
| | static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024; |
| |
|
| | V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate); |
| | V8_INLINE static void CheckInitialized(v8::Isolate* isolate) { |
| | #ifdef V8_ENABLE_CHECKS |
| | CheckInitializedImpl(isolate); |
| | #endif |
| | } |
| |
|
| | V8_INLINE static bool HasHeapObjectTag(const internal::Address value) { |
| | return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag); |
| | } |
| |
|
| | V8_INLINE static int SmiValue(const internal::Address value) { |
| | return PlatformSmiTagging::SmiToInt(value); |
| | } |
| |
|
| | V8_INLINE static constexpr internal::Address IntToSmi(int value) { |
| | return internal::IntToSmi(value); |
| | } |
| |
|
| | V8_INLINE static constexpr bool IsValidSmi(intptr_t value) { |
| | return PlatformSmiTagging::IsValidSmi(value); |
| | } |
| |
|
| | V8_INLINE static int GetInstanceType(const internal::Address obj) { |
| | typedef internal::Address A; |
| | A map = ReadTaggedPointerField(obj, kHeapObjectMapOffset); |
| | return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset); |
| | } |
| |
|
| | V8_INLINE static int GetOddballKind(const internal::Address obj) { |
| | return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset)); |
| | } |
| |
|
| | V8_INLINE static bool IsExternalTwoByteString(int instance_type) { |
| | int representation = (instance_type & kFullStringRepresentationMask); |
| | return representation == kExternalTwoByteRepresentationTag; |
| | } |
| |
|
| | V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) { |
| | uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; |
| | return *addr & static_cast<uint8_t>(1U << shift); |
| | } |
| |
|
| | V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value, |
| | int shift) { |
| | uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; |
| | uint8_t mask = static_cast<uint8_t>(1U << shift); |
| | *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift)); |
| | } |
| |
|
| | V8_INLINE static uint8_t GetNodeState(internal::Address* obj) { |
| | uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; |
| | return *addr & kNodeStateMask; |
| | } |
| |
|
| | V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) { |
| | uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset; |
| | *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value); |
| | } |
| |
|
| | V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot, |
| | void* data) { |
| | internal::Address addr = reinterpret_cast<internal::Address>(isolate) + |
| | kIsolateEmbedderDataOffset + |
| | slot * kApiSystemPointerSize; |
| | *reinterpret_cast<void**>(addr) = data; |
| | } |
| |
|
| | V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate, |
| | uint32_t slot) { |
| | internal::Address addr = reinterpret_cast<internal::Address>(isolate) + |
| | kIsolateEmbedderDataOffset + |
| | slot * kApiSystemPointerSize; |
| | return *reinterpret_cast<void* const*>(addr); |
| | } |
| |
|
| | V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) { |
| | internal::Address addr = reinterpret_cast<internal::Address>(isolate) + |
| | kIsolateRootsOffset + |
| | index * kApiSystemPointerSize; |
| | return reinterpret_cast<internal::Address*>(addr); |
| | } |
| |
|
| | template <typename T> |
| | V8_INLINE static T ReadRawField(internal::Address heap_object_ptr, |
| | int offset) { |
| | internal::Address addr = heap_object_ptr + offset - kHeapObjectTag; |
| | #ifdef V8_COMPRESS_POINTERS |
| | if (sizeof(T) > kApiTaggedSize) { |
| | |
| | |
| | |
| | |
| | T r; |
| | memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T)); |
| | return r; |
| | } |
| | #endif |
| | return *reinterpret_cast<const T*>(addr); |
| | } |
| |
|
| | V8_INLINE static internal::Address ReadTaggedPointerField( |
| | internal::Address heap_object_ptr, int offset) { |
| | #ifdef V8_COMPRESS_POINTERS |
| | uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset); |
| | internal::Address root = GetRootFromOnHeapAddress(heap_object_ptr); |
| | return root + static_cast<internal::Address>(static_cast<uintptr_t>(value)); |
| | #else |
| | return ReadRawField<internal::Address>(heap_object_ptr, offset); |
| | #endif |
| | } |
| |
|
| | V8_INLINE static internal::Address ReadTaggedSignedField( |
| | internal::Address heap_object_ptr, int offset) { |
| | #ifdef V8_COMPRESS_POINTERS |
| | uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset); |
| | return static_cast<internal::Address>(static_cast<uintptr_t>(value)); |
| | #else |
| | return ReadRawField<internal::Address>(heap_object_ptr, offset); |
| | #endif |
| | } |
| |
|
| | V8_INLINE static internal::Isolate* GetIsolateForHeapSandbox( |
| | internal::Address obj) { |
| | #ifdef V8_HEAP_SANDBOX |
| | return internal::IsolateFromNeverReadOnlySpaceObject(obj); |
| | #else |
| | |
| | return nullptr; |
| | #endif |
| | } |
| |
|
| | V8_INLINE static internal::Address ReadExternalPointerField( |
| | internal::Isolate* isolate, internal::Address heap_object_ptr, |
| | int offset) { |
| | internal::Address value = ReadRawField<Address>(heap_object_ptr, offset); |
| | #ifdef V8_HEAP_SANDBOX |
| | |
| | if (value) value = DecodeExternalPointer(isolate, value); |
| | #endif |
| | return value; |
| | } |
| |
|
| | #ifdef V8_COMPRESS_POINTERS |
| | |
| | static constexpr size_t kPtrComprHeapReservationSize = size_t{1} << 32; |
| | static constexpr size_t kPtrComprIsolateRootAlignment = size_t{1} << 32; |
| |
|
| | |
| | static constexpr uint32_t kExternalPointerSalt = |
| | 0x7fffffff & ~static_cast<uint32_t>(kHeapObjectTagMask); |
| |
|
| | V8_INLINE static internal::Address GetRootFromOnHeapAddress( |
| | internal::Address addr) { |
| | return addr & -static_cast<intptr_t>(kPtrComprIsolateRootAlignment); |
| | } |
| |
|
| | V8_INLINE static internal::Address DecompressTaggedAnyField( |
| | internal::Address heap_object_ptr, uint32_t value) { |
| | internal::Address root = GetRootFromOnHeapAddress(heap_object_ptr); |
| | return root + static_cast<internal::Address>(static_cast<uintptr_t>(value)); |
| | } |
| |
|
| | V8_INLINE static Address DecodeExternalPointer( |
| | const Isolate* isolate, ExternalPointer_t encoded_pointer) { |
| | #ifndef V8_HEAP_SANDBOX |
| | return encoded_pointer; |
| | #else |
| | return encoded_pointer ^ kExternalPointerSalt; |
| | #endif |
| | } |
| | #endif |
| | }; |
| |
|
| | |
| | |
| | template <bool PerformCheck> |
| | struct CastCheck { |
| | template <class T> |
| | static void Perform(T* data); |
| | }; |
| |
|
| | template <> |
| | template <class T> |
| | void CastCheck<true>::Perform(T* data) { |
| | T::Cast(data); |
| | } |
| |
|
| | template <> |
| | template <class T> |
| | void CastCheck<false>::Perform(T* data) {} |
| |
|
| | template <class T> |
| | V8_INLINE void PerformCastCheck(T* data) { |
| | CastCheck<std::is_base_of<Data, T>::value>::Perform(data); |
| | } |
| |
|
| | |
| | |
| | class BackingStoreBase {}; |
| |
|
| | } |
| | } |
| |
|
| | #endif |
| |
|