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