V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
v8-internal.h
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 typedef uintptr_t Address;
24 static const Address kNullAddress = 0;
25 
29 const int kApiSystemPointerSize = sizeof(void*);
30 const int kApiTaggedSize = kApiSystemPointerSize;
31 const int kApiDoubleSize = sizeof(double);
32 const int kApiIntSize = sizeof(int);
33 const int kApiInt64Size = sizeof(int64_t);
34 
35 // Tag information for HeapObject.
36 const int kHeapObjectTag = 1;
37 const int kWeakHeapObjectTag = 3;
38 const int kHeapObjectTagSize = 2;
39 const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
40 
41 // Tag information for Smi.
42 const int kSmiTag = 0;
43 const int kSmiTagSize = 1;
44 const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
45 
46 template <size_t tagged_ptr_size>
47 struct SmiTagging;
48 
49 // Smi constants for systems where tagged pointer is a 32-bit value.
50 template <>
51 struct SmiTagging<4> {
52  enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
53  V8_INLINE static int SmiToInt(const internal::Address value) {
54  int shift_bits = kSmiTagSize + kSmiShiftSize;
55  // Shift down (requires >> to be sign extending).
56  return static_cast<int>(static_cast<intptr_t>(value)) >> shift_bits;
57  }
58  V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
59  // To be representable as an tagged small integer, the two
60  // most-significant bits of 'value' must be either 00 or 11 due to
61  // sign-extension. To check this we add 01 to the two
62  // most-significant bits, and check if the most-significant bit is 0.
63  //
64  // CAUTION: The original code below:
65  // bool result = ((value + 0x40000000) & 0x80000000) == 0;
66  // may lead to incorrect results according to the C language spec, and
67  // in fact doesn't work correctly with gcc4.1.1 in some cases: The
68  // compiler may produce undefined results in case of signed integer
69  // overflow. The computation must be done w/ unsigned ints.
70  return static_cast<uintptr_t>(value) + 0x40000000U < 0x80000000U;
71  }
72 };
73 
74 // Smi constants for systems where tagged pointer is a 64-bit value.
75 template <>
76 struct SmiTagging<8> {
77  enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
78  V8_INLINE static int SmiToInt(const internal::Address value) {
79  int shift_bits = kSmiTagSize + kSmiShiftSize;
80  // Shift down and throw away top 32 bits.
81  return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
82  }
83  V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
84  // To be representable as a long smi, the value must be a 32-bit integer.
85  return (value == static_cast<int32_t>(value));
86  }
87 };
88 
89 #if defined(V8_COMPRESS_POINTERS) || defined(V8_31BIT_SMIS_ON_64BIT_ARCH)
90 static_assert(
91  kApiSystemPointerSize == kApiInt64Size,
92  "Pointer compression can be enabled only for 64-bit architectures");
94 #else
96 #endif
97 
98 const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
99 const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
100 const int kSmiMinValue = (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
101 const int kSmiMaxValue = -(kSmiMinValue + 1);
102 constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
103 constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
104 
105 V8_INLINE static constexpr internal::Address IntToSmi(int value) {
106  return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
107  kSmiTag;
108 }
109 
115 class Internals {
116  public:
117  // These values match non-compiler-dependent values defined within
118  // the implementation of v8.
119  static const int kHeapObjectMapOffset = 0;
120  static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiIntSize;
121  static const int kStringResourceOffset = 1 * kApiTaggedSize + 2 * kApiIntSize;
122 
123  static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
124  static const int kForeignAddressOffset = kApiTaggedSize;
125  static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
126  static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
127  static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
128  static const int kEmbedderDataSlotSize =
129 #ifdef V8_COMPRESS_POINTERS
130  2 *
131 #endif
132  kApiSystemPointerSize;
133  static const int kNativeContextEmbedderDataOffset = 7 * kApiTaggedSize;
134  static const int kFullStringRepresentationMask = 0x0f;
135  static const int kStringEncodingMask = 0x8;
136  static const int kExternalTwoByteRepresentationTag = 0x02;
137  static const int kExternalOneByteRepresentationTag = 0x0a;
138 
139  static const uint32_t kNumIsolateDataSlots = 4;
140 
141  static const int kIsolateEmbedderDataOffset = 0;
142  static const int kExternalMemoryOffset =
143  kNumIsolateDataSlots * kApiTaggedSize;
144  static const int kExternalMemoryLimitOffset =
145  kExternalMemoryOffset + kApiInt64Size;
146  static const int kExternalMemoryAtLastMarkCompactOffset =
147  kExternalMemoryLimitOffset + kApiInt64Size;
148  static const int kIsolateRootsOffset =
149  kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size;
150 
151  static const int kUndefinedValueRootIndex = 4;
152  static const int kTheHoleValueRootIndex = 5;
153  static const int kNullValueRootIndex = 6;
154  static const int kTrueValueRootIndex = 7;
155  static const int kFalseValueRootIndex = 8;
156  static const int kEmptyStringRootIndex = 9;
157 
158  static const int kNodeClassIdOffset = 1 * kApiTaggedSize;
159  static const int kNodeFlagsOffset = 1 * kApiTaggedSize + 3;
160  static const int kNodeStateMask = 0x7;
161  static const int kNodeStateIsWeakValue = 2;
162  static const int kNodeStateIsPendingValue = 3;
163  static const int kNodeStateIsNearDeathValue = 4;
164  static const int kNodeIsIndependentShift = 3;
165  static const int kNodeIsActiveShift = 4;
166 
167  static const int kFirstNonstringType = 0x80;
168  static const int kOddballType = 0x83;
169  static const int kForeignType = 0x87;
170  static const int kJSSpecialApiObjectType = 0x410;
171  static const int kJSApiObjectType = 0x420;
172  static const int kJSObjectType = 0x421;
173 
174  static const int kUndefinedOddballKind = 5;
175  static const int kNullOddballKind = 3;
176 
177  // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
178  // incremental GC once the external memory reaches this limit.
179  static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
180 
181  V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
182  V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
183 #ifdef V8_ENABLE_CHECKS
184  CheckInitializedImpl(isolate);
185 #endif
186  }
187 
188  V8_INLINE static bool HasHeapObjectTag(const internal::Address value) {
189  return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
190  }
191 
192  V8_INLINE static int SmiValue(const internal::Address value) {
193  return PlatformSmiTagging::SmiToInt(value);
194  }
195 
196  V8_INLINE static constexpr internal::Address IntToSmi(int value) {
197  return internal::IntToSmi(value);
198  }
199 
200  V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
201  return PlatformSmiTagging::IsValidSmi(value);
202  }
203 
204  V8_INLINE static int GetInstanceType(const internal::Address obj) {
205  typedef internal::Address A;
206  A map = ReadField<A>(obj, kHeapObjectMapOffset);
207  return ReadField<uint16_t>(map, kMapInstanceTypeOffset);
208  }
209 
210  V8_INLINE static int GetOddballKind(const internal::Address obj) {
211  return SmiValue(ReadField<internal::Address>(obj, kOddballKindOffset));
212  }
213 
214  V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
215  int representation = (instance_type & kFullStringRepresentationMask);
216  return representation == kExternalTwoByteRepresentationTag;
217  }
218 
219  V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) {
220  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
221  return *addr & static_cast<uint8_t>(1U << shift);
222  }
223 
224  V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value,
225  int shift) {
226  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
227  uint8_t mask = static_cast<uint8_t>(1U << shift);
228  *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
229  }
230 
231  V8_INLINE static uint8_t GetNodeState(internal::Address* obj) {
232  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
233  return *addr & kNodeStateMask;
234  }
235 
236  V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) {
237  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
238  *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
239  }
240 
241  V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
242  void* data) {
243  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
244  kIsolateEmbedderDataOffset +
245  slot * kApiSystemPointerSize;
246  *reinterpret_cast<void**>(addr) = data;
247  }
248 
249  V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
250  uint32_t slot) {
251  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
252  kIsolateEmbedderDataOffset +
253  slot * kApiSystemPointerSize;
254  return *reinterpret_cast<void* const*>(addr);
255  }
256 
257  V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) {
258  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
259  kIsolateRootsOffset +
260  index * kApiSystemPointerSize;
261  return reinterpret_cast<internal::Address*>(addr);
262  }
263 
264  template <typename T>
265  V8_INLINE static T ReadField(const internal::Address heap_object_ptr,
266  int offset) {
267  internal::Address addr = heap_object_ptr + offset - kHeapObjectTag;
268  return *reinterpret_cast<const T*>(addr);
269  }
270 
271 #ifndef V8_COMPRESS_POINTERS
272  template <typename T>
273  V8_INLINE static T ReadEmbedderData(const v8::Context* context, int index) {
274  typedef internal::Address A;
275  typedef internal::Internals I;
276  A ctx = *reinterpret_cast<const A*>(context);
277  A embedder_data = I::ReadField<A>(ctx, I::kNativeContextEmbedderDataOffset);
278  int value_offset =
279  I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
280  return I::ReadField<T>(embedder_data, value_offset);
281  }
282 #endif
283 };
284 
285 // Only perform cast check for types derived from v8::Data since
286 // other types do not implement the Cast method.
287 template <bool PerformCheck>
288 struct CastCheck {
289  template <class T>
290  static void Perform(T* data);
291 };
292 
293 template <>
294 template <class T>
295 void CastCheck<true>::Perform(T* data) {
296  T::Cast(data);
297 }
298 
299 template <>
300 template <class T>
301 void CastCheck<false>::Perform(T* data) {}
302 
303 template <class T>
304 V8_INLINE void PerformCastCheck(T* data) {
305  CastCheck<std::is_base_of<Data, T>::value>::Perform(data);
306 }
307 
308 } // namespace internal
309 } // namespace v8
310 
311 #endif // INCLUDE_V8_INTERNAL_H_
Definition: libplatform.h:13