v8  7.4.288(node12.0.0)
V8 is Google's open source JavaScript engine
v8-internal.h
Go to the documentation of this file.
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*);
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(
94  "Pointer compression can be enabled only for 64-bit architectures");
95 #endif
96 
97 #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
98 typedef SmiTagging<kApiInt32Size> PlatformSmiTagging;
99 #else
101 #endif
102 
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;
126  static const int kStringResourceOffset =
127  1 * kApiTaggedSize + 2 * kApiInt32Size;
128 
131  static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
132  static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
134  static const int kEmbedderDataSlotSize =
135 #ifdef V8_COMPRESS_POINTERS
136  2 *
137 #endif
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 =
150  static const int kExternalMemoryLimitOffset =
154  static const int kIsolateRootsOffset =
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 
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 
217  typedef internal::Address A;
219  return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
220  }
221 
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) +
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) +
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) +
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 
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 
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 
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>
358  T::Cast(data);
359 }
360 
361 template <>
362 template <class T>
364 
365 template <class T>
368 }
369 
370 // {obj} must be the raw tagged pointer representation of a HeapObject
371 // that's guaranteed to never be in ReadOnlySpace.
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_
static const int kJSApiObjectType
Definition: v8-internal.h:177
const intptr_t kSmiTagMask
Definition: v8-internal.h:46
static V8_INLINE internal::Address ReadTaggedPointerField(internal::Address heap_object_ptr, int offset)
Definition: v8-internal.h:283
const int kSmiMaxValue
Definition: v8-internal.h:106
static V8_INLINE uint8_t GetNodeState(internal::Address *obj)
Definition: v8-internal.h:243
static V8_INLINE T ReadEmbedderData(const v8::Context *context, int index)
Definition: v8-internal.h:334
#define V8_EXPORT
Definition: v8config.h:377
uintptr_t Address
Definition: v8-internal.h:23
static const int kOddballKindOffset
Definition: v8-internal.h:129
static V8_INLINE int GetOddballKind(const internal::Address obj)
Definition: v8-internal.h:222
static const int kEmbedderDataSlotSize
Definition: v8-internal.h:134
static constexpr int kExternalAllocationSoftLimit
Definition: v8-internal.h:191
static const int kFirstNonstringType
Definition: v8-internal.h:173
static const int kNullValueRootIndex
Definition: v8-internal.h:159
static const uint32_t kNumIsolateDataSlots
Definition: v8-internal.h:145
const int kSmiValueSize
Definition: v8-internal.h:104
static V8_INLINE void * GetEmbedderData(const v8::Isolate *isolate, uint32_t slot)
Definition: v8-internal.h:261
static const int kNodeIsActiveShift
Definition: v8-internal.h:171
static const int kExternalMemoryLimitOffset
Definition: v8-internal.h:150
static const int kExternalMemoryAtLastMarkCompactOffset
Definition: v8-internal.h:152
static const int kThrowOnError
Definition: v8-internal.h:185
static V8_INLINE internal::Address ReadTaggedAnyField(internal::Address heap_object_ptr, int offset)
Definition: v8-internal.h:304
SmiTagging< kApiTaggedSize > PlatformSmiTagging
Definition: v8-internal.h:100
static V8_INLINE int SmiValue(const internal::Address value)
Definition: v8-internal.h:204
static const int kStringResourceOffset
Definition: v8-internal.h:126
static const int kJSObjectHeaderSize
Definition: v8-internal.h:131
const intptr_t kHeapObjectTagMask
Definition: v8-internal.h:41
static const int kNodeStateIsNearDeathValue
Definition: v8-internal.h:169
const int kApiInt32Size
Definition: v8-internal.h:34
V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate *isolate)
static const int kNodeFlagsOffset
Definition: v8-internal.h:165
static const int kFixedArrayHeaderSize
Definition: v8-internal.h:132
static const int kTheHoleValueRootIndex
Definition: v8-internal.h:158
static const int kNodeStateIsPendingValue
Definition: v8-internal.h:168
static const int kNodeStateIsWeakValue
Definition: v8-internal.h:167
static V8_INLINE bool IsExternalTwoByteString(int instance_type)
Definition: v8-internal.h:226
const int kApiSystemPointerSize
Definition: v8-internal.h:31
Definition: libplatform.h:13
static const int kMapInstanceTypeOffset
Definition: v8-internal.h:125
static V8_INLINE bool HasHeapObjectTag(const internal::Address value)
Definition: v8-internal.h:200
static const int kNativeContextEmbedderDataOffset
Definition: v8-internal.h:139
static const int kInferShouldThrowMode
Definition: v8-internal.h:187
constexpr bool SmiValuesAre31Bits()
Definition: v8-internal.h:107
static V8_INLINE int GetInstanceType(const internal::Address obj)
Definition: v8-internal.h:216
static V8_INLINE void CheckInitialized(v8::Isolate *isolate)
Definition: v8-internal.h:194
V8_INLINE void PerformCastCheck(T *data)
Definition: v8-internal.h:366
static V8_INLINE constexpr internal::Address IntToSmi(int value)
Definition: v8-internal.h:208
const int kApiDoubleSize
Definition: v8-internal.h:33
const int kHeapObjectTag
Definition: v8-internal.h:38
constexpr bool SmiValuesAre32Bits()
Definition: v8-internal.h:108
static V8_INLINE T ReadRawField(internal::Address heap_object_ptr, int offset)
Definition: v8-internal.h:277
static const int kEmbedderDataArrayHeaderSize
Definition: v8-internal.h:133
const int kSmiMinValue
Definition: v8-internal.h:105
static const int kDontThrow
Definition: v8-internal.h:186
static const int kUndefinedValueRootIndex
Definition: v8-internal.h:157
static V8_INLINE void SetEmbedderData(v8::Isolate *isolate, uint32_t slot, void *data)
Definition: v8-internal.h:253
static const int kOddballType
Definition: v8-internal.h:174
static V8_INLINE constexpr bool IsValidSmi(intptr_t value)
Definition: v8-internal.h:60
const int kApiInt64Size
Definition: v8-internal.h:35
static const int kFalseValueRootIndex
Definition: v8-internal.h:161
static const int kEmptyStringRootIndex
Definition: v8-internal.h:162
static const int kNodeIsIndependentShift
Definition: v8-internal.h:170
V8_EXPORT internal::Isolate * IsolateFromNeverReadOnlySpaceObject(Address obj)
static V8_INLINE constexpr bool IsValidSmi(intptr_t value)
Definition: v8-internal.h:85
static V8_INLINE int SmiToInt(const internal::Address value)
Definition: v8-internal.h:80
static const int kHeapObjectMapOffset
Definition: v8-internal.h:124
static V8_INLINE void UpdateNodeState(internal::Address *obj, uint8_t value)
Definition: v8-internal.h:248
static V8_INLINE constexpr bool IsValidSmi(intptr_t value)
Definition: v8-internal.h:212
const int kSmiShiftSize
Definition: v8-internal.h:103
const int kSmiTagSize
Definition: v8-internal.h:45
static V8_INLINE internal::Address * GetRoot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:269
static const int kFullStringRepresentationMask
Definition: v8-internal.h:140
static V8_INLINE int SmiToInt(const internal::Address value)
Definition: v8-internal.h:55
const int kSmiTag
Definition: v8-internal.h:44
const int kWeakHeapObjectTag
Definition: v8-internal.h:39
static const int kUndefinedOddballKind
Definition: v8-internal.h:180
const int kHeapObjectTagSize
Definition: v8-internal.h:40
static V8_INLINE internal::Address ReadTaggedSignedField(internal::Address heap_object_ptr, int offset)
Definition: v8-internal.h:294
const int kApiTaggedSize
Definition: v8-internal.h:32
static V8_INLINE uint8_t GetNodeFlag(internal::Address *obj, int shift)
Definition: v8-internal.h:231
static V8_INLINE void UpdateNodeFlag(internal::Address *obj, bool value, int shift)
Definition: v8-internal.h:236
static const int kNodeStateMask
Definition: v8-internal.h:166
static const int kStringEncodingMask
Definition: v8-internal.h:141
static const int kExternalTwoByteRepresentationTag
Definition: v8-internal.h:142
static const int kTrueValueRootIndex
Definition: v8-internal.h:160
static V8_EXPORT void CheckInitializedImpl(v8::Isolate *isolate)
static const int kJSSpecialApiObjectType
Definition: v8-internal.h:176
static const int kForeignType
Definition: v8-internal.h:175
static const int kIsolateRootsOffset
Definition: v8-internal.h:154
static void Perform(T *data)
static const int kIsolateEmbedderDataOffset
Definition: v8-internal.h:147
static const int kNullOddballKind
Definition: v8-internal.h:181
#define V8_INLINE
Definition: v8config.h:287
static const int kExternalOneByteRepresentationTag
Definition: v8-internal.h:143
static const int kExternalMemoryOffset
Definition: v8-internal.h:148
static const int kNodeClassIdOffset
Definition: v8-internal.h:164
static const int kJSObjectType
Definition: v8-internal.h:178
static const int kForeignAddressOffset
Definition: v8-internal.h:130