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
545// External pointers using these tags are kept in a per-Isolate external
546// pointer table and can only be accessed when this Isolate is active.
547#define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V) \
548 V(kNativeContextMicrotaskQueueTag, TAG(10)) \
549 V(kEmbedderDataSlotPayloadTag, TAG(11)) \
550/* This tag essentially stands for a `void*` pointer in the V8 API, and */ \
551/* it is the Embedder's responsibility to ensure type safety (against */ \
552/* substitution) and lifetime validity of these objects. */ \
553 V(kExternalObjectValueTag, TAG(12)) \
554 V(kFunctionTemplateInfoCallbackTag, TAG(13)) \
555 V(kAccessorInfoGetterTag, TAG(14)) \
556 V(kAccessorInfoSetterTag, TAG(15)) \
557 V(kWasmInternalFunctionCallTargetTag, TAG(16)) \
558 V(kWasmTypeInfoNativeTypeTag, TAG(17)) \
559 V(kWasmExportedFunctionDataSignatureTag, TAG(18)) \
560 V(kWasmContinuationJmpbufTag, TAG(19)) \
561 V(kWasmIndirectFunctionTargetTag, TAG(20)) \
562 /* Foreigns */ \
563 V(kGenericForeignTag, TAG(30)) \
564 /* Managed */ \
565 V(kFirstManagedResourceTag, TAG(40)) \
566 V(kGenericManagedTag, TAG(40)) \
567 V(kWasmWasmStreamingTag, TAG(41)) \
568 V(kWasmFuncDataTag, TAG(42)) \
569 V(kWasmManagedDataTag, TAG(43)) \
570 V(kWasmNativeModuleTag, TAG(44)) \
571 V(kWasmStackMemoryTag, TAG(45)) \
572 V(kIcuBreakIteratorTag, TAG(46)) \
573 V(kIcuUnicodeStringTag, TAG(47)) \
574 V(kIcuListFormatterTag, TAG(48)) \
575 V(kIcuLocaleTag, TAG(49)) \
576 V(kIcuSimpleDateFormatTag, TAG(50)) \
577 V(kIcuDateIntervalFormatTag, TAG(51)) \
578 V(kIcuRelativeDateTimeFormatterTag, TAG(52)) \
579 V(kIcuLocalizedNumberFormatterTag, TAG(53)) \
580 V(kIcuPluralRulesTag, TAG(54)) \
581 V(kIcuCollatorTag, TAG(55)) \
582 V(kDisplayNamesInternalTag, TAG(56)) \
583 /* External resources whose lifetime is tied to */ \
584 /* their entry in the external pointer table but */ \
585 /* which are not referenced via a Managed */ \
586 V(kArrayBufferExtensionTag, TAG(57)) \
587 V(kLastManagedResourceTag, TAG(57)) \
588
589// All external pointer tags.
590#define ALL_EXTERNAL_POINTER_TAGS(V) \
591 SHARED_EXTERNAL_POINTER_TAGS(V) \
592 PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
593
594#define EXTERNAL_POINTER_TAG_ENUM(Name, Tag) Name = Tag,
595#define MAKE_TAG(HasMarkBit, TypeTag) \
596 ((static_cast<uint64_t>(TypeTag) << kExternalPointerTagShift) | \
597 (HasMarkBit ? kExternalPointerMarkBit : 0))
598enum ExternalPointerTag : uint64_t {
599 // Empty tag value. Mostly used as placeholder.
601 // External pointer tag that will match any external pointer. Use with care!
603 // External pointer tag that will match any external pointer in a Foreign.
604 // Use with care! If desired, this could be made more fine-granular.
606 // The free entry tag has all type bits set so every type check with a
607 // different type fails. It also doesn't have the mark bit set as free
608 // entries are (by definition) not alive.
610 // Evacuation entries are used during external pointer table compaction.
612 // Tag for zapped/invalidated entries. Those are considered to no longer be
613 // in use and so have the marking bit cleared.
615
617};
618
619#undef MAKE_TAG
620#undef TAG
621#undef EXTERNAL_POINTER_TAG_ENUM
622
623// clang-format on
624
625// True if the external pointer must be accessed from the shared isolate's
626// external pointer table.
627V8_INLINE static constexpr bool IsSharedExternalPointerType(
628 ExternalPointerTag tag) {
629 return tag >= kFirstSharedTag && tag <= kLastSharedTag;
630}
631
632// True if the external pointer may live in a read-only object, in which case
633// the table entry will be in the shared read-only segment of the external
634// pointer table.
635V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
636 ExternalPointerTag tag) {
637 return tag == kAccessorInfoGetterTag || tag == kAccessorInfoSetterTag ||
639}
640
641// True if the external pointer references an external object whose lifetime is
642// tied to the entry in the external pointer table.
643// In this case, the entry in the ExternalPointerTable always points to an
644// object derived from ExternalPointerTable::ManagedResource.
645V8_INLINE static constexpr bool IsManagedExternalPointerType(
646 ExternalPointerTag tag) {
648}
649
650// Sanity checks.
651#define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
652 static_assert(IsSharedExternalPointerType(Tag));
653#define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
654 static_assert(!IsSharedExternalPointerType(Tag));
655
658
659#undef CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS
660#undef CHECK_SHARED_EXTERNAL_POINTER_TAGS
661
662#undef SHARED_EXTERNAL_POINTER_TAGS
663#undef EXTERNAL_POINTER_TAGS
664
665//
666// Indirect Pointers.
667//
668// When the sandbox is enabled, indirect pointers are used to reference
669// HeapObjects that live outside of the sandbox (but are still managed by V8's
670// garbage collector). When object A references an object B through an indirect
671// pointer, object A will contain a IndirectPointerHandle, i.e. a shifted
672// 32-bit index, which identifies an entry in a pointer table (either the
673// trusted pointer table for TrustedObjects, or the code pointer table if it is
674// a Code object). This table entry then contains the actual pointer to object
675// B. Further, object B owns this pointer table entry, and it is responsible
676// for updating the "self-pointer" in the entry when it is relocated in memory.
677// This way, in contrast to "normal" pointers, indirect pointers never need to
678// be tracked by the GC (i.e. there is no remembered set for them).
679// These pointers do not exist when the sandbox is disabled.
680
681// An IndirectPointerHandle represents a 32-bit index into a pointer table.
682using IndirectPointerHandle = uint32_t;
683
684// A null handle always references an entry that contains nullptr.
686
687// When the sandbox is enabled, indirect pointers are used to implement:
688// - TrustedPointers: an indirect pointer using the trusted pointer table (TPT)
689// and referencing a TrustedObject in one of the trusted heap spaces.
690// - CodePointers, an indirect pointer using the code pointer table (CPT) and
691// referencing a Code object together with its instruction stream.
692
693//
694// Trusted Pointers.
695//
696// A pointer to a TrustedObject.
697// When the sandbox is enabled, these are indirect pointers using the trusted
698// pointer table (TPT). They are used to reference trusted objects (located in
699// one of V8's trusted heap spaces, outside of the sandbox) from inside the
700// sandbox in a memory-safe way. When the sandbox is disabled, these are
701// regular tagged pointers.
704// The size of the virtual memory reservation for the trusted pointer table.
705// As with the external pointer table, a maximum table size in combination with
706// shifted indices allows omitting bounds checks.
708
709// The trusted pointer handles are stores shifted to the left by this amount
710// to guarantee that they are smaller than the maximum table size.
711constexpr uint32_t kTrustedPointerHandleShift = 9;
712
713// A null handle always references an entry that contains nullptr.
717// The maximum number of entries in an trusted pointer table.
718constexpr int kTrustedPointerTableEntrySize = 8;
719constexpr int kTrustedPointerTableEntrySizeLog2 = 3;
720constexpr size_t kMaxTrustedPointers =
722static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
723 "kTrustedPointerTableReservationSize and "
724 "kTrustedPointerHandleShift don't match");
725
726//
727// Code Pointers.
728//
729// A pointer to a Code object.
730// Essentially a specialized version of a trusted pointer that (when the
731// sandbox is enabled) uses the code pointer table (CPT) instead of the TPT.
732// Each entry in the CPT contains both a pointer to a Code object as well as a
733// pointer to the Code's entrypoint. This allows calling/jumping into Code with
734// one fewer memory access (compared to the case where the entrypoint pointer
735// first needs to be loaded from the Code object). As such, a CodePointerHandle
736// can be used both to obtain the referenced Code object and to directly load
737// its entrypoint.
738//
739// When the sandbox is disabled, these are regular tagged pointers.
742// The size of the virtual memory reservation for the code pointer table.
743// As with the other tables, a maximum table size in combination with shifted
744// indices allows omitting bounds checks.
745constexpr size_t kCodePointerTableReservationSize = 128 * MB;
746
747// Code pointer handles are shifted by a different amount than indirect pointer
748// handles as the tables have a different maximum size.
749constexpr uint32_t kCodePointerHandleShift = 9;
750
751// A null handle always references an entry that contains nullptr.
753
754// It can sometimes be necessary to distinguish a code pointer handle from a
755// trusted pointer handle. A typical example would be a union trusted pointer
756// field that can refer to both Code objects and other trusted objects. To
757// support these use-cases, we use a simple marking scheme where some of the
758// low bits of a code pointer handle are set, while they will be unset on a
759// trusted pointer handle. This way, the correct table to resolve the handle
760// can be determined even in the absence of a type tag.
761constexpr uint32_t kCodePointerHandleMarker = 0x1;
762static_assert(kCodePointerHandleShift > 0);
763static_assert(kTrustedPointerHandleShift > 0);
765// The maximum number of entries in a code pointer table.
766constexpr int kCodePointerTableEntrySize = 16;
767constexpr int kCodePointerTableEntrySizeLog2 = 4;
768constexpr size_t kMaxCodePointers =
770static_assert(
772 "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
773
777// Constants that can be used to mark places that should be modified once
778// certain types of objects are moved out of the sandbox and into trusted space.
780constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace = false;
784
785// {obj} must be the raw tagged pointer representation of a HeapObject
786// that's guaranteed to never be in ReadOnlySpace.
789// Returns if we need to throw when an error occurs. This infers the language
790// mode based on the current context and the closure. This returns true if the
791// language mode is strict.
792V8_EXPORT bool ShouldThrowOnError(internal::Isolate* isolate);
798class Internals {
799#ifdef V8_MAP_PACKING
800 V8_INLINE static constexpr Address UnpackMapWord(Address mapword) {
801 // TODO(wenyuzhao): Clear header metadata.
802 return mapword ^ kMapWordXorMask;
803 }
804#endif
806 public:
807 // These values match non-compiler-dependent values defined within
808 // the implementation of v8.
809 static const int kHeapObjectMapOffset = 0;
811 static const int kStringResourceOffset =
813
814 static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
815 static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
816#ifdef V8_COMPRESS_POINTERS
819#else // !V8_COMPRESS_POINTERS
822#endif // !V8_COMPRESS_POINTERS
823 static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
824 static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
826#ifdef V8_ENABLE_SANDBOX
828#else
830#endif
832 static const int kStringRepresentationAndEncodingMask = 0x0f;
833 static const int kStringEncodingMask = 0x8;
834 static const int kExternalTwoByteRepresentationTag = 0x02;
835 static const int kExternalOneByteRepresentationTag = 0x0a;
837 static const uint32_t kNumIsolateDataSlots = 4;
839 static const int kNumberOfBooleanFlags = 6;
840 static const int kErrorMessageParamSize = 1;
841 static const int kTablesAlignmentPaddingSize = 1;
843 static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
845 static const int kThreadLocalTopSize = 30 * kApiSystemPointerSize;
846 static const int kHandleScopeDataSize =
849 // ExternalPointerTable and TrustedPointerTable layout guarantees.
852 static const int kExternalBufferTableSize = 2 * kApiSystemPointerSize;
855
856 // IsolateData layout guarantees.
857 static const int kIsolateCageBaseOffset = 0;
858 static const int kIsolateStackGuardOffset =
860 static const int kVariousBooleanFlagsOffset =
862 static const int kErrorMessageParamOffset =
867 static const int kBuiltinTier0TableOffset =
869 static const int kNewAllocationInfoOffset =
871 static const int kOldAllocationInfoOffset =
873
874 static const int kFastCCallAlignmentPaddingSize =
876 static const int kIsolateFastCCallCallerFpOffset =
887 static const int kIsolateHandleScopeDataOffset =
889 static const int kIsolateEmbedderDataOffset =
891#ifdef V8_COMPRESS_POINTERS
892 static const int kIsolateExternalPointerTableOffset =
894 static const int kIsolateSharedExternalPointerTableAddressOffset =
895 kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
896 static const int kIsolateCppHeapPointerTableOffset =
897 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
898#ifdef V8_ENABLE_SANDBOX
899 static const int kIsolateTrustedCageBaseOffset =
900 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
901 static const int kIsolateTrustedPointerTableOffset =
902 kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
903 static const int kIsolateExternalBufferTableOffset =
904 kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
905 static const int kIsolateSharedExternalBufferTableAddressOffset =
906 kIsolateExternalBufferTableOffset + kExternalBufferTableSize;
908 kIsolateSharedExternalBufferTableAddressOffset + kApiSystemPointerSize;
909#else
911 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
912#endif // V8_ENABLE_SANDBOX
913#else
916#endif // V8_COMPRESS_POINTERS
919 static const int kIsolateRootsOffset =
921
922#if V8_STATIC_ROOTS_BOOL
923
924// These constants are copied from static-roots.h and guarded by static asserts.
925#define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
926 V(UndefinedValue, 0x69) \
927 V(NullValue, 0x85) \
928 V(TrueValue, 0xc9) \
929 V(FalseValue, 0xad) \
930 V(EmptyString, 0xa1) \
931 V(TheHoleValue, 0x741)
932
933 using Tagged_t = uint32_t;
934 struct StaticReadOnlyRoot {
935#define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
936 EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
937#undef DEF_ROOT
938
939 static constexpr Tagged_t kFirstStringMap = 0xe5;
940 static constexpr Tagged_t kLastStringMap = 0x47d;
941
942#define PLUSONE(...) +1
943 static constexpr size_t kNumberOfExportedStaticRoots =
944 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
945#undef PLUSONE
946 };
948#endif // V8_STATIC_ROOTS_BOOL
950 static const int kUndefinedValueRootIndex = 4;
951 static const int kTheHoleValueRootIndex = 5;
952 static const int kNullValueRootIndex = 6;
953 static const int kTrueValueRootIndex = 7;
954 static const int kFalseValueRootIndex = 8;
955 static const int kEmptyStringRootIndex = 9;
957 static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
958 static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
959 static const int kNodeStateMask = 0x3;
960 static const int kNodeStateIsWeakValue = 2;
962 static const int kFirstNonstringType = 0x80;
963 static const int kOddballType = 0x83;
964 static const int kForeignType = 0xcc;
965 static const int kJSSpecialApiObjectType = 0x410;
966 static const int kJSObjectType = 0x421;
967 static const int kFirstJSApiObjectType = 0x422;
968 static const int kLastJSApiObjectType = 0x80A;
969 // Defines a range [kFirstEmbedderJSApiObjectType, kJSApiObjectTypesCount]
970 // of JSApiObject instance type values that an embedder can use.
971 static const int kFirstEmbedderJSApiObjectType = 0;
974
975 static const int kUndefinedOddballKind = 4;
976 static const int kNullOddballKind = 3;
978 // Constants used by PropertyCallbackInfo to check if we should throw when an
979 // error occurs.
980 static const int kThrowOnError = 0;
981 static const int kDontThrow = 1;
982 static const int kInferShouldThrowMode = 2;
983
984 // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
985 // incremental GC once the external memory reaches this limit.
986 static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
987
988#ifdef V8_MAP_PACKING
989 static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
990 // The lowest two bits of mapwords are always `0b10`
991 static const uintptr_t kMapWordSignature = 0b10;
992 // XORing a (non-compressed) map with this mask ensures that the two
993 // low-order bits are 0b10. The 0 at the end makes this look like a Smi,
994 // although real Smis have all lower 32 bits unset. We only rely on these
995 // values passing as Smis in very few places.
996 static const int kMapWordXorMask = 0b11;
997#endif
998
999 V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
1000 V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
1001#ifdef V8_ENABLE_CHECKS
1003#endif
1004 }
1005
1006 V8_INLINE static constexpr bool HasHeapObjectTag(Address value) {
1007 return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
1008 }
1009
1010 V8_INLINE static constexpr int SmiValue(Address value) {
1011 return PlatformSmiTagging::SmiToInt(value);
1012 }
1013
1014 V8_INLINE static constexpr Address AddressToSmi(Address value) {
1015 return (value << (kSmiTagSize + PlatformSmiTagging::kSmiShiftSize)) |
1016 kSmiTag;
1017 }
1018
1019 V8_INLINE static constexpr Address IntToSmi(int value) {
1020 return AddressToSmi(static_cast<Address>(value));
1022
1023 template <typename T,
1024 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1025 V8_INLINE static constexpr Address IntegralToSmi(T value) {
1026 return AddressToSmi(static_cast<Address>(value));
1028
1029 template <typename T,
1030 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1031 V8_INLINE static constexpr bool IsValidSmi(T value) {
1032 return PlatformSmiTagging::IsValidSmi(value);
1034
1035 template <typename T,
1036 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1037 static constexpr std::optional<Address> TryIntegralToSmi(T value) {
1038 if (V8_LIKELY(PlatformSmiTagging::IsValidSmi(value))) {
1039 return {AddressToSmi(static_cast<Address>(value))};
1040 }
1041 return {};
1042 }
1043
1044#if V8_STATIC_ROOTS_BOOL
1045 V8_INLINE static bool is_identical(Address obj, Tagged_t constant) {
1046 return static_cast<Tagged_t>(obj) == constant;
1047 }
1048
1049 V8_INLINE static bool CheckInstanceMapRange(Address obj, Tagged_t first_map,
1050 Tagged_t last_map) {
1051 auto map = ReadRawField<Tagged_t>(obj, kHeapObjectMapOffset);
1052#ifdef V8_MAP_PACKING
1053 map = UnpackMapWord(map);
1054#endif
1055 return map >= first_map && map <= last_map;
1056 }
1057#endif
1058
1059 V8_INLINE static int GetInstanceType(Address obj) {
1061#ifdef V8_MAP_PACKING
1062 map = UnpackMapWord(map);
1063#endif
1064 return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
1065 }
1066
1067 V8_INLINE static Address LoadMap(Address obj) {
1068 if (!HasHeapObjectTag(obj)) return kNullAddress;
1070#ifdef V8_MAP_PACKING
1071 map = UnpackMapWord(map);
1072#endif
1073 return map;
1074 }
1075
1078 }
1079
1080 V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
1081 int representation = (instance_type & kStringRepresentationAndEncodingMask);
1082 return representation == kExternalTwoByteRepresentationTag;
1083 }
1084
1085 V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
1086 static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
1087 static_assert(kJSObjectType < kLastJSApiObjectType);
1089 // Check for IsJSObject() || IsJSSpecialApiObject() || IsJSApiObject()
1090 return instance_type == kJSSpecialApiObjectType ||
1091 // inlined version of base::IsInRange
1092 (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
1093 static_cast<unsigned>(kJSObjectType)) <=
1094 static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
1095 }
1096
1097 V8_INLINE static uint8_t GetNodeFlag(Address* obj, int shift) {
1098 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1099 return *addr & static_cast<uint8_t>(1U << shift);
1100 }
1101
1102 V8_INLINE static void UpdateNodeFlag(Address* obj, bool value, int shift) {
1103 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1104 uint8_t mask = static_cast<uint8_t>(1U << shift);
1105 *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
1106 }
1107
1108 V8_INLINE static uint8_t GetNodeState(Address* obj) {
1109 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1110 return *addr & kNodeStateMask;
1111 }
1112
1113 V8_INLINE static void UpdateNodeState(Address* obj, uint8_t value) {
1114 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1115 *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
1116 }
1117
1118 V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
1119 void* data) {
1120 Address addr = reinterpret_cast<Address>(isolate) +
1122 *reinterpret_cast<void**>(addr) = data;
1123 }
1124
1125 V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
1126 uint32_t slot) {
1127 Address addr = reinterpret_cast<Address>(isolate) +
1129 return *reinterpret_cast<void* const*>(addr);
1130 }
1131
1133 Address addr =
1134 reinterpret_cast<Address>(isolate) + kIsolateLongTaskStatsCounterOffset;
1135 ++(*reinterpret_cast<size_t*>(addr));
1136 }
1137
1138 V8_INLINE static Address* GetRootSlot(v8::Isolate* isolate, int index) {
1139 Address addr = reinterpret_cast<Address>(isolate) + kIsolateRootsOffset +
1141 return reinterpret_cast<Address*>(addr);
1142 }
1143
1144 V8_INLINE static Address GetRoot(v8::Isolate* isolate, int index) {
1145#if V8_STATIC_ROOTS_BOOL
1146 Address base = *reinterpret_cast<Address*>(
1147 reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
1148 switch (index) {
1149#define DECOMPRESS_ROOT(name, ...) \
1150 case k##name##RootIndex: \
1151 return base + StaticReadOnlyRoot::k##name;
1152 EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
1153#undef DECOMPRESS_ROOT
1154#undef EXPORTED_STATIC_ROOTS_PTR_LIST
1155 default:
1156 break;
1157 }
1158#endif // V8_STATIC_ROOTS_BOOL
1159 return *GetRootSlot(isolate, index);
1160 }
1161
1162#ifdef V8_ENABLE_SANDBOX
1163 V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) {
1164 Address addr = reinterpret_cast<Address>(isolate) +
1165 kIsolateExternalPointerTableOffset +
1167 return *reinterpret_cast<Address**>(addr);
1168 }
1169
1170 V8_INLINE static Address* GetSharedExternalPointerTableBase(
1171 v8::Isolate* isolate) {
1172 Address addr = reinterpret_cast<Address>(isolate) +
1173 kIsolateSharedExternalPointerTableAddressOffset;
1174 addr = *reinterpret_cast<Address*>(addr);
1176 return *reinterpret_cast<Address**>(addr);
1178#endif
1179
1180 template <typename T>
1181 V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
1182 Address addr = heap_object_ptr + offset - kHeapObjectTag;
1183#ifdef V8_COMPRESS_POINTERS
1184 if (sizeof(T) > kApiTaggedSize) {
1185 // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
1186 // fields (external pointers, doubles and BigInt data) are only
1187 // kTaggedSize aligned so we have to use unaligned pointer friendly way of
1188 // accessing them in order to avoid undefined behavior in C++ code.
1189 T r;
1190 memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
1191 return r;
1192 }
1193#endif
1194 return *reinterpret_cast<const T*>(addr);
1195 }
1196
1197 V8_INLINE static Address ReadTaggedPointerField(Address heap_object_ptr,
1198 int offset) {
1199#ifdef V8_COMPRESS_POINTERS
1200 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1201 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1202 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1203#else
1204 return ReadRawField<Address>(heap_object_ptr, offset);
1205#endif
1206 }
1207
1208 V8_INLINE static Address ReadTaggedSignedField(Address heap_object_ptr,
1209 int offset) {
1210#ifdef V8_COMPRESS_POINTERS
1211 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1212 return static_cast<Address>(static_cast<uintptr_t>(value));
1213#else
1214 return ReadRawField<Address>(heap_object_ptr, offset);
1215#endif
1216 }
1217
1219#ifdef V8_ENABLE_SANDBOX
1220 return reinterpret_cast<v8::Isolate*>(
1222#else
1223 // Not used in non-sandbox mode.
1224 return nullptr;
1225#endif
1226 }
1227
1228 template <ExternalPointerTag tag>
1230 Address heap_object_ptr,
1231 int offset) {
1232#ifdef V8_ENABLE_SANDBOX
1233 static_assert(tag != kExternalPointerNullTag);
1234 // See src/sandbox/external-pointer-table-inl.h. Logic duplicated here so
1235 // it can be inlined and doesn't require an additional call.
1236 Address* table = IsSharedExternalPointerType(tag)
1237 ? GetSharedExternalPointerTableBase(isolate)
1238 : GetExternalPointerTableBase(isolate);
1240 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1241 uint32_t index = handle >> kExternalPointerIndexShift;
1242 std::atomic<Address>* ptr =
1243 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1244 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1245 return entry & ~tag;
1246#else
1247 return ReadRawField<Address>(heap_object_ptr, offset);
1248#endif // V8_ENABLE_SANDBOX
1249 }
1250
1251#ifdef V8_COMPRESS_POINTERS
1252 V8_INLINE static Address GetPtrComprCageBaseFromOnHeapAddress(Address addr) {
1253 return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
1254 }
1255
1256 V8_INLINE static uint32_t CompressTagged(Address value) {
1257 return static_cast<uint32_t>(value);
1258 }
1259
1260 V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
1261 uint32_t value) {
1262 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1263 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1264 }
1265
1266#endif // V8_COMPRESS_POINTERS
1267};
1269// Only perform cast check for types derived from v8::Data since
1270// other types do not implement the Cast method.
1271template <bool PerformCheck>
1272struct CastCheck {
1273 template <class T>
1274 static void Perform(T* data);
1276
1277template <>
1278template <class T>
1279void CastCheck<true>::Perform(T* data) {
1280 T::Cast(data);
1282
1283template <>
1284template <class T>
1285void CastCheck<false>::Perform(T* data) {}
1286
1287template <class T>
1288V8_INLINE void PerformCastCheck(T* data) {
1289 CastCheck<std::is_base_of<Data, T>::value &&
1290 !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
1292
1293// A base class for backing stores, which is needed due to vagaries of
1294// how static casts work with std::shared_ptr.
1296
1297// The maximum value in enum GarbageCollectionReason, defined in heap.h.
1298// This is needed for histograms sampling garbage collection reasons.
1300
1301// Base class for the address block allocator compatible with standard
1302// containers, which registers its allocated range as strong roots.
1304 public:
1305 Heap* heap() const { return heap_; }
1307 bool operator==(const StrongRootAllocatorBase& other) const {
1308 return heap_ == other.heap_;
1309 }
1310 bool operator!=(const StrongRootAllocatorBase& other) const {
1311 return heap_ != other.heap_;
1313
1314 protected:
1315 explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
1317
1318 // Allocate/deallocate a range of n elements of type internal::Address.
1319 Address* allocate_impl(size_t n);
1320 void deallocate_impl(Address* p, size_t n) noexcept;
1321
1322 private:
1323 Heap* heap_;
1324};
1325
1326// The general version of this template behaves just as std::allocator, with
1327// the exception that the constructor takes the isolate as parameter. Only
1328// specialized versions, e.g., internal::StrongRootAllocator<internal::Address>
1329// and internal::StrongRootAllocator<v8::Local<T>> register the allocated range
1330// as strong roots.
1331template <typename T>
1332class StrongRootAllocator : private std::allocator<T> {
1333 public:
1334 using value_type = T;
1335
1336 explicit StrongRootAllocator(Heap* heap) {}
1337 explicit StrongRootAllocator(Isolate* isolate) {}
1338 explicit StrongRootAllocator(v8::Isolate* isolate) {}
1339 template <typename U>
1340 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept {}
1341
1342 using std::allocator<T>::allocate;
1343 using std::allocator<T>::deallocate;
1344};
1345
1346// A class of iterators that wrap some different iterator type.
1347// If specified, ElementType is the type of element accessed by the wrapper
1348// iterator; in this case, the actual reference and pointer types of Iterator
1349// must be convertible to ElementType& and ElementType*, respectively.
1350template <typename Iterator, typename ElementType = void>
1351class WrappedIterator {
1352 public:
1353 static_assert(
1354 !std::is_void_v<ElementType> ||
1355 (std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
1356 ElementType*> &&
1357 std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
1358 ElementType&>));
1359
1361 typename std::iterator_traits<Iterator>::iterator_category;
1362 using difference_type =
1363 typename std::iterator_traits<Iterator>::difference_type;
1365 std::conditional_t<std::is_void_v<ElementType>,
1366 typename std::iterator_traits<Iterator>::value_type,
1367 ElementType>;
1368 using pointer =
1369 std::conditional_t<std::is_void_v<ElementType>,
1370 typename std::iterator_traits<Iterator>::pointer,
1371 ElementType*>;
1372 using reference =
1373 std::conditional_t<std::is_void_v<ElementType>,
1374 typename std::iterator_traits<Iterator>::reference,
1375 ElementType&>;
1376
1377 constexpr WrappedIterator() noexcept : it_() {}
1378 constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
1380 template <typename OtherIterator, typename OtherElementType,
1381 std::enable_if_t<std::is_convertible_v<OtherIterator, Iterator>,
1382 bool> = true>
1385 : it_(it.base()) {}
1387 constexpr reference operator*() const noexcept { return *it_; }
1388 constexpr pointer operator->() const noexcept { return it_.operator->(); }
1389
1390 constexpr WrappedIterator& operator++() noexcept {
1391 ++it_;
1392 return *this;
1393 }
1394 constexpr WrappedIterator operator++(int) noexcept {
1395 WrappedIterator result(*this);
1396 ++(*this);
1397 return result;
1398 }
1399
1400 constexpr WrappedIterator& operator--() noexcept {
1401 --it_;
1402 return *this;
1403 }
1404 constexpr WrappedIterator operator--(int) noexcept {
1405 WrappedIterator result(*this);
1406 --(*this);
1407 return result;
1408 }
1409 constexpr WrappedIterator operator+(difference_type n) const noexcept {
1410 WrappedIterator result(*this);
1411 result += n;
1412 return result;
1413 }
1415 it_ += n;
1416 return *this;
1418 constexpr WrappedIterator operator-(difference_type n) const noexcept {
1419 return *this + (-n);
1420 }
1422 *this += -n;
1423 return *this;
1424 }
1425 constexpr reference operator[](difference_type n) const noexcept {
1426 return it_[n];
1427 }
1428
1429 constexpr Iterator base() const noexcept { return it_; }
1430
1431 private:
1432 template <typename OtherIterator, typename OtherElementType>
1433 friend class WrappedIterator;
1434
1435 private:
1436 Iterator it_;
1438
1439template <typename Iterator, typename ElementType, typename OtherIterator,
1440 typename OtherElementType>
1441constexpr bool operator==(
1442 const WrappedIterator<Iterator, ElementType>& x,
1443 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1444 return x.base() == y.base();
1446
1447template <typename Iterator, typename ElementType, typename OtherIterator,
1448 typename OtherElementType>
1449constexpr bool operator<(
1450 const WrappedIterator<Iterator, ElementType>& x,
1451 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1452 return x.base() < y.base();
1454
1455template <typename Iterator, typename ElementType, typename OtherIterator,
1456 typename OtherElementType>
1457constexpr bool operator!=(
1458 const WrappedIterator<Iterator, ElementType>& x,
1459 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1460 return !(x == y);
1462
1463template <typename Iterator, typename ElementType, typename OtherIterator,
1464 typename OtherElementType>
1465constexpr bool operator>(
1466 const WrappedIterator<Iterator, ElementType>& x,
1467 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1468 return y < x;
1470
1471template <typename Iterator, typename ElementType, typename OtherIterator,
1472 typename OtherElementType>
1473constexpr bool operator>=(
1474 const WrappedIterator<Iterator, ElementType>& x,
1475 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1476 return !(x < y);
1478
1479template <typename Iterator, typename ElementType, typename OtherIterator,
1480 typename OtherElementType>
1481constexpr bool operator<=(
1482 const WrappedIterator<Iterator, ElementType>& x,
1483 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1484 return !(y < x);
1486
1487template <typename Iterator, typename ElementType, typename OtherIterator,
1488 typename OtherElementType>
1489constexpr auto operator-(
1490 const WrappedIterator<Iterator, ElementType>& x,
1491 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept
1492 -> decltype(x.base() - y.base()) {
1493 return x.base() - y.base();
1494}
1495
1496template <typename Iterator, typename ElementType>
1497constexpr WrappedIterator<Iterator> operator+(
1499 const WrappedIterator<Iterator, ElementType>& x) noexcept {
1500 x += n;
1501 return x;
1502}
1504// Helper functions about values contained in handles.
1505// A value is either an indirect pointer or a direct pointer, depending on
1506// whether direct local support is enabled.
1507class ValueHelper final {
1508 public:
1509#ifdef V8_ENABLE_DIRECT_LOCAL
1510 static constexpr Address kTaggedNullAddress = 1;
1511 static constexpr Address kEmpty = kTaggedNullAddress;
1512#else
1513 static constexpr Address kEmpty = kNullAddress;
1514#endif // V8_ENABLE_DIRECT_LOCAL
1515
1516 template <typename T>
1517 V8_INLINE static bool IsEmpty(T* value) {
1518 return reinterpret_cast<Address>(value) == kEmpty;
1519 }
1520
1521 // Returns a handle's "value" for all kinds of abstract handles. For Local,
1522 // it is equivalent to `*handle`. The variadic parameters support handle
1523 // types with extra type parameters, like `Persistent<T, M>`.
1524 template <template <typename T, typename... Ms> typename H, typename T,
1525 typename... Ms>
1526 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
1527 return handle.template value<T>();
1528 }
1529
1530#ifdef V8_ENABLE_DIRECT_LOCAL
1531
1532 template <typename T>
1533 V8_INLINE static Address ValueAsAddress(const T* value) {
1534 return reinterpret_cast<Address>(value);
1535 }
1536
1537 template <typename T, bool check_null = true, typename S>
1538 V8_INLINE static T* SlotAsValue(S* slot) {
1539 if (check_null && slot == nullptr) {
1540 return reinterpret_cast<T*>(kTaggedNullAddress);
1541 }
1542 return *reinterpret_cast<T**>(slot);
1543 }
1545#else // !V8_ENABLE_DIRECT_LOCAL
1546
1547 template <typename T>
1548 V8_INLINE static Address ValueAsAddress(const T* value) {
1549 return *reinterpret_cast<const Address*>(value);
1550 }
1551
1552 template <typename T, bool check_null = true, typename S>
1553 V8_INLINE static T* SlotAsValue(S* slot) {
1554 return reinterpret_cast<T*>(slot);
1555 }
1556
1557#endif // V8_ENABLE_DIRECT_LOCAL
1558};
1563class HandleHelper final {
1564 public:
1575 template <typename T1, typename T2>
1576 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
1577 if (lhs.IsEmpty()) return rhs.IsEmpty();
1578 if (rhs.IsEmpty()) return false;
1579 return lhs.ptr() == rhs.ptr();
1580 }
1581};
1582
1583V8_EXPORT void VerifyHandleIsNonEmpty(bool is_empty);
1584
1585} // namespace internal
1586} // namespace v8
1587
1588#endif // INCLUDE_V8_INTERNAL_H_
Definition: v8-isolate.h:210
Definition: v8-internal.h:1291
Definition: v8-internal.h:1559
static bool EqualHandles(const T1 &lhs, const T2 &rhs)
Definition: v8-internal.h:1572
Definition: v8-internal.h:794
static Address LoadMap(Address obj)
Definition: v8-internal.h:1063
static bool IsExternalTwoByteString(int instance_type)
Definition: v8-internal.h:1076
static const int kIsolateCageBaseOffset
Definition: v8-internal.h:853
static const int kEmbedderDataArrayHeaderSize
Definition: v8-internal.h:820
static const int kHeapObjectMapOffset
Definition: v8-internal.h:805
static const int kEmbedderDataSlotSize
Definition: v8-internal.h:821
static const int kIsolateApiCallbackThunkArgumentOffset
Definition: v8-internal.h:910
static Address ReadExternalPointerField(v8::Isolate *isolate, Address heap_object_ptr, int offset)
Definition: v8-internal.h:1225
static const int kJSAPIObjectWithEmbedderSlotsHeaderSize
Definition: v8-internal.h:816
static constexpr bool HasHeapObjectTag(Address value)
Definition: v8-internal.h:1002
static const int kOddballType
Definition: v8-internal.h:959
static const int kInferShouldThrowMode
Definition: v8-internal.h:978
static const int kNewAllocationInfoOffset
Definition: v8-internal.h:865
static Address GetRoot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1140
static const int kStringEncodingMask
Definition: v8-internal.h:829
static const int kIsolateFastCCallCallerPcOffset
Definition: v8-internal.h:875
static uint8_t GetNodeFlag(Address *obj, int shift)
Definition: v8-internal.h:1093
static const int kIsolateThreadLocalTopOffset
Definition: v8-internal.h:881
static const uint32_t kNumIsolateDataSlots
Definition: v8-internal.h:833
static const int kForeignType
Definition: v8-internal.h:960
static const int kFirstEmbedderJSApiObjectType
Definition: v8-internal.h:967
static const int kNumberOfBooleanFlags
Definition: v8-internal.h:835
static uint8_t GetNodeState(Address *obj)
Definition: v8-internal.h:1104
static const int kThreadLocalTopSize
Definition: v8-internal.h:841
static const int kIsolateRootsOffset
Definition: v8-internal.h:915
static const int kExternalPointerTableSize
Definition: v8-internal.h:847
static const int kUndefinedOddballKind
Definition: v8-internal.h:971
static const int kMapInstanceTypeOffset
Definition: v8-internal.h:806
static constexpr Address AddressToSmi(Address value)
Definition: v8-internal.h:1010
static const int kIsolateStackGuardOffset
Definition: v8-internal.h:854
static const int kLinearAllocationAreaSize
Definition: v8-internal.h:840
static const int kFastCCallAlignmentPaddingSize
Definition: v8-internal.h:870
static const int kIsolateFastCCallCallerFpOffset
Definition: v8-internal.h:872
static const int kErrorMessageParamSize
Definition: v8-internal.h:836
static void CheckInitialized(v8::Isolate *isolate)
Definition: v8-internal.h:996
static void UpdateNodeState(Address *obj, uint8_t value)
Definition: v8-internal.h:1109
static constexpr Address IntegralToSmi(T value)
Definition: v8-internal.h:1021
static constexpr bool IsValidSmi(T value)
Definition: v8-internal.h:1027
static const int kJSObjectType
Definition: v8-internal.h:962
static const int kBuiltinTier0TableOffset
Definition: v8-internal.h:863
static const int kIsolateLongTaskStatsCounterOffset
Definition: v8-internal.h:879
static const int kNativeContextEmbedderDataOffset
Definition: v8-internal.h:827
static const int kLastJSApiObjectType
Definition: v8-internal.h:964
static constexpr bool CanHaveInternalField(int instance_type)
Definition: v8-internal.h:1081
static const int kIsolateHandleScopeDataOffset
Definition: v8-internal.h:883
static const int kFirstNonstringType
Definition: v8-internal.h:958
static const int kEmptyStringRootIndex
Definition: v8-internal.h:951
static const int kBuiltinTier0EntryTableOffset
Definition: v8-internal.h:860
static const int kFixedArrayHeaderSize
Definition: v8-internal.h:819
static const int kNullOddballKind
Definition: v8-internal.h:972
static const int kUndefinedValueRootIndex
Definition: v8-internal.h:946
static const int kExternalTwoByteRepresentationTag
Definition: v8-internal.h:830
static const int kExternalBufferTableSize
Definition: v8-internal.h:848
static constexpr Address IntToSmi(int value)
Definition: v8-internal.h:1015
static const int kDontThrow
Definition: v8-internal.h:977
static void CheckInitializedImpl(v8::Isolate *isolate)
static void * GetEmbedderData(const v8::Isolate *isolate, uint32_t slot)
Definition: v8-internal.h:1121
static const int kStackGuardSize
Definition: v8-internal.h:834
static const int kNodeStateMask
Definition: v8-internal.h:955
static const int kNodeStateIsWeakValue
Definition: v8-internal.h:956
static const int kFirstJSApiObjectType
Definition: v8-internal.h:963
static const int kStringResourceOffset
Definition: v8-internal.h:807
static const int kErrorMessageParamOffset
Definition: v8-internal.h:858
static const int kExternalPointerTableBasePointerOffset
Definition: v8-internal.h:846
static const int kFalseValueRootIndex
Definition: v8-internal.h:950
static const int kIsolateFastApiCallTargetOffset
Definition: v8-internal.h:877
static const int kTrueValueRootIndex
Definition: v8-internal.h:949
static int GetInstanceType(Address obj)
Definition: v8-internal.h:1055
static const int kThrowOnError
Definition: v8-internal.h:976
static Address ReadTaggedSignedField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1204
static const int kOddballKindOffset
Definition: v8-internal.h:810
static const int kBuiltinTier0TableSize
Definition: v8-internal.h:839
static const int kContinuationPreservedEmbedderDataOffset
Definition: v8-internal.h:913
static Address ReadTaggedPointerField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1193
static const int kNullValueRootIndex
Definition: v8-internal.h:948
static void SetEmbedderData(v8::Isolate *isolate, uint32_t slot, void *data)
Definition: v8-internal.h:1114
static Address * GetRootSlot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1134
static const int kTrustedPointerTableSize
Definition: v8-internal.h:849
static const int kTheHoleValueRootIndex
Definition: v8-internal.h:947
static constexpr int SmiValue(Address value)
Definition: v8-internal.h:1006
static const int kTablesAlignmentPaddingSize
Definition: v8-internal.h:837
static const int kHandleScopeDataSize
Definition: v8-internal.h:842
static const int kExternalOneByteRepresentationTag
Definition: v8-internal.h:831
static const int kBuiltinTier0EntryTableSize
Definition: v8-internal.h:838
static void UpdateNodeFlag(Address *obj, bool value, int shift)
Definition: v8-internal.h:1098
static void IncrementLongTasksStatsCounter(v8::Isolate *isolate)
Definition: v8-internal.h:1128
static const int kOldAllocationInfoOffset
Definition: v8-internal.h:867
static const int kIsolateEmbedderDataOffset
Definition: v8-internal.h:885
static T ReadRawField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1177
static const int kEmbedderDataSlotExternalPointerOffset
Definition: v8-internal.h:825
static int GetOddballKind(Address obj)
Definition: v8-internal.h:1072
static const int kNodeFlagsOffset
Definition: v8-internal.h:954
static const int kTrustedPointerTableBasePointerOffset
Definition: v8-internal.h:850
static const int kLastEmbedderJSApiObjectType
Definition: v8-internal.h:968
static const int kVariousBooleanFlagsOffset
Definition: v8-internal.h:856
static constexpr std::optional< Address > TryIntegralToSmi(T value)
Definition: v8-internal.h:1033
static const int kNodeClassIdOffset
Definition: v8-internal.h:953
static const int kStringRepresentationAndEncodingMask
Definition: v8-internal.h:828
static constexpr int kExternalAllocationSoftLimit
Definition: v8-internal.h:982
static const int kJSObjectHeaderSize
Definition: v8-internal.h:811
static v8::Isolate * GetIsolateForSandbox(Address obj)
Definition: v8-internal.h:1214
static const int kJSSpecialApiObjectType
Definition: v8-internal.h:961
Definition: v8-internal.h:1299
Definition: v8-internal.h:1328
T value_type
Definition: v8-internal.h:1330
StrongRootAllocator(const StrongRootAllocator< U > &other) noexcept
Definition: v8-internal.h:1336
Definition: v8-internal.h:1503
static Address ValueAsAddress(const T *value)
Definition: v8-internal.h:1544
static constexpr Address kEmpty
Definition: v8-internal.h:1509
static T * SlotAsValue(S *slot)
Definition: v8-internal.h:1549
static T * HandleAsValue(const H< T, Ms... > &handle)
Definition: v8-internal.h:1522
static bool IsEmpty(T *value)
Definition: v8-internal.h:1513
Definition: v8-internal.h:1347
constexpr WrappedIterator & operator-=(difference_type n) noexcept
Definition: v8-internal.h:1417
constexpr WrappedIterator operator--(int) noexcept
Definition: v8-internal.h:1400
constexpr WrappedIterator & operator+=(difference_type n) noexcept
Definition: v8-internal.h:1410
constexpr Iterator base() const noexcept
Definition: v8-internal.h:1425
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::reference, ElementType & > reference
Definition: v8-internal.h:1371
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::value_type, ElementType > value_type
Definition: v8-internal.h:1363
constexpr WrappedIterator & operator++() noexcept
Definition: v8-internal.h:1386
constexpr pointer operator->() const noexcept
Definition: v8-internal.h:1384
constexpr reference operator[](difference_type n) const noexcept
Definition: v8-internal.h:1421
typename std::iterator_traits< Iterator >::difference_type difference_type
Definition: v8-internal.h:1359
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::pointer, ElementType * > pointer
Definition: v8-internal.h:1367
constexpr WrappedIterator & operator--() noexcept
Definition: v8-internal.h:1396
typename std::iterator_traits< Iterator >::iterator_category iterator_category
Definition: v8-internal.h:1357
constexpr reference operator*() const noexcept
Definition: v8-internal.h:1383
constexpr WrappedIterator operator+(difference_type n) const noexcept
Definition: v8-internal.h:1405
constexpr WrappedIterator operator++(int) noexcept
Definition: v8-internal.h:1390
constexpr WrappedIterator operator-(difference_type n) const noexcept
Definition: v8-internal.h:1414
friend class WrappedIterator
Definition: v8-internal.h:1429
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:763
constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:775
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:698
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:1477
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
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
IndirectPointerHandle CodePointerHandle
Definition: v8-internal.h:736
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:771
constexpr int kTrustedPointerTableEntrySizeLog2
Definition: v8-internal.h:715
constexpr int kTrustedPointerTableEntrySize
Definition: v8-internal.h:714
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:1461
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:1493
uint32_t IndirectPointerHandle
Definition: v8-internal.h:678
constexpr CppHeapPointer_t kNullCppHeapPointer
Definition: v8-internal.h:359
const int kApiSizetSize
Definition: v8-internal.h:50
constexpr int kCodePointerTableEntryEntrypointOffset
Definition: v8-internal.h:770
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:741
constexpr TrustedPointerHandle kNullTrustedPointerHandle
Definition: v8-internal.h:710
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:1445
constexpr bool operator!=(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1453
constexpr uintptr_t kUintptrAllBitsSet
Definition: v8-internal.h:75
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:716
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:1485
constexpr int KB
Definition: v8-internal.h:36
constexpr uint64_t kAllTagsForAndBasedTypeChecking[]
Definition: v8-internal.h:510
constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:776
constexpr bool operator>=(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1469
constexpr uint32_t kTrustedPointerHandleShift
Definition: v8-internal.h:707
constexpr uint32_t kCodePointerHandleShift
Definition: v8-internal.h:745
const int kHeapObjectTag
Definition: v8-internal.h:53
const int kSmiShiftSize
Definition: v8-internal.h:185
constexpr size_t kMaxCodePointers
Definition: v8-internal.h:764
SmiTagging< kApiTaggedSize > PlatformSmiTagging
Definition: v8-internal.h:180
const int kSmiValueSize
Definition: v8-internal.h:186
constexpr bool SmiValuesAre32Bits()
Definition: v8-internal.h:190
constexpr IndirectPointerHandle kNullIndirectPointerHandle
Definition: v8-internal.h:681
uintptr_t Address
Definition: v8-internal.h:33
void PerformCastCheck(T *data)
Definition: v8-internal.h:1284
constexpr size_t kTrustedPointerTableReservationSize
Definition: v8-internal.h:703
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:777
constexpr bool operator==(const WrappedIterator< Iterator, ElementType > &x, const WrappedIterator< OtherIterator, OtherElementType > &y) noexcept
Definition: v8-internal.h:1437
const int kSmiTag
Definition: v8-internal.h:67
constexpr CodePointerHandle kNullCodePointerHandle
Definition: v8-internal.h:748
Address CppHeapPointer_t
Definition: v8-internal.h:356
constexpr CppHeapPointerHandle kNullCppHeapPointerHandle
Definition: v8-internal.h:360
constexpr int kGarbageCollectionReasonMaxValue
Definition: v8-internal.h:1295
constexpr int kCodePointerTableEntrySize
Definition: v8-internal.h:762
constexpr int kExternalBufferTableEntrySize
Definition: v8-internal.h:422
ExternalPointerTag
Definition: v8-internal.h:598
@ kExternalPointerEvacuationEntryTag
Definition: v8-internal.h:611
@ kAccessorInfoGetterTag
Definition: v8-internal.h:616
@ kFirstSharedTag
Definition: v8-internal.h:616
@ kAccessorInfoSetterTag
Definition: v8-internal.h:616
@ kAnyForeignTag
Definition: v8-internal.h:605
@ kExternalPointerFreeEntryTag
Definition: v8-internal.h:609
@ kAnyExternalPointerTag
Definition: v8-internal.h:602
@ kLastSharedTag
Definition: v8-internal.h:616
@ kExternalPointerNullTag
Definition: v8-internal.h:600
@ kLastManagedResourceTag
Definition: v8-internal.h:616
@ kExternalPointerZappedEntryTag
Definition: v8-internal.h:614
@ kFirstManagedResourceTag
Definition: v8-internal.h:616
@ kFunctionTemplateInfoCallbackTag
Definition: v8-internal.h:616
constexpr uint32_t kCodePointerHandleMarker
Definition: v8-internal.h:757
const int kSmiMinValue
Definition: v8-internal.h:187
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:1268
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:594
#define ALL_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:590
#define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag,...)
Definition: v8-internal.h:652
#define SHARED_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:538
#define MAKE_TAG(HasMarkBit, TypeTag)
Definition: v8-internal.h:595
#define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
Definition: v8-internal.h:547
#define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag,...)
Definition: v8-internal.h:650
#define V8_EXPORT
Definition: v8config.h:762
#define V8_INLINE
Definition: v8config.h:477
#define V8_LIKELY(condition)
Definition: v8config.h:627