Loading...
Searching...
No Matches
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 <string.h>
11
12#include <atomic>
13#include <iterator>
14#include <limits>
15#include <memory>
16#include <optional>
17#include <type_traits>
18
19#include "v8config.h" // NOLINT(build/include_directory)
20
21namespace v8 {
22
23class Array;
24class Context;
25class Data;
26class Isolate;
27
28namespace internal {
29
30class Heap;
31class Isolate;
32
33typedef uintptr_t Address;
34static constexpr Address kNullAddress = 0;
35
36constexpr int KB = 1024;
37constexpr int MB = KB * 1024;
38constexpr int GB = MB * 1024;
39#ifdef V8_TARGET_ARCH_X64
40constexpr size_t TB = size_t{GB} * 1024;
41#endif
42
46const int kApiSystemPointerSize = sizeof(void*);
47const int kApiDoubleSize = sizeof(double);
48const int kApiInt32Size = sizeof(int32_t);
49const int kApiInt64Size = sizeof(int64_t);
50const int kApiSizetSize = sizeof(size_t);
51
52// Tag information for HeapObject.
53const int kHeapObjectTag = 1;
54const int kWeakHeapObjectTag = 3;
55const int kHeapObjectTagSize = 2;
56const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
58
59// Tag information for fowarding pointers stored in object headers.
60// 0b00 at the lowest 2 bits in the header indicates that the map word is a
61// forwarding pointer.
62const int kForwardingTag = 0;
63const int kForwardingTagSize = 2;
64const intptr_t kForwardingTagMask = (1 << kForwardingTagSize) - 1;
65
66// Tag information for Smi.
67const int kSmiTag = 0;
68const int kSmiTagSize = 1;
69const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
70
71template <size_t tagged_ptr_size>
73
74constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1};
75constexpr uintptr_t kUintptrAllBitsSet =
76 static_cast<uintptr_t>(kIntptrAllBitsSet);
77
78// Smi constants for systems where tagged pointer is a 32-bit value.
79template <>
80struct SmiTagging<4> {
81 enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
82
83 static constexpr intptr_t kSmiMinValue =
84 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
85 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
86
87 V8_INLINE static constexpr int SmiToInt(Address value) {
88 int shift_bits = kSmiTagSize + kSmiShiftSize;
89 // Truncate and shift down (requires >> to be sign extending).
90 return static_cast<int32_t>(static_cast<uint32_t>(value)) >> shift_bits;
91 }
92
93 template <class T, typename std::enable_if_t<std::is_integral_v<T> &&
94 std::is_signed_v<T>>* = nullptr>
95 V8_INLINE static constexpr bool IsValidSmi(T value) {
96 // Is value in range [kSmiMinValue, kSmiMaxValue].
97 // Use unsigned operations in order to avoid undefined behaviour in case of
98 // signed integer overflow.
99 return (static_cast<uintptr_t>(value) -
100 static_cast<uintptr_t>(kSmiMinValue)) <=
101 (static_cast<uintptr_t>(kSmiMaxValue) -
102 static_cast<uintptr_t>(kSmiMinValue));
103 }
104
105 template <class T,
106 typename std::enable_if_t<std::is_integral_v<T> &&
107 std::is_unsigned_v<T>>* = nullptr>
108 V8_INLINE static constexpr bool IsValidSmi(T value) {
109 static_assert(kSmiMaxValue <= std::numeric_limits<uintptr_t>::max());
110 return value <= static_cast<uintptr_t>(kSmiMaxValue);
111 }
112
113 // Same as the `intptr_t` version but works with int64_t on 32-bit builds
114 // without slowing down anything else.
115 V8_INLINE static constexpr bool IsValidSmi(int64_t value) {
116 return (static_cast<uint64_t>(value) -
117 static_cast<uint64_t>(kSmiMinValue)) <=
118 (static_cast<uint64_t>(kSmiMaxValue) -
119 static_cast<uint64_t>(kSmiMinValue));
120 }
121
122 V8_INLINE static constexpr bool IsValidSmi(uint64_t value) {
123 static_assert(kSmiMaxValue <= std::numeric_limits<uint64_t>::max());
124 return value <= static_cast<uint64_t>(kSmiMaxValue);
125 }
126};
127
128// Smi constants for systems where tagged pointer is a 64-bit value.
129template <>
130struct SmiTagging<8> {
131 enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
132
133 static constexpr intptr_t kSmiMinValue =
134 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
135 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
136
137 V8_INLINE static constexpr int SmiToInt(Address value) {
138 int shift_bits = kSmiTagSize + kSmiShiftSize;
139 // Shift down and throw away top 32 bits.
140 return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
141 }
142
143 template <class T, typename std::enable_if_t<std::is_integral_v<T> &&
144 std::is_signed_v<T>>* = nullptr>
145 V8_INLINE static constexpr bool IsValidSmi(T value) {
146 // To be representable as a long smi, the value must be a 32-bit integer.
147 return (value == static_cast<int32_t>(value));
148 }
149
150 template <class T,
151 typename std::enable_if_t<std::is_integral_v<T> &&
152 std::is_unsigned_v<T>>* = nullptr>
153 V8_INLINE static constexpr bool IsValidSmi(T value) {
154 return (static_cast<uintptr_t>(value) ==
155 static_cast<uintptr_t>(static_cast<int32_t>(value)));
156 }
157};
158
159#ifdef V8_COMPRESS_POINTERS
160// See v8:7703 or src/common/ptr-compr-inl.h for details about pointer
161// compression.
162constexpr size_t kPtrComprCageReservationSize = size_t{1} << 32;
163constexpr size_t kPtrComprCageBaseAlignment = size_t{1} << 32;
164
165static_assert(
167 "Pointer compression can be enabled only for 64-bit architectures");
168const int kApiTaggedSize = kApiInt32Size;
169#else
171#endif
172
175}
176
177#ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
178using PlatformSmiTagging = SmiTagging<kApiInt32Size>;
179#else
181#endif
182
183// TODO(ishell): Consinder adding kSmiShiftBits = kSmiShiftSize + kSmiTagSize
184// since it's used much more often than the inividual constants.
185const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
186const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
187const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue);
188const int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue);
189constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
190constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
191constexpr bool Is64() { return kApiSystemPointerSize == sizeof(int64_t); }
192
193V8_INLINE static constexpr Address IntToSmi(int value) {
194 return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
195 kSmiTag;
196}
197
198/*
199 * Sandbox related types, constants, and functions.
200 */
201constexpr bool SandboxIsEnabled() {
202#ifdef V8_ENABLE_SANDBOX
203 return true;
204#else
205 return false;
206#endif
207}
208
209// SandboxedPointers are guaranteed to point into the sandbox. This is achieved
210// for example by storing them as offset rather than as raw pointers.
212
213#ifdef V8_ENABLE_SANDBOX
214
215// Size of the sandbox, excluding the guard regions surrounding it.
216#if defined(V8_TARGET_OS_ANDROID)
217// On Android, most 64-bit devices seem to be configured with only 39 bits of
218// virtual address space for userspace. As such, limit the sandbox to 128GB (a
219// quarter of the total available address space).
220constexpr size_t kSandboxSizeLog2 = 37; // 128 GB
221#elif defined(V8_TARGET_ARCH_LOONG64)
222// Some Linux distros on LoongArch64 configured with only 40 bits of virtual
223// address space for userspace. Limit the sandbox to 256GB here.
224constexpr size_t kSandboxSizeLog2 = 38; // 256 GB
225#else
226// Everywhere else use a 1TB sandbox.
227constexpr size_t kSandboxSizeLog2 = 40; // 1 TB
228#endif // V8_TARGET_OS_ANDROID
229constexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2;
230
231// Required alignment of the sandbox. For simplicity, we require the
232// size of the guard regions to be a multiple of this, so that this specifies
233// the alignment of the sandbox including and excluding surrounding guard
234// regions. The alignment requirement is due to the pointer compression cage
235// being located at the start of the sandbox.
236constexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment;
237
238// Sandboxed pointers are stored inside the heap as offset from the sandbox
239// base shifted to the left. This way, it is guaranteed that the offset is
240// smaller than the sandbox size after shifting it to the right again. This
241// constant specifies the shift amount.
242constexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2;
243
244// Size of the guard regions surrounding the sandbox. This assumes a worst-case
245// scenario of a 32-bit unsigned index used to access an array of 64-bit
246// values.
247constexpr size_t kSandboxGuardRegionSize = 32ULL * GB;
248
249static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
250 "The size of the guard regions around the sandbox must be a "
251 "multiple of its required alignment.");
252
253// On OSes where reserving virtual memory is too expensive to reserve the
254// entire address space backing the sandbox, notably Windows pre 8.1, we create
255// a partially reserved sandbox that doesn't actually reserve most of the
256// memory, and so doesn't have the desired security properties as unrelated
257// memory allocations could end up inside of it, but which still ensures that
258// objects that should be located inside the sandbox are allocated within
259// kSandboxSize bytes from the start of the sandbox. The minimum size of the
260// region that is actually reserved for such a sandbox is specified by this
261// constant and should be big enough to contain the pointer compression cage as
262// well as the ArrayBuffer partition.
263constexpr size_t kSandboxMinimumReservationSize = 8ULL * GB;
264
265static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
266 "The minimum reservation size for a sandbox must be larger than "
267 "the pointer compression cage contained within it.");
268
269// The maximum buffer size allowed inside the sandbox. This is mostly dependent
270// on the size of the guard regions around the sandbox: an attacker must not be
271// able to construct a buffer that appears larger than the guard regions and
272// thereby "reach out of" the sandbox.
273constexpr size_t kMaxSafeBufferSizeForSandbox = 32ULL * GB - 1;
274static_assert(kMaxSafeBufferSizeForSandbox <= kSandboxGuardRegionSize,
275 "The maximum allowed buffer size must not be larger than the "
276 "sandbox's guard regions");
277
278constexpr size_t kBoundedSizeShift = 29;
279static_assert(1ULL << (64 - kBoundedSizeShift) ==
280 kMaxSafeBufferSizeForSandbox + 1,
281 "The maximum size of a BoundedSize must be synchronized with the "
282 "kMaxSafeBufferSizeForSandbox");
283
284#endif // V8_ENABLE_SANDBOX
285
286#ifdef V8_COMPRESS_POINTERS
287
288#ifdef V8_TARGET_OS_ANDROID
289// The size of the virtual memory reservation for an external pointer table.
290// This determines the maximum number of entries in a table. Using a maximum
291// size allows omitting bounds checks on table accesses if the indices are
292// guaranteed (e.g. through shifting) to be below the maximum index. This
293// value must be a power of two.
294constexpr size_t kExternalPointerTableReservationSize = 256 * MB;
295
296// The external pointer table indices stored in HeapObjects as external
297// pointers are shifted to the left by this amount to guarantee that they are
298// smaller than the maximum table size.
299constexpr uint32_t kExternalPointerIndexShift = 7;
300#else
301constexpr size_t kExternalPointerTableReservationSize = 512 * MB;
302constexpr uint32_t kExternalPointerIndexShift = 6;
303#endif // V8_TARGET_OS_ANDROID
304
305// The maximum number of entries in an external pointer table.
306constexpr int kExternalPointerTableEntrySize = 8;
307constexpr int kExternalPointerTableEntrySizeLog2 = 3;
308constexpr size_t kMaxExternalPointers =
309 kExternalPointerTableReservationSize / kExternalPointerTableEntrySize;
310static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers,
311 "kExternalPointerTableReservationSize and "
312 "kExternalPointerIndexShift don't match");
313
314#else // !V8_COMPRESS_POINTERS
315
316// Needed for the V8.SandboxedExternalPointersCount histogram.
317constexpr size_t kMaxExternalPointers = 0;
318
319#endif // V8_COMPRESS_POINTERS
320
321// A ExternalPointerHandle represents a (opaque) reference to an external
322// pointer that can be stored inside the sandbox. A ExternalPointerHandle has
323// meaning only in combination with an (active) Isolate as it references an
324// external pointer stored in the currently active Isolate's
325// ExternalPointerTable. Internally, an ExternalPointerHandles is simply an
326// index into an ExternalPointerTable that is shifted to the left to guarantee
327// that it is smaller than the size of the table.
328using ExternalPointerHandle = uint32_t;
329
330// ExternalPointers point to objects located outside the sandbox. When the V8
331// sandbox is enabled, these are stored on heap as ExternalPointerHandles,
332// otherwise they are simply raw pointers.
333#ifdef V8_ENABLE_SANDBOX
335#else
337#endif
338
341
342// See `ExternalPointerHandle` for the main documentation. The difference to
343// `ExternalPointerHandle` is that the handle does not represent an arbitrary
344// external pointer but always refers to an object managed by `CppHeap`. The
345// handles are using in combination with a dedicated table for `CppHeap`
346// references.
347using CppHeapPointerHandle = uint32_t;
348
349// The actual pointer to objects located on the `CppHeap`. When pointer
350// compression is enabled these pointers are stored as `CppHeapPointerHandle`.
351// In non-compressed configurations the pointers are simply stored as raw
352// pointers.
353#ifdef V8_COMPRESS_POINTERS
355#else
357#endif
358
361
362constexpr uint64_t kCppHeapPointerMarkBit = 1ULL;
363constexpr uint64_t kCppHeapPointerTagShift = 1;
364constexpr uint64_t kCppHeapPointerPayloadShift = 16;
365
366#ifdef V8_COMPRESS_POINTERS
367// CppHeapPointers use a dedicated pointer table. These constants control the
368// size and layout of the table. See the corresponding constants for the
369// external pointer table for further details.
370constexpr size_t kCppHeapPointerTableReservationSize =
371 kExternalPointerTableReservationSize;
372constexpr uint32_t kCppHeapPointerIndexShift = kExternalPointerIndexShift;
373
374constexpr int kCppHeapPointerTableEntrySize = 8;
375constexpr int kCppHeapPointerTableEntrySizeLog2 = 3;
376constexpr size_t kMaxCppHeapPointers =
377 kCppHeapPointerTableReservationSize / kCppHeapPointerTableEntrySize;
378static_assert((1 << (32 - kCppHeapPointerIndexShift)) == kMaxCppHeapPointers,
379 "kCppHeapPointerTableReservationSize and "
380 "kCppHeapPointerIndexShift don't match");
381
382#else // !V8_COMPRESS_POINTERS
383
384// Needed for the V8.SandboxedCppHeapPointersCount histogram.
385constexpr size_t kMaxCppHeapPointers = 0;
386
387#endif // V8_COMPRESS_POINTERS
388
389// See `ExternalPointerHandle` for the main documentation. The difference to
390// `ExternalPointerHandle` is that the handle always refers to a
391// (external pointer, size) tuple. The handles are used in combination with a
392// dedicated external buffer table (EBT).
393using ExternalBufferHandle = uint32_t;
394
395// ExternalBuffer point to buffer located outside the sandbox. When the V8
396// sandbox is enabled, these are stored on heap as ExternalBufferHandles,
397// otherwise they are simply raw pointers.
398#ifdef V8_ENABLE_SANDBOX
400#else
402#endif
403
404#ifdef V8_TARGET_OS_ANDROID
405// The size of the virtual memory reservation for the external buffer table.
406// As with the external pointer table, a maximum table size in combination with
407// shifted indices allows omitting bounds checks.
408constexpr size_t kExternalBufferTableReservationSize = 64 * MB;
409
410// The external buffer handles are stores shifted to the left by this amount
411// to guarantee that they are smaller than the maximum table size.
412constexpr uint32_t kExternalBufferHandleShift = 10;
413#else
415constexpr uint32_t kExternalBufferHandleShift = 9;
416#endif // V8_TARGET_OS_ANDROID
417
418// A null handle always references an entry that contains nullptr.
420
421// The maximum number of entries in an external buffer table.
426static_assert((1 << (32 - kExternalBufferHandleShift)) ==
428 "kExternalBufferTableReservationSize and "
429 "kExternalBufferHandleShift don't match");
430
431//
432// External Pointers.
433//
434// When the sandbox is enabled, external pointers are stored in an external
435// pointer table and are referenced from HeapObjects through an index (a
436// "handle"). When stored in the table, the pointers are tagged with per-type
437// tags to prevent type confusion attacks between different external objects.
438// Besides type information bits, these tags also contain the GC marking bit
439// which indicates whether the pointer table entry is currently alive. When a
440// pointer is written into the table, the tag is ORed into the top bits. When
441// that pointer is later loaded from the table, it is ANDed with the inverse of
442// the expected tag. If the expected and actual type differ, this will leave
443// some of the top bits of the pointer set, rendering the pointer inaccessible.
444// The AND operation also removes the GC marking bit from the pointer.
445//
446// The tags are constructed such that UNTAG(TAG(0, T1), T2) != 0 for any two
447// (distinct) tags T1 and T2. In practice, this is achieved by generating tags
448// that all have the same number of zeroes and ones but different bit patterns.
449// With N type tag bits, this allows for (N choose N/2) possible type tags.
450// Besides the type tag bits, the tags also have the GC marking bit set so that
451// the marking bit is automatically set when a pointer is written into the
452// external pointer table (in which case it is clearly alive) and is cleared
453// when the pointer is loaded. The exception to this is the free entry tag,
454// which doesn't have the mark bit set, as the entry is not alive. This
455// construction allows performing the type check and removing GC marking bits
456// from the pointer in one efficient operation (bitwise AND). The number of
457// available bits is limited in the following way: on x64, bits [47, 64) are
458// generally available for tagging (userspace has 47 address bits available).
459// On Arm64, userspace typically has a 40 or 48 bit address space. However, due
460// to top-byte ignore (TBI) and memory tagging (MTE), the top byte is unusable
461// for type checks as type-check failures would go unnoticed or collide with
462// MTE bits. Some bits of the top byte can, however, still be used for the GC
463// marking bit. The bits available for the type tags are therefore limited to
464// [48, 56), i.e. (8 choose 4) = 70 different types.
465// The following options exist to increase the number of possible types:
466// - Using multiple ExternalPointerTables since tags can safely be reused
467// across different tables
468// - Using "extended" type checks, where additional type information is stored
469// either in an adjacent pointer table entry or at the pointed-to location
470// - Using a different tagging scheme, for example based on XOR which would
471// allow for 2**8 different tags but require a separate operation to remove
472// the marking bit
473//
474// The external pointer sandboxing mechanism ensures that every access to an
475// external pointer field will result in a valid pointer of the expected type
476// even in the presence of an attacker able to corrupt memory inside the
477// sandbox. However, if any data related to the external object is stored
478// inside the sandbox it may still be corrupted and so must be validated before
479// use or moved into the external object. Further, an attacker will always be
480// able to substitute different external pointers of the same type for each
481// other. Therefore, code using external pointers must be written in a
482// "substitution-safe" way, i.e. it must always be possible to substitute
483// external pointers of the same type without causing memory corruption outside
484// of the sandbox. Generally this is achieved by referencing any group of
485// related external objects through a single external pointer.
486//
487// Currently we use bit 62 for the marking bit which should always be unused as
488// it's part of the non-canonical address range. When Arm's top-byte ignore
489// (TBI) is enabled, this bit will be part of the ignored byte, and we assume
490// that the Embedder is not using this byte (really only this one bit) for any
491// other purpose. This bit also does not collide with the memory tagging
492// extension (MTE) which would use bits [56, 60).
493//
494// External pointer tables are also available even when the sandbox is off but
495// pointer compression is on. In that case, the mechanism can be used to ease
496// alignment requirements as it turns unaligned 64-bit raw pointers into
497// aligned 32-bit indices. To "opt-in" to the external pointer table mechanism
498// for this purpose, instead of using the ExternalPointer accessors one needs to
499// use ExternalPointerHandles directly and use them to access the pointers in an
500// ExternalPointerTable.
501constexpr uint64_t kExternalPointerMarkBit = 1ULL << 62;
502constexpr uint64_t kExternalPointerTagMask = 0x40ff000000000000;
503constexpr uint64_t kExternalPointerTagMaskWithoutMarkBit = 0xff000000000000;
504constexpr uint64_t kExternalPointerTagShift = 48;
505
506// All possible 8-bit type tags.
507// These are sorted so that tags can be grouped together and it can efficiently
508// be checked if a tag belongs to a given group. See for example the
509// IsSharedExternalPointerType routine.
510constexpr uint64_t kAllTagsForAndBasedTypeChecking[] = {
511 0b00001111, 0b00010111, 0b00011011, 0b00011101, 0b00011110, 0b00100111,
512 0b00101011, 0b00101101, 0b00101110, 0b00110011, 0b00110101, 0b00110110,
513 0b00111001, 0b00111010, 0b00111100, 0b01000111, 0b01001011, 0b01001101,
514 0b01001110, 0b01010011, 0b01010101, 0b01010110, 0b01011001, 0b01011010,
515 0b01011100, 0b01100011, 0b01100101, 0b01100110, 0b01101001, 0b01101010,
516 0b01101100, 0b01110001, 0b01110010, 0b01110100, 0b01111000, 0b10000111,
517 0b10001011, 0b10001101, 0b10001110, 0b10010011, 0b10010101, 0b10010110,
518 0b10011001, 0b10011010, 0b10011100, 0b10100011, 0b10100101, 0b10100110,
519 0b10101001, 0b10101010, 0b10101100, 0b10110001, 0b10110010, 0b10110100,
520 0b10111000, 0b11000011, 0b11000101, 0b11000110, 0b11001001, 0b11001010,
521 0b11001100, 0b11010001, 0b11010010, 0b11010100, 0b11011000, 0b11100001,
522 0b11100010, 0b11100100, 0b11101000, 0b11110000};
523
524#define TAG(i) \
525 ((kAllTagsForAndBasedTypeChecking[i] << kExternalPointerTagShift) | \
526 kExternalPointerMarkBit)
527
528// clang-format off
529
530// When adding new tags, please ensure that the code using these tags is
531// "substitution-safe", i.e. still operate safely if external pointers of the
532// same type are swapped by an attacker. See comment above for more details.
533
534// Shared external pointers are owned by the shared Isolate and stored in the
535// shared external pointer table associated with that Isolate, where they can
536// be accessed from multiple threads at the same time. The objects referenced
537// in this way must therefore always be thread-safe.
538#define SHARED_EXTERNAL_POINTER_TAGS(V) \
539 V(kFirstSharedTag, TAG(0)) \
540 V(kWaiterQueueNodeTag, TAG(0)) \
541 V(kExternalStringResourceTag, TAG(1)) \
542 V(kExternalStringResourceDataTag, TAG(2)) \
543 V(kLastSharedTag, TAG(2))
544 // Leave some space in the tag range here for future shared tags.
545
546// External pointers using these tags are kept in a per-Isolate external
547// pointer table and can only be accessed when this Isolate is active.
548#define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V) \
549 V(kNativeContextMicrotaskQueueTag, TAG(5)) \
550 V(kEmbedderDataSlotPayloadTag, TAG(6)) \
551/* This tag essentially stands for a `void*` pointer in the V8 API, and */ \
552/* it is the Embedder's responsibility to ensure type safety (against */ \
553/* substitution) and lifetime validity of these objects. */ \
554 V(kExternalObjectValueTag, TAG(7)) \
555 V(kFunctionTemplateInfoCallbackTag, TAG(8)) \
556 V(kAccessorInfoGetterTag, TAG(9)) \
557 V(kAccessorInfoSetterTag, TAG(10)) \
558 V(kWasmInternalFunctionCallTargetTag, TAG(11)) \
559 V(kWasmTypeInfoNativeTypeTag, TAG(12)) \
560 V(kWasmExportedFunctionDataSignatureTag, TAG(13)) \
561 V(kWasmContinuationJmpbufTag, TAG(14)) \
562 V(kWasmStackMemoryTag, TAG(15)) \
563 V(kWasmIndirectFunctionTargetTag, TAG(16)) \
564 /* Foreigns */ \
565 V(kGenericForeignTag, TAG(20)) \
566 V(kApiNamedPropertyQueryCallbackTag, TAG(21)) \
567 V(kApiNamedPropertyGetterCallbackTag, TAG(22)) \
568 V(kApiNamedPropertySetterCallbackTag, TAG(23)) \
569 V(kApiNamedPropertyDescriptorCallbackTag, TAG(24)) \
570 V(kApiNamedPropertyDefinerCallbackTag, TAG(25)) \
571 V(kApiNamedPropertyDeleterCallbackTag, TAG(26)) \
572 V(kApiIndexedPropertyQueryCallbackTag, TAG(27)) \
573 V(kApiIndexedPropertyGetterCallbackTag, TAG(28)) \
574 V(kApiIndexedPropertySetterCallbackTag, TAG(29)) \
575 V(kApiIndexedPropertyDescriptorCallbackTag, TAG(30)) \
576 V(kApiIndexedPropertyDefinerCallbackTag, TAG(31)) \
577 V(kApiIndexedPropertyDeleterCallbackTag, TAG(32)) \
578 V(kApiIndexedPropertyEnumeratorCallbackTag, TAG(33)) \
579 V(kApiAccessCheckCallbackTag, TAG(34)) \
580 V(kApiAbortScriptExecutionCallbackTag, TAG(35)) \
581 V(kSyntheticModuleTag, TAG(36)) \
582 V(kMicrotaskCallbackTag, TAG(37)) \
583 V(kMicrotaskCallbackDataTag, TAG(38)) \
584 V(kCFunctionTag, TAG(39)) \
585 V(kCFunctionInfoTag, TAG(40)) \
586 V(kMessageListenerTag, TAG(41)) \
587 V(kWaiterQueueForeignTag, TAG(42)) \
588 /* Managed */ \
589 V(kFirstManagedResourceTag, TAG(50)) \
590 V(kGenericManagedTag, TAG(50)) \
591 V(kWasmWasmStreamingTag, TAG(51)) \
592 V(kWasmFuncDataTag, TAG(52)) \
593 V(kWasmManagedDataTag, TAG(53)) \
594 V(kWasmNativeModuleTag, TAG(54)) \
595 V(kIcuBreakIteratorTag, TAG(55)) \
596 V(kIcuUnicodeStringTag, TAG(56)) \
597 V(kIcuListFormatterTag, TAG(57)) \
598 V(kIcuLocaleTag, TAG(58)) \
599 V(kIcuSimpleDateFormatTag, TAG(59)) \
600 V(kIcuDateIntervalFormatTag, TAG(60)) \
601 V(kIcuRelativeDateTimeFormatterTag, TAG(61)) \
602 V(kIcuLocalizedNumberFormatterTag, TAG(62)) \
603 V(kIcuPluralRulesTag, TAG(63)) \
604 V(kIcuCollatorTag, TAG(64)) \
605 V(kDisplayNamesInternalTag, TAG(65)) \
606 /* External resources whose lifetime is tied to */ \
607 /* their entry in the external pointer table but */ \
608 /* which are not referenced via a Managed */ \
609 V(kArrayBufferExtensionTag, TAG(66)) \
610 V(kLastManagedResourceTag, TAG(66)) \
611
612// All external pointer tags.
613#define ALL_EXTERNAL_POINTER_TAGS(V) \
614 SHARED_EXTERNAL_POINTER_TAGS(V) \
615 PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
616
617#define EXTERNAL_POINTER_TAG_ENUM(Name, Tag) Name = Tag,
618#define MAKE_TAG(HasMarkBit, TypeTag) \
619 ((static_cast<uint64_t>(TypeTag) << kExternalPointerTagShift) | \
620 (HasMarkBit ? kExternalPointerMarkBit : 0))
621enum ExternalPointerTag : uint64_t {
622 // Empty tag value. Mostly used as placeholder.
624 // External pointer tag that will match any external pointer. Use with care!
626 // External pointer tag that will match any external pointer in a Foreign.
627 // Use with care! If desired, this could be made more fine-granular.
629 // The free entry tag has all type bits set so every type check with a
630 // different type fails. It also doesn't have the mark bit set as free
631 // entries are (by definition) not alive.
633 // Evacuation entries are used during external pointer table compaction.
635 // Tag for zapped/invalidated entries. Those are considered to no longer be
636 // in use and so have the marking bit cleared.
638
640};
641
642#undef MAKE_TAG
643#undef TAG
644#undef EXTERNAL_POINTER_TAG_ENUM
645
646// clang-format on
647
648// True if the external pointer must be accessed from the shared isolate's
649// external pointer table.
650V8_INLINE static constexpr bool IsSharedExternalPointerType(
651 ExternalPointerTag tag) {
652 return tag >= kFirstSharedTag && tag <= kLastSharedTag;
653}
654
655// True if the external pointer may live in a read-only object, in which case
656// the table entry will be in the shared read-only segment of the external
657// pointer table.
658V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
659 ExternalPointerTag tag) {
660 return tag == kAccessorInfoGetterTag || tag == kAccessorInfoSetterTag ||
662}
663
664// True if the external pointer references an external object whose lifetime is
665// tied to the entry in the external pointer table.
666// In this case, the entry in the ExternalPointerTable always points to an
667// object derived from ExternalPointerTable::ManagedResource.
668V8_INLINE static constexpr bool IsManagedExternalPointerType(
669 ExternalPointerTag tag) {
671}
672
673// Sanity checks.
674#define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
675 static_assert(IsSharedExternalPointerType(Tag));
676#define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
677 static_assert(!IsSharedExternalPointerType(Tag));
678
681
682#undef CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS
683#undef CHECK_SHARED_EXTERNAL_POINTER_TAGS
684
685#undef SHARED_EXTERNAL_POINTER_TAGS
686#undef EXTERNAL_POINTER_TAGS
687
688//
689// Indirect Pointers.
690//
691// When the sandbox is enabled, indirect pointers are used to reference
692// HeapObjects that live outside of the sandbox (but are still managed by V8's
693// garbage collector). When object A references an object B through an indirect
694// pointer, object A will contain a IndirectPointerHandle, i.e. a shifted
695// 32-bit index, which identifies an entry in a pointer table (either the
696// trusted pointer table for TrustedObjects, or the code pointer table if it is
697// a Code object). This table entry then contains the actual pointer to object
698// B. Further, object B owns this pointer table entry, and it is responsible
699// for updating the "self-pointer" in the entry when it is relocated in memory.
700// This way, in contrast to "normal" pointers, indirect pointers never need to
701// be tracked by the GC (i.e. there is no remembered set for them).
702// These pointers do not exist when the sandbox is disabled.
703
704// An IndirectPointerHandle represents a 32-bit index into a pointer table.
705using IndirectPointerHandle = uint32_t;
706
707// A null handle always references an entry that contains nullptr.
709
710// When the sandbox is enabled, indirect pointers are used to implement:
711// - TrustedPointers: an indirect pointer using the trusted pointer table (TPT)
712// and referencing a TrustedObject in one of the trusted heap spaces.
713// - CodePointers, an indirect pointer using the code pointer table (CPT) and
714// referencing a Code object together with its instruction stream.
715
716//
717// Trusted Pointers.
718//
719// A pointer to a TrustedObject.
720// When the sandbox is enabled, these are indirect pointers using the trusted
721// pointer table (TPT). They are used to reference trusted objects (located in
722// one of V8's trusted heap spaces, outside of the sandbox) from inside the
723// sandbox in a memory-safe way. When the sandbox is disabled, these are
724// regular tagged pointers.
727// The size of the virtual memory reservation for the trusted pointer table.
728// As with the external pointer table, a maximum table size in combination with
729// shifted indices allows omitting bounds checks.
731
732// The trusted pointer handles are stores shifted to the left by this amount
733// to guarantee that they are smaller than the maximum table size.
734constexpr uint32_t kTrustedPointerHandleShift = 9;
735
736// A null handle always references an entry that contains nullptr.
740// The maximum number of entries in an trusted pointer table.
741constexpr int kTrustedPointerTableEntrySize = 8;
742constexpr int kTrustedPointerTableEntrySizeLog2 = 3;
743constexpr size_t kMaxTrustedPointers =
745static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
746 "kTrustedPointerTableReservationSize and "
747 "kTrustedPointerHandleShift don't match");
748
749//
750// Code Pointers.
751//
752// A pointer to a Code object.
753// Essentially a specialized version of a trusted pointer that (when the
754// sandbox is enabled) uses the code pointer table (CPT) instead of the TPT.
755// Each entry in the CPT contains both a pointer to a Code object as well as a
756// pointer to the Code's entrypoint. This allows calling/jumping into Code with
757// one fewer memory access (compared to the case where the entrypoint pointer
758// first needs to be loaded from the Code object). As such, a CodePointerHandle
759// can be used both to obtain the referenced Code object and to directly load
760// its entrypoint.
761//
762// When the sandbox is disabled, these are regular tagged pointers.
765// The size of the virtual memory reservation for the code pointer table.
766// As with the other tables, a maximum table size in combination with shifted
767// indices allows omitting bounds checks.
768constexpr size_t kCodePointerTableReservationSize = 128 * MB;
769
770// Code pointer handles are shifted by a different amount than indirect pointer
771// handles as the tables have a different maximum size.
772constexpr uint32_t kCodePointerHandleShift = 9;
773
774// A null handle always references an entry that contains nullptr.
776
777// It can sometimes be necessary to distinguish a code pointer handle from a
778// trusted pointer handle. A typical example would be a union trusted pointer
779// field that can refer to both Code objects and other trusted objects. To
780// support these use-cases, we use a simple marking scheme where some of the
781// low bits of a code pointer handle are set, while they will be unset on a
782// trusted pointer handle. This way, the correct table to resolve the handle
783// can be determined even in the absence of a type tag.
784constexpr uint32_t kCodePointerHandleMarker = 0x1;
785static_assert(kCodePointerHandleShift > 0);
786static_assert(kTrustedPointerHandleShift > 0);
788// The maximum number of entries in a code pointer table.
789constexpr int kCodePointerTableEntrySize = 16;
790constexpr int kCodePointerTableEntrySizeLog2 = 4;
791constexpr size_t kMaxCodePointers =
793static_assert(
795 "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
796
800// Constants that can be used to mark places that should be modified once
801// certain types of objects are moved out of the sandbox and into trusted space.
803constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace = false;
807
809// JavaScript Dispatch Table
811// A JSDispatchHandle represents a 32-bit index into a JSDispatchTable.
812using JSDispatchHandle = uint32_t;
813
816// The size of the virtual memory reservation for the JSDispatchTable.
817// As with the other tables, a maximum table size in combination with shifted
818// indices allows omitting bounds checks.
819constexpr size_t kJSDispatchTableReservationSize = 128 * MB;
820constexpr uint32_t kJSDispatchHandleShift = 9;
822// The maximum number of entries in a JSDispatchTable.
823constexpr int kJSDispatchTableEntrySize = 16;
824constexpr int kJSDispatchTableEntrySizeLog2 = 4;
825constexpr size_t kMaxJSDispatchEntries =
827static_assert((1 << (32 - kJSDispatchHandleShift)) == kMaxJSDispatchEntries,
828 "kJSDispatchTableReservationSize and kJSDispatchEntryHandleShift "
829 "don't match");
830
831// {obj} must be the raw tagged pointer representation of a HeapObject
832// that's guaranteed to never be in ReadOnlySpace.
835// Returns if we need to throw when an error occurs. This infers the language
836// mode based on the current context and the closure. This returns true if the
837// language mode is strict.
838V8_EXPORT bool ShouldThrowOnError(internal::Isolate* isolate);
844class Internals {
845#ifdef V8_MAP_PACKING
846 V8_INLINE static constexpr Address UnpackMapWord(Address mapword) {
847 // TODO(wenyuzhao): Clear header metadata.
848 return mapword ^ kMapWordXorMask;
849 }
850#endif
852 public:
853 // These values match non-compiler-dependent values defined within
854 // the implementation of v8.
855 static const int kHeapObjectMapOffset = 0;
857 static const int kStringResourceOffset =
859
860 static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
861 static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
862#ifdef V8_COMPRESS_POINTERS
865#else // !V8_COMPRESS_POINTERS
868#endif // !V8_COMPRESS_POINTERS
869 static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
870 static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
872#ifdef V8_ENABLE_SANDBOX
874#else
876#endif
878 static const int kStringRepresentationAndEncodingMask = 0x0f;
879 static const int kStringEncodingMask = 0x8;
880 static const int kExternalTwoByteRepresentationTag = 0x02;
881 static const int kExternalOneByteRepresentationTag = 0x0a;
883 static const uint32_t kNumIsolateDataSlots = 4;
885 static const int kNumberOfBooleanFlags = 6;
886 static const int kErrorMessageParamSize = 1;
887 static const int kTablesAlignmentPaddingSize = 1;
889 static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
891 static const int kThreadLocalTopSize = 30 * kApiSystemPointerSize;
892 static const int kHandleScopeDataSize =
895 // ExternalPointerTable and TrustedPointerTable layout guarantees.
898 static const int kExternalBufferTableSize = 2 * kApiSystemPointerSize;
901
902 // IsolateData layout guarantees.
903 static const int kIsolateCageBaseOffset = 0;
904 static const int kIsolateStackGuardOffset =
906 static const int kVariousBooleanFlagsOffset =
908 static const int kErrorMessageParamOffset =
913 static const int kBuiltinTier0TableOffset =
915 static const int kNewAllocationInfoOffset =
917 static const int kOldAllocationInfoOffset =
919
920 static const int kFastCCallAlignmentPaddingSize =
922 static const int kIsolateFastCCallCallerFpOffset =
933 static const int kIsolateHandleScopeDataOffset =
935 static const int kIsolateEmbedderDataOffset =
937#ifdef V8_COMPRESS_POINTERS
938 static const int kIsolateExternalPointerTableOffset =
940 static const int kIsolateSharedExternalPointerTableAddressOffset =
941 kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
942 static const int kIsolateCppHeapPointerTableOffset =
943 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
944#ifdef V8_ENABLE_SANDBOX
945 static const int kIsolateTrustedCageBaseOffset =
946 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
947 static const int kIsolateTrustedPointerTableOffset =
948 kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
949 static const int kIsolateExternalBufferTableOffset =
950 kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
951 static const int kIsolateSharedExternalBufferTableAddressOffset =
952 kIsolateExternalBufferTableOffset + kExternalBufferTableSize;
954 kIsolateSharedExternalBufferTableAddressOffset + kApiSystemPointerSize;
955#else
957 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
958#endif // V8_ENABLE_SANDBOX
959#else
962#endif // V8_COMPRESS_POINTERS
965 static const int kIsolateRootsOffset =
967
968 // Assert scopes
969 static const int kDisallowGarbageCollectionAlign = alignof(uint32_t);
970 static const int kDisallowGarbageCollectionSize = sizeof(uint32_t);
971
972#if V8_STATIC_ROOTS_BOOL
973
974// These constants are copied from static-roots.h and guarded by static asserts.
975#define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
976 V(UndefinedValue, 0x69) \
977 V(NullValue, 0x85) \
978 V(TrueValue, 0xc9) \
979 V(FalseValue, 0xad) \
980 V(EmptyString, 0xa1) \
981 V(TheHoleValue, 0x741)
982
983 using Tagged_t = uint32_t;
984 struct StaticReadOnlyRoot {
985#define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
986 EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
987#undef DEF_ROOT
988
989 // Use 0 for kStringMapLowerBound since string maps are the first maps.
990 static constexpr Tagged_t kStringMapLowerBound = 0;
991 static constexpr Tagged_t kStringMapUpperBound = 0x47d;
992
993#define PLUSONE(...) +1
994 static constexpr size_t kNumberOfExportedStaticRoots =
995 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
996#undef PLUSONE
997 };
999#endif // V8_STATIC_ROOTS_BOOL
1001 static const int kUndefinedValueRootIndex = 4;
1002 static const int kTheHoleValueRootIndex = 5;
1003 static const int kNullValueRootIndex = 6;
1004 static const int kTrueValueRootIndex = 7;
1005 static const int kFalseValueRootIndex = 8;
1006 static const int kEmptyStringRootIndex = 9;
1008 static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
1009 static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
1010 static const int kNodeStateMask = 0x3;
1011 static const int kNodeStateIsWeakValue = 2;
1013 static const int kFirstNonstringType = 0x80;
1014 static const int kOddballType = 0x83;
1015 static const int kForeignType = 0xcc;
1016 static const int kJSSpecialApiObjectType = 0x410;
1017 static const int kJSObjectType = 0x421;
1018 static const int kFirstJSApiObjectType = 0x422;
1019 static const int kLastJSApiObjectType = 0x80A;
1020 // Defines a range [kFirstEmbedderJSApiObjectType, kJSApiObjectTypesCount]
1021 // of JSApiObject instance type values that an embedder can use.
1022 static const int kFirstEmbedderJSApiObjectType = 0;
1025
1026 static const int kUndefinedOddballKind = 4;
1027 static const int kNullOddballKind = 3;
1029 // Constants used by PropertyCallbackInfo to check if we should throw when an
1030 // error occurs.
1031 static const int kDontThrow = 0;
1032 static const int kThrowOnError = 1;
1033 static const int kInferShouldThrowMode = 2;
1034
1035 // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
1036 // incremental GC once the external memory reaches this limit.
1037 static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
1038
1039#ifdef V8_MAP_PACKING
1040 static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
1041 // The lowest two bits of mapwords are always `0b10`
1042 static const uintptr_t kMapWordSignature = 0b10;
1043 // XORing a (non-compressed) map with this mask ensures that the two
1044 // low-order bits are 0b10. The 0 at the end makes this look like a Smi,
1045 // although real Smis have all lower 32 bits unset. We only rely on these
1046 // values passing as Smis in very few places.
1047 static const int kMapWordXorMask = 0b11;
1048#endif
1049
1050 V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
1051 V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
1052#ifdef V8_ENABLE_CHECKS
1054#endif
1055 }
1056
1057 V8_INLINE static constexpr bool HasHeapObjectTag(Address value) {
1058 return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
1059 }
1060
1061 V8_INLINE static constexpr int SmiValue(Address value) {
1062 return PlatformSmiTagging::SmiToInt(value);
1063 }
1064
1065 V8_INLINE static constexpr Address AddressToSmi(Address value) {
1066 return (value << (kSmiTagSize + PlatformSmiTagging::kSmiShiftSize)) |
1067 kSmiTag;
1068 }
1069
1070 V8_INLINE static constexpr Address IntToSmi(int value) {
1071 return AddressToSmi(static_cast<Address>(value));
1073
1074 template <typename T,
1075 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1076 V8_INLINE static constexpr Address IntegralToSmi(T value) {
1077 return AddressToSmi(static_cast<Address>(value));
1079
1080 template <typename T,
1081 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1082 V8_INLINE static constexpr bool IsValidSmi(T value) {
1083 return PlatformSmiTagging::IsValidSmi(value);
1085
1086 template <typename T,
1087 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1088 static constexpr std::optional<Address> TryIntegralToSmi(T value) {
1089 if (V8_LIKELY(PlatformSmiTagging::IsValidSmi(value))) {
1090 return {AddressToSmi(static_cast<Address>(value))};
1091 }
1092 return {};
1093 }
1094
1095#if V8_STATIC_ROOTS_BOOL
1096 V8_INLINE static bool is_identical(Address obj, Tagged_t constant) {
1097 return static_cast<Tagged_t>(obj) == constant;
1098 }
1099
1100 V8_INLINE static bool CheckInstanceMapRange(Address obj, Tagged_t first_map,
1101 Tagged_t last_map) {
1102 auto map = ReadRawField<Tagged_t>(obj, kHeapObjectMapOffset);
1103#ifdef V8_MAP_PACKING
1104 map = UnpackMapWord(map);
1105#endif
1106 return map >= first_map && map <= last_map;
1107 }
1108#endif
1109
1110 V8_INLINE static int GetInstanceType(Address obj) {
1112#ifdef V8_MAP_PACKING
1113 map = UnpackMapWord(map);
1114#endif
1115 return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
1116 }
1117
1118 V8_INLINE static Address LoadMap(Address obj) {
1119 if (!HasHeapObjectTag(obj)) return kNullAddress;
1121#ifdef V8_MAP_PACKING
1122 map = UnpackMapWord(map);
1123#endif
1124 return map;
1125 }
1126
1129 }
1130
1131 V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
1132 int representation = (instance_type & kStringRepresentationAndEncodingMask);
1133 return representation == kExternalTwoByteRepresentationTag;
1134 }
1135
1136 V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
1137 static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
1138 static_assert(kJSObjectType < kLastJSApiObjectType);
1140 // Check for IsJSObject() || IsJSSpecialApiObject() || IsJSApiObject()
1141 return instance_type == kJSSpecialApiObjectType ||
1142 // inlined version of base::IsInRange
1143 (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
1144 static_cast<unsigned>(kJSObjectType)) <=
1145 static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
1146 }
1147
1148 V8_INLINE static uint8_t GetNodeFlag(Address* obj, int shift) {
1149 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1150 return *addr & static_cast<uint8_t>(1U << shift);
1151 }
1152
1153 V8_INLINE static void UpdateNodeFlag(Address* obj, bool value, int shift) {
1154 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1155 uint8_t mask = static_cast<uint8_t>(1U << shift);
1156 *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
1157 }
1158
1159 V8_INLINE static uint8_t GetNodeState(Address* obj) {
1160 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1161 return *addr & kNodeStateMask;
1162 }
1163
1164 V8_INLINE static void UpdateNodeState(Address* obj, uint8_t value) {
1165 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1166 *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
1167 }
1168
1169 V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
1170 void* data) {
1171 Address addr = reinterpret_cast<Address>(isolate) +
1173 *reinterpret_cast<void**>(addr) = data;
1174 }
1175
1176 V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
1177 uint32_t slot) {
1178 Address addr = reinterpret_cast<Address>(isolate) +
1180 return *reinterpret_cast<void* const*>(addr);
1181 }
1182
1184 Address addr =
1185 reinterpret_cast<Address>(isolate) + kIsolateLongTaskStatsCounterOffset;
1186 ++(*reinterpret_cast<size_t*>(addr));
1187 }
1188
1189 V8_INLINE static Address* GetRootSlot(v8::Isolate* isolate, int index) {
1190 Address addr = reinterpret_cast<Address>(isolate) + kIsolateRootsOffset +
1192 return reinterpret_cast<Address*>(addr);
1193 }
1194
1195 V8_INLINE static Address GetRoot(v8::Isolate* isolate, int index) {
1196#if V8_STATIC_ROOTS_BOOL
1197 Address base = *reinterpret_cast<Address*>(
1198 reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
1199 switch (index) {
1200#define DECOMPRESS_ROOT(name, ...) \
1201 case k##name##RootIndex: \
1202 return base + StaticReadOnlyRoot::k##name;
1203 EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
1204#undef DECOMPRESS_ROOT
1205#undef EXPORTED_STATIC_ROOTS_PTR_LIST
1206 default:
1207 break;
1208 }
1209#endif // V8_STATIC_ROOTS_BOOL
1210 return *GetRootSlot(isolate, index);
1211 }
1212
1213#ifdef V8_ENABLE_SANDBOX
1214 V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) {
1215 Address addr = reinterpret_cast<Address>(isolate) +
1216 kIsolateExternalPointerTableOffset +
1218 return *reinterpret_cast<Address**>(addr);
1219 }
1220
1221 V8_INLINE static Address* GetSharedExternalPointerTableBase(
1222 v8::Isolate* isolate) {
1223 Address addr = reinterpret_cast<Address>(isolate) +
1224 kIsolateSharedExternalPointerTableAddressOffset;
1225 addr = *reinterpret_cast<Address*>(addr);
1227 return *reinterpret_cast<Address**>(addr);
1229#endif
1230
1231 template <typename T>
1232 V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
1233 Address addr = heap_object_ptr + offset - kHeapObjectTag;
1234#ifdef V8_COMPRESS_POINTERS
1235 if (sizeof(T) > kApiTaggedSize) {
1236 // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
1237 // fields (external pointers, doubles and BigInt data) are only
1238 // kTaggedSize aligned so we have to use unaligned pointer friendly way of
1239 // accessing them in order to avoid undefined behavior in C++ code.
1240 T r;
1241 memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
1242 return r;
1243 }
1244#endif
1245 return *reinterpret_cast<const T*>(addr);
1246 }
1247
1248 V8_INLINE static Address ReadTaggedPointerField(Address heap_object_ptr,
1249 int offset) {
1250#ifdef V8_COMPRESS_POINTERS
1251 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1252 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1253 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1254#else
1255 return ReadRawField<Address>(heap_object_ptr, offset);
1256#endif
1257 }
1258
1259 V8_INLINE static Address ReadTaggedSignedField(Address heap_object_ptr,
1260 int offset) {
1261#ifdef V8_COMPRESS_POINTERS
1262 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1263 return static_cast<Address>(static_cast<uintptr_t>(value));
1264#else
1265 return ReadRawField<Address>(heap_object_ptr, offset);
1266#endif
1267 }
1268
1270#ifdef V8_ENABLE_SANDBOX
1271 return reinterpret_cast<v8::Isolate*>(
1273#else
1274 // Not used in non-sandbox mode.
1275 return nullptr;
1276#endif
1277 }
1278
1279 template <ExternalPointerTag tag>
1281 Address heap_object_ptr,
1282 int offset) {
1283#ifdef V8_ENABLE_SANDBOX
1284 static_assert(tag != kExternalPointerNullTag);
1285 // See src/sandbox/external-pointer-table-inl.h. Logic duplicated here so
1286 // it can be inlined and doesn't require an additional call.
1287 Address* table = IsSharedExternalPointerType(tag)
1288 ? GetSharedExternalPointerTableBase(isolate)
1289 : GetExternalPointerTableBase(isolate);
1291 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1292 uint32_t index = handle >> kExternalPointerIndexShift;
1293 std::atomic<Address>* ptr =
1294 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1295 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1296 return entry & ~tag;
1297#else
1298 return ReadRawField<Address>(heap_object_ptr, offset);
1299#endif // V8_ENABLE_SANDBOX
1300 }
1301
1302#ifdef V8_COMPRESS_POINTERS
1303 V8_INLINE static Address GetPtrComprCageBaseFromOnHeapAddress(Address addr) {
1304 return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
1305 }
1306
1307 V8_INLINE static uint32_t CompressTagged(Address value) {
1308 return static_cast<uint32_t>(value);
1309 }
1310
1311 V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
1312 uint32_t value) {
1313 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1314 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1315 }
1316
1317#endif // V8_COMPRESS_POINTERS
1318};
1320// Only perform cast check for types derived from v8::Data since
1321// other types do not implement the Cast method.
1322template <bool PerformCheck>
1323struct CastCheck {
1324 template <class T>
1325 static void Perform(T* data);
1327
1328template <>
1329template <class T>
1330void CastCheck<true>::Perform(T* data) {
1331 T::Cast(data);
1333
1334template <>
1335template <class T>
1336void CastCheck<false>::Perform(T* data) {}
1337
1338template <class T>
1339V8_INLINE void PerformCastCheck(T* data) {
1340 CastCheck<std::is_base_of<Data, T>::value &&
1341 !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
1343
1344// A base class for backing stores, which is needed due to vagaries of
1345// how static casts work with std::shared_ptr.
1347
1348// The maximum value in enum GarbageCollectionReason, defined in heap.h.
1349// This is needed for histograms sampling garbage collection reasons.
1351
1352// Base class for the address block allocator compatible with standard
1353// containers, which registers its allocated range as strong roots.
1355 public:
1356 Heap* heap() const { return heap_; }
1358 bool operator==(const StrongRootAllocatorBase& other) const {
1359 return heap_ == other.heap_;
1360 }
1361 bool operator!=(const StrongRootAllocatorBase& other) const {
1362 return heap_ != other.heap_;
1364
1365 protected:
1366 explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
1368
1369 // Allocate/deallocate a range of n elements of type internal::Address.
1370 Address* allocate_impl(size_t n);
1371 void deallocate_impl(Address* p, size_t n) noexcept;
1372
1373 private:
1374 Heap* heap_;
1375};
1376
1377// The general version of this template behaves just as std::allocator, with
1378// the exception that the constructor takes the isolate as parameter. Only
1379// specialized versions, e.g., internal::StrongRootAllocator<internal::Address>
1380// and internal::StrongRootAllocator<v8::Local<T>> register the allocated range
1381// as strong roots.
1382template <typename T>
1383class StrongRootAllocator : private std::allocator<T> {
1384 public:
1385 using value_type = T;
1386
1387 explicit StrongRootAllocator(Heap* heap) {}
1388 explicit StrongRootAllocator(Isolate* isolate) {}
1389 explicit StrongRootAllocator(v8::Isolate* isolate) {}
1390 template <typename U>
1391 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept {}
1392
1393 using std::allocator<T>::allocate;
1394 using std::allocator<T>::deallocate;
1395};
1396
1397// A class of iterators that wrap some different iterator type.
1398// If specified, ElementType is the type of element accessed by the wrapper
1399// iterator; in this case, the actual reference and pointer types of Iterator
1400// must be convertible to ElementType& and ElementType*, respectively.
1401template <typename Iterator, typename ElementType = void>
1402class WrappedIterator {
1403 public:
1404 static_assert(
1405 !std::is_void_v<ElementType> ||
1406 (std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
1407 ElementType*> &&
1408 std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
1409 ElementType&>));
1410
1412 typename std::iterator_traits<Iterator>::iterator_category;
1413 using difference_type =
1414 typename std::iterator_traits<Iterator>::difference_type;
1416 std::conditional_t<std::is_void_v<ElementType>,
1417 typename std::iterator_traits<Iterator>::value_type,
1418 ElementType>;
1419 using pointer =
1420 std::conditional_t<std::is_void_v<ElementType>,
1421 typename std::iterator_traits<Iterator>::pointer,
1422 ElementType*>;
1423 using reference =
1424 std::conditional_t<std::is_void_v<ElementType>,
1425 typename std::iterator_traits<Iterator>::reference,
1426 ElementType&>;
1427
1428 constexpr WrappedIterator() noexcept : it_() {}
1429 constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
1431 template <typename OtherIterator, typename OtherElementType,
1432 std::enable_if_t<std::is_convertible_v<OtherIterator, Iterator>,
1433 bool> = true>
1436 : it_(it.base()) {}
1438 constexpr reference operator*() const noexcept { return *it_; }
1439 constexpr pointer operator->() const noexcept { return it_.operator->(); }
1440
1441 constexpr WrappedIterator& operator++() noexcept {
1442 ++it_;
1443 return *this;
1444 }
1445 constexpr WrappedIterator operator++(int) noexcept {
1446 WrappedIterator result(*this);
1447 ++(*this);
1448 return result;
1449 }
1450
1451 constexpr WrappedIterator& operator--() noexcept {
1452 --it_;
1453 return *this;
1454 }
1455 constexpr WrappedIterator operator--(int) noexcept {
1456 WrappedIterator result(*this);
1457 --(*this);
1458 return result;
1459 }
1460 constexpr WrappedIterator operator+(difference_type n) const noexcept {
1461 WrappedIterator result(*this);
1462 result += n;
1463 return result;
1464 }
1466 it_ += n;
1467 return *this;
1469 constexpr WrappedIterator operator-(difference_type n) const noexcept {
1470 return *this + (-n);
1471 }
1473 *this += -n;
1474 return *this;
1475 }
1476 constexpr reference operator[](difference_type n) const noexcept {
1477 return it_[n];
1478 }
1479
1480 constexpr Iterator base() const noexcept { return it_; }
1481
1482 private:
1483 template <typename OtherIterator, typename OtherElementType>
1484 friend class WrappedIterator;
1485
1486 private:
1487 Iterator it_;
1489
1490template <typename Iterator, typename ElementType, typename OtherIterator,
1491 typename OtherElementType>
1492constexpr bool operator==(
1493 const WrappedIterator<Iterator, ElementType>& x,
1494 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1495 return x.base() == y.base();
1497
1498template <typename Iterator, typename ElementType, typename OtherIterator,
1499 typename OtherElementType>
1500constexpr bool operator<(
1501 const WrappedIterator<Iterator, ElementType>& x,
1502 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1503 return x.base() < y.base();
1505
1506template <typename Iterator, typename ElementType, typename OtherIterator,
1507 typename OtherElementType>
1508constexpr bool operator!=(
1509 const WrappedIterator<Iterator, ElementType>& x,
1510 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1511 return !(x == y);
1513
1514template <typename Iterator, typename ElementType, typename OtherIterator,
1515 typename OtherElementType>
1516constexpr bool operator>(
1517 const WrappedIterator<Iterator, ElementType>& x,
1518 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1519 return y < x;
1521
1522template <typename Iterator, typename ElementType, typename OtherIterator,
1523 typename OtherElementType>
1524constexpr bool operator>=(
1525 const WrappedIterator<Iterator, ElementType>& x,
1526 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1527 return !(x < y);
1529
1530template <typename Iterator, typename ElementType, typename OtherIterator,
1531 typename OtherElementType>
1532constexpr bool operator<=(
1533 const WrappedIterator<Iterator, ElementType>& x,
1534 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1535 return !(y < x);
1537
1538template <typename Iterator, typename ElementType, typename OtherIterator,
1539 typename OtherElementType>
1540constexpr auto operator-(
1541 const WrappedIterator<Iterator, ElementType>& x,
1542 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept
1543 -> decltype(x.base() - y.base()) {
1544 return x.base() - y.base();
1545}
1546
1547template <typename Iterator, typename ElementType>
1548constexpr WrappedIterator<Iterator> operator+(
1550 const WrappedIterator<Iterator, ElementType>& x) noexcept {
1551 x += n;
1552 return x;
1553}
1555// Helper functions about values contained in handles.
1556// A value is either an indirect pointer or a direct pointer, depending on
1557// whether direct local support is enabled.
1558class ValueHelper final {
1559 public:
1560#ifdef V8_ENABLE_DIRECT_HANDLE
1561 static constexpr Address kTaggedNullAddress = 1;
1562 static constexpr Address kEmpty = kTaggedNullAddress;
1563#else
1564 static constexpr Address kEmpty = kNullAddress;
1565#endif // V8_ENABLE_DIRECT_HANDLE
1566
1567 template <typename T>
1568 V8_INLINE static bool IsEmpty(T* value) {
1569 return reinterpret_cast<Address>(value) == kEmpty;
1570 }
1571
1572 // Returns a handle's "value" for all kinds of abstract handles. For Local,
1573 // it is equivalent to `*handle`. The variadic parameters support handle
1574 // types with extra type parameters, like `Persistent<T, M>`.
1575 template <template <typename T, typename... Ms> typename H, typename T,
1576 typename... Ms>
1577 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
1578 return handle.template value<T>();
1579 }
1580
1581#ifdef V8_ENABLE_DIRECT_HANDLE
1582
1583 template <typename T>
1584 V8_INLINE static Address ValueAsAddress(const T* value) {
1585 return reinterpret_cast<Address>(value);
1586 }
1587
1588 template <typename T, bool check_null = true, typename S>
1589 V8_INLINE static T* SlotAsValue(S* slot) {
1590 if (check_null && slot == nullptr) {
1591 return reinterpret_cast<T*>(kTaggedNullAddress);
1592 }
1593 return *reinterpret_cast<T**>(slot);
1594 }
1596#else // !V8_ENABLE_DIRECT_HANDLE
1597
1598 template <typename T>
1599 V8_INLINE static Address ValueAsAddress(const T* value) {
1600 return *reinterpret_cast<const Address*>(value);
1601 }
1602
1603 template <typename T, bool check_null = true, typename S>
1604 V8_INLINE static T* SlotAsValue(S* slot) {
1605 return reinterpret_cast<T*>(slot);
1606 }
1607
1608#endif // V8_ENABLE_DIRECT_HANDLE
1609};
1614class HandleHelper final {
1615 public:
1626 template <typename T1, typename T2>
1627 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
1628 if (lhs.IsEmpty()) return rhs.IsEmpty();
1629 if (rhs.IsEmpty()) return false;
1630 return lhs.ptr() == rhs.ptr();
1631 }
1632};
1633
1634V8_EXPORT void VerifyHandleIsNonEmpty(bool is_empty);
1635
1636// These functions are here just to match friend declarations in
1637// XxxCallbackInfo classes allowing these functions to access the internals
1638// of the info objects. These functions are supposed to be called by debugger
1639// macros.
1640void PrintFunctionCallbackInfo(void* function_callback_info);
1641void PrintPropertyCallbackInfo(void* property_callback_info);
1642
1643} // namespace internal
1644} // namespace v8
1645
1646#endif // INCLUDE_V8_INTERNAL_H_
Definition: v8-isolate.h:211
Definition: v8-internal.h:1342
Definition: v8-internal.h:1610
static bool EqualHandles(const T1 &lhs, const T2 &rhs)
Definition: v8-internal.h:1623
Definition: v8-internal.h:840
static Address LoadMap(Address obj)
Definition: v8-internal.h:1114
static bool IsExternalTwoByteString(int instance_type)
Definition: v8-internal.h:1127
static const int kIsolateCageBaseOffset
Definition: v8-internal.h:899
static const int kEmbedderDataArrayHeaderSize
Definition: v8-internal.h:866
static const int kHeapObjectMapOffset
Definition: v8-internal.h:851
static const int kEmbedderDataSlotSize
Definition: v8-internal.h:867
static const int kIsolateApiCallbackThunkArgumentOffset
Definition: v8-internal.h:956
static Address ReadExternalPointerField(v8::Isolate *isolate, Address heap_object_ptr, int offset)
Definition: v8-internal.h:1276
static const int kJSAPIObjectWithEmbedderSlotsHeaderSize
Definition: v8-internal.h:862
static constexpr bool HasHeapObjectTag(Address value)
Definition: v8-internal.h:1053
static const int kOddballType
Definition: v8-internal.h:1010
static const int kInferShouldThrowMode
Definition: v8-internal.h:1029
static const int kNewAllocationInfoOffset
Definition: v8-internal.h:911
static Address GetRoot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1191
static const int kStringEncodingMask
Definition: v8-internal.h:875
static const int kIsolateFastCCallCallerPcOffset
Definition: v8-internal.h:921
static uint8_t GetNodeFlag(Address *obj, int shift)
Definition: v8-internal.h:1144
static const int kIsolateThreadLocalTopOffset
Definition: v8-internal.h:927
static const uint32_t kNumIsolateDataSlots
Definition: v8-internal.h:879
static const int kForeignType
Definition: v8-internal.h:1011
static const int kFirstEmbedderJSApiObjectType
Definition: v8-internal.h:1018
static const int kNumberOfBooleanFlags
Definition: v8-internal.h:881
static uint8_t GetNodeState(Address *obj)
Definition: v8-internal.h:1155
static const int kThreadLocalTopSize
Definition: v8-internal.h:887
static const int kIsolateRootsOffset
Definition: v8-internal.h:961
static const int kExternalPointerTableSize
Definition: v8-internal.h:893
static const int kUndefinedOddballKind
Definition: v8-internal.h:1022
static const int kMapInstanceTypeOffset
Definition: v8-internal.h:852
static constexpr Address AddressToSmi(Address value)
Definition: v8-internal.h:1061
static const int kIsolateStackGuardOffset
Definition: v8-internal.h:900
static const int kLinearAllocationAreaSize
Definition: v8-internal.h:886
static const int kFastCCallAlignmentPaddingSize
Definition: v8-internal.h:916
static const int kDisallowGarbageCollectionAlign
Definition: v8-internal.h:965
static const int kIsolateFastCCallCallerFpOffset
Definition: v8-internal.h:918
static const int kErrorMessageParamSize
Definition: v8-internal.h:882
static void CheckInitialized(v8::Isolate *isolate)
Definition: v8-internal.h:1047
static void UpdateNodeState(Address *obj, uint8_t value)
Definition: v8-internal.h:1160
static constexpr Address IntegralToSmi(T value)
Definition: v8-internal.h:1072
static constexpr bool IsValidSmi(T value)
Definition: v8-internal.h:1078
static const int kJSObjectType
Definition: v8-internal.h:1013
static const int kBuiltinTier0TableOffset
Definition: v8-internal.h:909
static const int kIsolateLongTaskStatsCounterOffset
Definition: v8-internal.h:925
static const int kNativeContextEmbedderDataOffset
Definition: v8-internal.h:873
static const int kLastJSApiObjectType
Definition: v8-internal.h:1015
static constexpr bool CanHaveInternalField(int instance_type)
Definition: v8-internal.h:1132
static const int kIsolateHandleScopeDataOffset
Definition: v8-internal.h:929
static const int kFirstNonstringType
Definition: v8-internal.h:1009
static const int kEmptyStringRootIndex
Definition: v8-internal.h:1002
static const int kBuiltinTier0EntryTableOffset
Definition: v8-internal.h:906
static const int kFixedArrayHeaderSize
Definition: v8-internal.h:865
static const int kNullOddballKind
Definition: v8-internal.h:1023
static const int kUndefinedValueRootIndex
Definition: v8-internal.h:997
static const int kExternalTwoByteRepresentationTag
Definition: v8-internal.h:876
static const int kExternalBufferTableSize
Definition: v8-internal.h:894
static constexpr Address IntToSmi(int value)
Definition: v8-internal.h:1066
static const int kDontThrow
Definition: v8-internal.h:1027
static void CheckInitializedImpl(v8::Isolate *isolate)
static void * GetEmbedderData(const v8::Isolate *isolate, uint32_t slot)
Definition: v8-internal.h:1172
static const int kStackGuardSize
Definition: v8-internal.h:880
static const int kNodeStateMask
Definition: v8-internal.h:1006
static const int kNodeStateIsWeakValue
Definition: v8-internal.h:1007
static const int kFirstJSApiObjectType
Definition: v8-internal.h:1014
static const int kStringResourceOffset
Definition: v8-internal.h:853
static const int kErrorMessageParamOffset
Definition: v8-internal.h:904
static const int kExternalPointerTableBasePointerOffset
Definition: v8-internal.h:892
static const int kFalseValueRootIndex
Definition: v8-internal.h:1001
static const int kIsolateFastApiCallTargetOffset
Definition: v8-internal.h:923
static const int kTrueValueRootIndex
Definition: v8-internal.h:1000
static int GetInstanceType(Address obj)
Definition: v8-internal.h:1106
static const int kThrowOnError
Definition: v8-internal.h:1028
static Address ReadTaggedSignedField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1255
static const int kOddballKindOffset
Definition: v8-internal.h:856
static const int kBuiltinTier0TableSize
Definition: v8-internal.h:885
static const int kContinuationPreservedEmbedderDataOffset
Definition: v8-internal.h:959
static Address ReadTaggedPointerField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1244
static const int kNullValueRootIndex
Definition: v8-internal.h:999
static void SetEmbedderData(v8::Isolate *isolate, uint32_t slot, void *data)
Definition: v8-internal.h:1165
static Address * GetRootSlot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1185
static const int kTrustedPointerTableSize
Definition: v8-internal.h:895
static const int kTheHoleValueRootIndex
Definition: v8-internal.h:998
static constexpr int SmiValue(Address value)
Definition: v8-internal.h:1057
static const int kTablesAlignmentPaddingSize
Definition: v8-internal.h:883
static const int kHandleScopeDataSize
Definition: v8-internal.h:888
static const int kExternalOneByteRepresentationTag
Definition: v8-internal.h:877
static const int kBuiltinTier0EntryTableSize
Definition: v8-internal.h:884
static void UpdateNodeFlag(Address *obj, bool value, int shift)
Definition: v8-internal.h:1149
static void IncrementLongTasksStatsCounter(v8::Isolate *isolate)
Definition: v8-internal.h:1179
static const int kDisallowGarbageCollectionSize
Definition: v8-internal.h:966
static const int kOldAllocationInfoOffset
Definition: v8-internal.h:913
static const int kIsolateEmbedderDataOffset
Definition: v8-internal.h:931
static T ReadRawField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1228
static const int kEmbedderDataSlotExternalPointerOffset
Definition: v8-internal.h:871
static int GetOddballKind(Address obj)
Definition: v8-internal.h:1123
static const int kNodeFlagsOffset
Definition: v8-internal.h:1005
static const int kTrustedPointerTableBasePointerOffset
Definition: v8-internal.h:896
static const int kLastEmbedderJSApiObjectType
Definition: v8-internal.h:1019
static const int kVariousBooleanFlagsOffset
Definition: v8-internal.h:902
static constexpr std::optional< Address > TryIntegralToSmi(T value)
Definition: v8-internal.h:1084
static const int kNodeClassIdOffset
Definition: v8-internal.h:1004
static const int kStringRepresentationAndEncodingMask
Definition: v8-internal.h:874
static constexpr int kExternalAllocationSoftLimit
Definition: v8-internal.h:1033
static const int kJSObjectHeaderSize
Definition: v8-internal.h:857
static v8::Isolate * GetIsolateForSandbox(Address obj)
Definition: v8-internal.h:1265
static const int kJSSpecialApiObjectType
Definition: v8-internal.h:1012
Definition: v8-internal.h:1350
Definition: v8-internal.h:1379
T value_type
Definition: v8-internal.h:1381
StrongRootAllocator(const StrongRootAllocator< U > &other) noexcept
Definition: v8-internal.h:1387
Definition: v8-internal.h:1554
static Address ValueAsAddress(const T *value)
Definition: v8-internal.h:1595
static constexpr Address kEmpty
Definition: v8-internal.h:1560
static T * SlotAsValue(S *slot)
Definition: v8-internal.h:1600
static T * HandleAsValue(const H< T, Ms... > &handle)
Definition: v8-internal.h:1573
static bool IsEmpty(T *value)
Definition: v8-internal.h:1564
Definition: v8-internal.h:1398
constexpr WrappedIterator & operator-=(difference_type n) noexcept
Definition: v8-internal.h:1468
constexpr WrappedIterator operator--(int) noexcept
Definition: v8-internal.h:1451
constexpr WrappedIterator & operator+=(difference_type n) noexcept
Definition: v8-internal.h:1461
constexpr Iterator base() const noexcept
Definition: v8-internal.h:1476
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::reference, ElementType & > reference
Definition: v8-internal.h:1422
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::value_type, ElementType > value_type
Definition: v8-internal.h:1414
constexpr WrappedIterator & operator++() noexcept
Definition: v8-internal.h:1437
constexpr pointer operator->() const noexcept
Definition: v8-internal.h:1435
constexpr reference operator[](difference_type n) const noexcept
Definition: v8-internal.h:1472
typename std::iterator_traits< Iterator >::difference_type difference_type
Definition: v8-internal.h:1410
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::pointer, ElementType * > pointer
Definition: v8-internal.h:1418
constexpr WrappedIterator & operator--() noexcept
Definition: v8-internal.h:1447
typename std::iterator_traits< Iterator >::iterator_category iterator_category
Definition: v8-internal.h:1408
constexpr reference operator*() const noexcept
Definition: v8-internal.h:1434
constexpr WrappedIterator operator+(difference_type n) const noexcept
Definition: v8-internal.h:1456
constexpr WrappedIterator operator++(int) noexcept
Definition: v8-internal.h:1441
constexpr WrappedIterator operator-(difference_type n) const noexcept
Definition: v8-internal.h:1465
friend class WrappedIterator
Definition: v8-internal.h:1480
const intptr_t kHeapObjectTagMask
Definition: v8-internal.h:56
constexpr uint64_t kCppHeapPointerMarkBit
Definition: v8-internal.h:362
constexpr int kCodePointerTableEntrySizeLog2
Definition: v8-internal.h:786
constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:798
uint32_t ExternalBufferHandle
Definition: v8-internal.h:393
internal::Isolate * IsolateFromNeverReadOnlySpaceObject(Address obj)
constexpr uint64_t kExternalPointerTagShift
Definition: v8-internal.h:504
IndirectPointerHandle TrustedPointerHandle
Definition: v8-internal.h:721
const int kApiSystemPointerSize
Definition: v8-internal.h:46
constexpr bool SandboxIsEnabled()
Definition: v8-internal.h:201
constexpr size_t kExternalBufferTableReservationSize
Definition: v8-internal.h:414
const int kApiDoubleSize
Definition: v8-internal.h:47
constexpr bool operator<=(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1528
constexpr size_t kMaxCppHeapPointers
Definition: v8-internal.h:385
constexpr intptr_t kIntptrAllBitsSet
Definition: v8-internal.h:74
constexpr int GB
Definition: v8-internal.h:38
void VerifyHandleIsNonEmpty(bool is_empty)
const int kApiInt32Size
Definition: v8-internal.h:48
constexpr uint32_t kJSDispatchHandleShift
Definition: v8-internal.h:816
const int kForwardingTagSize
Definition: v8-internal.h:63
uint32_t CppHeapPointerHandle
Definition: v8-internal.h:347
const intptr_t kForwardingTagMask
Definition: v8-internal.h:64
void PrintPropertyCallbackInfo(void *property_callback_info)
IndirectPointerHandle CodePointerHandle
Definition: v8-internal.h:759
constexpr size_t kMaxExternalBufferPointers
Definition: v8-internal.h:424
const int kSmiTagSize
Definition: v8-internal.h:68
const int kApiInt64Size
Definition: v8-internal.h:49
constexpr int kExternalBufferTableEntrySizeLog2
Definition: v8-internal.h:423
constexpr uint64_t kExternalPointerTagMask
Definition: v8-internal.h:502
constexpr int kCodePointerTableEntryCodeObjectOffset
Definition: v8-internal.h:794
constexpr int kTrustedPointerTableEntrySizeLog2
Definition: v8-internal.h:738
constexpr size_t kJSDispatchTableReservationSize
Definition: v8-internal.h:815
constexpr int kTrustedPointerTableEntrySize
Definition: v8-internal.h:737
constexpr uint64_t kCppHeapPointerPayloadShift
Definition: v8-internal.h:364
constexpr ExternalPointer_t kNullExternalPointer
Definition: v8-internal.h:339
constexpr bool operator>(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1512
Address ExternalPointer_t
Definition: v8-internal.h:336
constexpr WrappedIterator< Iterator > operator+(typename WrappedIterator< Iterator, ElementType >::difference_type n, const WrappedIterator< Iterator, ElementType > &x) noexcept
Definition: v8-internal.h:1544
uint32_t IndirectPointerHandle
Definition: v8-internal.h:701
constexpr CppHeapPointer_t kNullCppHeapPointer
Definition: v8-internal.h:359
const int kApiSizetSize
Definition: v8-internal.h:50
constexpr int kCodePointerTableEntryEntrypointOffset
Definition: v8-internal.h:793
constexpr size_t kMaxExternalPointers
Definition: v8-internal.h:317
constexpr uint64_t kExternalPointerTagMaskWithoutMarkBit
Definition: v8-internal.h:503
constexpr size_t kCodePointerTableReservationSize
Definition: v8-internal.h:764
constexpr TrustedPointerHandle kNullTrustedPointerHandle
Definition: v8-internal.h:733
constexpr ExternalBufferHandle kNullExternalBufferHandle
Definition: v8-internal.h:419
const int kWeakHeapObjectTag
Definition: v8-internal.h:54
constexpr ExternalPointerHandle kNullExternalPointerHandle
Definition: v8-internal.h:340
constexpr bool operator<(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1496
constexpr bool operator!=(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1504
constexpr uintptr_t kUintptrAllBitsSet
Definition: v8-internal.h:75
uint32_t JSDispatchHandle
Definition: v8-internal.h:808
const int kForwardingTag
Definition: v8-internal.h:62
const intptr_t kHeapObjectReferenceTagMask
Definition: v8-internal.h:57
constexpr bool SmiValuesAre31Bits()
Definition: v8-internal.h:189
constexpr size_t kMaxTrustedPointers
Definition: v8-internal.h:739
bool ShouldThrowOnError(internal::Isolate *isolate)
constexpr uint64_t kCppHeapPointerTagShift
Definition: v8-internal.h:363
constexpr auto operator-(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept -> decltype(x.base() - y.base())
Definition: v8-internal.h:1536
constexpr int KB
Definition: v8-internal.h:36
constexpr uint64_t kAllTagsForAndBasedTypeChecking[]
Definition: v8-internal.h:510
constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:799
constexpr bool operator>=(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1520
constexpr uint32_t kTrustedPointerHandleShift
Definition: v8-internal.h:730
constexpr uint32_t kCodePointerHandleShift
Definition: v8-internal.h:768
const int kHeapObjectTag
Definition: v8-internal.h:53
const int kSmiShiftSize
Definition: v8-internal.h:185
constexpr size_t kMaxCodePointers
Definition: v8-internal.h:787
SmiTagging< kApiTaggedSize > PlatformSmiTagging
Definition: v8-internal.h:180
const int kSmiValueSize
Definition: v8-internal.h:186
constexpr size_t kMaxJSDispatchEntries
Definition: v8-internal.h:821
constexpr bool SmiValuesAre32Bits()
Definition: v8-internal.h:190
constexpr IndirectPointerHandle kNullIndirectPointerHandle
Definition: v8-internal.h:704
uintptr_t Address
Definition: v8-internal.h:33
constexpr int kJSDispatchTableEntrySizeLog2
Definition: v8-internal.h:820
void PerformCastCheck(T *data)
Definition: v8-internal.h:1335
void PrintFunctionCallbackInfo(void *function_callback_info)
constexpr size_t kTrustedPointerTableReservationSize
Definition: v8-internal.h:726
uint32_t ExternalPointerHandle
Definition: v8-internal.h:328
const intptr_t kSmiTagMask
Definition: v8-internal.h:69
constexpr uint32_t kExternalBufferHandleShift
Definition: v8-internal.h:415
const int kHeapObjectTagSize
Definition: v8-internal.h:55
const int kSmiMaxValue
Definition: v8-internal.h:188
Address ExternalBuffer_t
Definition: v8-internal.h:401
constexpr bool Is64()
Definition: v8-internal.h:191
constexpr bool kAllCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:800
constexpr bool operator==(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1488
const int kSmiTag
Definition: v8-internal.h:67
constexpr CodePointerHandle kNullCodePointerHandle
Definition: v8-internal.h:771
Address CppHeapPointer_t
Definition: v8-internal.h:356
constexpr CppHeapPointerHandle kNullCppHeapPointerHandle
Definition: v8-internal.h:360
constexpr int kGarbageCollectionReasonMaxValue
Definition: v8-internal.h:1346
constexpr int kCodePointerTableEntrySize
Definition: v8-internal.h:785
constexpr int kExternalBufferTableEntrySize
Definition: v8-internal.h:422
ExternalPointerTag
Definition: v8-internal.h:621
@ kExternalPointerEvacuationEntryTag
Definition: v8-internal.h:634
@ kAccessorInfoGetterTag
Definition: v8-internal.h:639
@ kFirstSharedTag
Definition: v8-internal.h:639
@ kAccessorInfoSetterTag
Definition: v8-internal.h:639
@ kAnyForeignTag
Definition: v8-internal.h:628
@ kExternalPointerFreeEntryTag
Definition: v8-internal.h:632
@ kAnyExternalPointerTag
Definition: v8-internal.h:625
@ kLastSharedTag
Definition: v8-internal.h:639
@ kExternalPointerNullTag
Definition: v8-internal.h:623
@ kLastManagedResourceTag
Definition: v8-internal.h:639
@ kExternalPointerZappedEntryTag
Definition: v8-internal.h:637
@ kFirstManagedResourceTag
Definition: v8-internal.h:639
@ kFunctionTemplateInfoCallbackTag
Definition: v8-internal.h:639
constexpr uint32_t kCodePointerHandleMarker
Definition: v8-internal.h:780
constexpr JSDispatchHandle kNullJSDispatchHandle
Definition: v8-internal.h:810
const int kSmiMinValue
Definition: v8-internal.h:187
constexpr int kJSDispatchTableEntrySize
Definition: v8-internal.h:819
constexpr int MB
Definition: v8-internal.h:37
constexpr uint64_t kExternalPointerMarkBit
Definition: v8-internal.h:501
Address SandboxedPointer_t
Definition: v8-internal.h:211
const int kApiTaggedSize
Definition: v8-internal.h:170
constexpr bool PointerCompressionIsEnabled()
Definition: v8-internal.h:173
Definition: libplatform.h:15
Definition: v8-internal.h:1319
static void Perform(T *data)
static constexpr bool IsValidSmi(uint64_t value)
Definition: v8-internal.h:122
static constexpr bool IsValidSmi(int64_t value)
Definition: v8-internal.h:115
static constexpr bool IsValidSmi(T value)
Definition: v8-internal.h:95
static constexpr int SmiToInt(Address value)
Definition: v8-internal.h:87
static constexpr bool IsValidSmi(T value)
Definition: v8-internal.h:145
static constexpr int SmiToInt(Address value)
Definition: v8-internal.h:137
Definition: v8-internal.h:72
#define EXTERNAL_POINTER_TAG_ENUM(Name, Tag)
Definition: v8-internal.h:617
#define ALL_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:613
#define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag,...)
Definition: v8-internal.h:675
#define SHARED_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:538
#define MAKE_TAG(HasMarkBit, TypeTag)
Definition: v8-internal.h:618
#define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:548
#define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag,...)
Definition: v8-internal.h:673
#define V8_EXPORT
Definition: v8config.h:779
#define V8_INLINE
Definition: v8config.h:493
#define V8_LIKELY(condition)
Definition: v8config.h:644