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