My Project
V8 API Reference Guide generated from the header files
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 class Isolate;
24 
25 typedef uintptr_t Address;
26 static const Address kNullAddress = 0;
27 
31 const int kApiSystemPointerSize = sizeof(void*);
32 const int kApiTaggedSize = kApiSystemPointerSize;
33 const int kApiDoubleSize = sizeof(double);
34 const int kApiInt32Size = sizeof(int32_t);
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  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  return (value == static_cast<int32_t>(value));
88  }
89 };
90 
91 #ifdef V8_COMPRESS_POINTERS
92 static_assert(
93  kApiSystemPointerSize == kApiInt64Size,
94  "Pointer compression can be enabled only for 64-bit architectures");
95 #endif
96 
97 #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
99 #else
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  return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
112  kSmiTag;
113 }
114 
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 + kApiInt32Size;
126  static const int kStringResourceOffset =
127  1 * kApiTaggedSize + 2 * kApiInt32Size;
128 
129  static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
130  static const int kForeignAddressOffset = kApiTaggedSize;
131  static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
132  static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
133  static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
134  static const int kEmbedderDataSlotSize =
135 #ifdef V8_COMPRESS_POINTERS
136  2 *
137 #endif
138  kApiSystemPointerSize;
139  static const int kNativeContextEmbedderDataOffset = 7 * kApiTaggedSize;
140  static const int kFullStringRepresentationMask = 0x0f;
141  static const int kStringEncodingMask = 0x8;
142  static const int kExternalTwoByteRepresentationTag = 0x02;
143  static const int kExternalOneByteRepresentationTag = 0x0a;
144 
145  static const uint32_t kNumIsolateDataSlots = 4;
146 
147  static const int kIsolateEmbedderDataOffset = 0;
148  static const int kExternalMemoryOffset =
149  kNumIsolateDataSlots * kApiSystemPointerSize;
150  static const int kExternalMemoryLimitOffset =
151  kExternalMemoryOffset + kApiInt64Size;
152  static const int kExternalMemoryAtLastMarkCompactOffset =
153  kExternalMemoryLimitOffset + kApiInt64Size;
154  static const int kIsolateRootsOffset =
155  kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size;
156 
157  static const int kUndefinedValueRootIndex = 4;
158  static const int kTheHoleValueRootIndex = 5;
159  static const int kNullValueRootIndex = 6;
160  static const int kTrueValueRootIndex = 7;
161  static const int kFalseValueRootIndex = 8;
162  static const int kEmptyStringRootIndex = 9;
163 
164  static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
165  static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
166  static const int kNodeStateMask = 0x7;
167  static const int kNodeStateIsWeakValue = 2;
168  static const int kNodeStateIsPendingValue = 3;
169  static const int kNodeStateIsNearDeathValue = 4;
170  static const int kNodeIsIndependentShift = 3;
171  static const int kNodeIsActiveShift = 4;
172 
173  static const int kFirstNonstringType = 0x40;
174  static const int kOddballType = 0x43;
175  static const int kForeignType = 0x47;
176  static const int kJSSpecialApiObjectType = 0x410;
177  static const int kJSApiObjectType = 0x420;
178  static const int kJSObjectType = 0x421;
179 
180  static const int kUndefinedOddballKind = 5;
181  static const int kNullOddballKind = 3;
182 
183  // Constants used by PropertyCallbackInfo to check if we should throw when an
184  // error occurs.
185  static const int kThrowOnError = 0;
186  static const int kDontThrow = 1;
187  static const int kInferShouldThrowMode = 2;
188 
189  // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
190  // incremental GC once the external memory reaches this limit.
191  static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
192 
193  V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
194  V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
195 #ifdef V8_ENABLE_CHECKS
196  CheckInitializedImpl(isolate);
197 #endif
198  }
199 
200  V8_INLINE static bool HasHeapObjectTag(const internal::Address value) {
201  return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
202  }
203 
204  V8_INLINE static int SmiValue(const internal::Address value) {
205  return PlatformSmiTagging::SmiToInt(value);
206  }
207 
208  V8_INLINE static constexpr internal::Address IntToSmi(int value) {
209  return internal::IntToSmi(value);
210  }
211 
212  V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
213  return PlatformSmiTagging::IsValidSmi(value);
214  }
215 
216  V8_INLINE static int GetInstanceType(const internal::Address obj) {
217  typedef internal::Address A;
218  A map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
219  return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
220  }
221 
222  V8_INLINE static int GetOddballKind(const internal::Address obj) {
223  return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
224  }
225 
226  V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
227  int representation = (instance_type & kFullStringRepresentationMask);
228  return representation == kExternalTwoByteRepresentationTag;
229  }
230 
231  V8_INLINE static uint8_t GetNodeFlag(internal::Address* obj, int shift) {
232  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
233  return *addr & static_cast<uint8_t>(1U << shift);
234  }
235 
236  V8_INLINE static void UpdateNodeFlag(internal::Address* obj, bool value,
237  int shift) {
238  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
239  uint8_t mask = static_cast<uint8_t>(1U << shift);
240  *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
241  }
242 
243  V8_INLINE static uint8_t GetNodeState(internal::Address* obj) {
244  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
245  return *addr & kNodeStateMask;
246  }
247 
248  V8_INLINE static void UpdateNodeState(internal::Address* obj, uint8_t value) {
249  uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
250  *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
251  }
252 
253  V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
254  void* data) {
255  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
256  kIsolateEmbedderDataOffset +
257  slot * kApiSystemPointerSize;
258  *reinterpret_cast<void**>(addr) = data;
259  }
260 
261  V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
262  uint32_t slot) {
263  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
264  kIsolateEmbedderDataOffset +
265  slot * kApiSystemPointerSize;
266  return *reinterpret_cast<void* const*>(addr);
267  }
268 
269  V8_INLINE static internal::Address* GetRoot(v8::Isolate* isolate, int index) {
270  internal::Address addr = reinterpret_cast<internal::Address>(isolate) +
271  kIsolateRootsOffset +
272  index * kApiSystemPointerSize;
273  return reinterpret_cast<internal::Address*>(addr);
274  }
275 
276  template <typename T>
277  V8_INLINE static T ReadRawField(internal::Address heap_object_ptr,
278  int offset) {
279  internal::Address addr = heap_object_ptr + offset - kHeapObjectTag;
280  return *reinterpret_cast<const T*>(addr);
281  }
282 
283  V8_INLINE static internal::Address ReadTaggedPointerField(
284  internal::Address heap_object_ptr, int offset) {
285 #ifdef V8_COMPRESS_POINTERS
286  int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
287  internal::Address root = GetRootFromOnHeapAddress(heap_object_ptr);
288  return root + static_cast<internal::Address>(static_cast<intptr_t>(value));
289 #else
290  return ReadRawField<internal::Address>(heap_object_ptr, offset);
291 #endif
292  }
293 
294  V8_INLINE static internal::Address ReadTaggedSignedField(
295  internal::Address heap_object_ptr, int offset) {
296 #ifdef V8_COMPRESS_POINTERS
297  int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
298  return static_cast<internal::Address>(static_cast<intptr_t>(value));
299 #else
300  return ReadRawField<internal::Address>(heap_object_ptr, offset);
301 #endif
302  }
303 
304  V8_INLINE static internal::Address ReadTaggedAnyField(
305  internal::Address heap_object_ptr, int offset) {
306 #ifdef V8_COMPRESS_POINTERS
307  int32_t value = ReadRawField<int32_t>(heap_object_ptr, offset);
308  internal::Address root_mask = static_cast<internal::Address>(
309  -static_cast<intptr_t>(value & kSmiTagMask));
310  internal::Address root_or_zero =
311  root_mask & GetRootFromOnHeapAddress(heap_object_ptr);
312  return root_or_zero +
313  static_cast<internal::Address>(static_cast<intptr_t>(value));
314 #else
315  return ReadRawField<internal::Address>(heap_object_ptr, offset);
316 #endif
317  }
318 
319 #ifdef V8_COMPRESS_POINTERS
320  static constexpr size_t kPtrComprHeapReservationSize = size_t{1} << 32;
321  static constexpr size_t kPtrComprIsolateRootBias =
322  kPtrComprHeapReservationSize / 2;
323  static constexpr size_t kPtrComprIsolateRootAlignment = size_t{1} << 32;
324 
325  V8_INLINE static internal::Address GetRootFromOnHeapAddress(
326  internal::Address addr) {
327  return (addr + kPtrComprIsolateRootBias) &
328  -static_cast<intptr_t>(kPtrComprIsolateRootAlignment);
329  }
330 
331 #else
332 
333  template <typename T>
334  V8_INLINE static T ReadEmbedderData(const v8::Context* context, int index) {
335  typedef internal::Address A;
336  typedef internal::Internals I;
337  A ctx = *reinterpret_cast<const A*>(context);
338  A embedder_data =
339  I::ReadTaggedPointerField(ctx, I::kNativeContextEmbedderDataOffset);
340  int value_offset =
341  I::kEmbedderDataArrayHeaderSize + (I::kEmbedderDataSlotSize * index);
342  return I::ReadRawField<T>(embedder_data, value_offset);
343  }
344 #endif // V8_COMPRESS_POINTERS
345 };
346 
347 // Only perform cast check for types derived from v8::Data since
348 // other types do not implement the Cast method.
349 template <bool PerformCheck>
350 struct CastCheck {
351  template <class T>
352  static void Perform(T* data);
353 };
354 
355 template <>
356 template <class T>
357 void CastCheck<true>::Perform(T* data) {
358  T::Cast(data);
359 }
360 
361 template <>
362 template <class T>
363 void CastCheck<false>::Perform(T* data) {}
364 
365 template <class T>
366 V8_INLINE void PerformCastCheck(T* data) {
367  CastCheck<std::is_base_of<Data, T>::value>::Perform(data);
368 }
369 
370 // {obj} must be the raw tagged pointer representation of a HeapObject
371 // that's guaranteed to never be in ReadOnlySpace.
372 V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
373 
374 // Returns if we need to throw when an error occurs. This infers the language
375 // mode based on the current context and the closure. This returns true if the
376 // language mode is strict.
377 V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate);
378 
379 } // namespace internal
380 } // namespace v8
381 
382 #endif // INCLUDE_V8_INTERNAL_H_
Definition: v8-internal.h:120
Definition: v8-internal.h:49
Definition: v8.h:9256
Definition: v8-internal.h:15
Definition: v8.h:1109
Definition: v8.h:7374
Definition: v8-internal.h:350