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#elif defined(V8_TARGET_OS_IOS)
241// On iOS, we only get 64 GB of usable virtual address space even with the
242// "jumbo" extended virtual addressing entitlement. Limit the sandbox size to
243// 16 GB so that the base address + size for the emulated virtual address space
244// lies within the 64 GB total virtual address space.
245constexpr size_t kSandboxSizeLog2 = 34; // 16 GB
246#else
247// Everywhere else use a 1TB sandbox.
248constexpr size_t kSandboxSizeLog2 = 40; // 1 TB
249#endif // V8_TARGET_OS_ANDROID
250constexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2;
251
252// Required alignment of the sandbox. For simplicity, we require the
253// size of the guard regions to be a multiple of this, so that this specifies
254// the alignment of the sandbox including and excluding surrounding guard
255// regions. The alignment requirement is due to the pointer compression cage
256// being located at the start of the sandbox.
257constexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment;
258
259// Sandboxed pointers are stored inside the heap as offset from the sandbox
260// base shifted to the left. This way, it is guaranteed that the offset is
261// smaller than the sandbox size after shifting it to the right again. This
262// constant specifies the shift amount.
263constexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2;
264
265// Size of the guard regions surrounding the sandbox. This assumes a worst-case
266// scenario of a 32-bit unsigned index used to access an array of 64-bit values
267// with an additional 4GB (compressed pointer) offset. In particular, accesses
268// to TypedArrays are effectively computed as
269// `entry_pointer = array->base + array->offset + index * array->element_size`.
270// See also https://crbug.com/40070746 for more details.
271constexpr size_t kSandboxGuardRegionSize = 32ULL * GB + 4ULL * GB;
272
273static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
274 "The size of the guard regions around the sandbox must be a "
275 "multiple of its required alignment.");
276
277// On OSes where reserving virtual memory is too expensive to reserve the
278// entire address space backing the sandbox, notably Windows pre 8.1, we create
279// a partially reserved sandbox that doesn't actually reserve most of the
280// memory, and so doesn't have the desired security properties as unrelated
281// memory allocations could end up inside of it, but which still ensures that
282// objects that should be located inside the sandbox are allocated within
283// kSandboxSize bytes from the start of the sandbox. The minimum size of the
284// region that is actually reserved for such a sandbox is specified by this
285// constant and should be big enough to contain the pointer compression cage as
286// well as the ArrayBuffer partition.
287constexpr size_t kSandboxMinimumReservationSize = 8ULL * GB;
288
289static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
290 "The minimum reservation size for a sandbox must be larger than "
291 "the pointer compression cage contained within it.");
292
293// The maximum buffer size allowed inside the sandbox. This is mostly dependent
294// on the size of the guard regions around the sandbox: an attacker must not be
295// able to construct a buffer that appears larger than the guard regions and
296// thereby "reach out of" the sandbox.
297constexpr size_t kMaxSafeBufferSizeForSandbox = 32ULL * GB - 1;
298static_assert(kMaxSafeBufferSizeForSandbox <= kSandboxGuardRegionSize,
299 "The maximum allowed buffer size must not be larger than the "
300 "sandbox's guard regions");
301
302constexpr size_t kBoundedSizeShift = 29;
303static_assert(1ULL << (64 - kBoundedSizeShift) ==
304 kMaxSafeBufferSizeForSandbox + 1,
305 "The maximum size of a BoundedSize must be synchronized with the "
306 "kMaxSafeBufferSizeForSandbox");
307
308#endif // V8_ENABLE_SANDBOX
309
310#ifdef V8_COMPRESS_POINTERS
311
312#ifdef V8_TARGET_OS_ANDROID
313// The size of the virtual memory reservation for an external pointer table.
314// This determines the maximum number of entries in a table. Using a maximum
315// size allows omitting bounds checks on table accesses if the indices are
316// guaranteed (e.g. through shifting) to be below the maximum index. This
317// value must be a power of two.
318constexpr size_t kExternalPointerTableReservationSize = 256 * MB;
319
320// The external pointer table indices stored in HeapObjects as external
321// pointers are shifted to the left by this amount to guarantee that they are
322// smaller than the maximum table size even after the C++ compiler multiplies
323// them by 8 to be used as indexes into a table of 64 bit pointers.
324constexpr uint32_t kExternalPointerIndexShift = 7;
325#else
326constexpr size_t kExternalPointerTableReservationSize = 512 * MB;
327constexpr uint32_t kExternalPointerIndexShift = 6;
328#endif // V8_TARGET_OS_ANDROID
329
330// The maximum number of entries in an external pointer table.
331constexpr int kExternalPointerTableEntrySize = 8;
332constexpr int kExternalPointerTableEntrySizeLog2 = 3;
333constexpr size_t kMaxExternalPointers =
334 kExternalPointerTableReservationSize / kExternalPointerTableEntrySize;
335static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers,
336 "kExternalPointerTableReservationSize and "
337 "kExternalPointerIndexShift don't match");
338
339#else // !V8_COMPRESS_POINTERS
340
341// Needed for the V8.SandboxedExternalPointersCount histogram.
342constexpr size_t kMaxExternalPointers = 0;
343
344#endif // V8_COMPRESS_POINTERS
345
346constexpr uint64_t kExternalPointerMarkBit = 1ULL << 48;
347constexpr uint64_t kExternalPointerTagShift = 49;
348constexpr uint64_t kExternalPointerTagMask = 0x00fe000000000000ULL;
353constexpr uint64_t kExternalPointerTagAndMarkbitMask = 0x00ff000000000000ULL;
354constexpr uint64_t kExternalPointerPayloadMask = 0xff00ffffffffffffULL;
355
356// A ExternalPointerHandle represents a (opaque) reference to an external
357// pointer that can be stored inside the sandbox. A ExternalPointerHandle has
358// meaning only in combination with an (active) Isolate as it references an
359// external pointer stored in the currently active Isolate's
360// ExternalPointerTable. Internally, an ExternalPointerHandles is simply an
361// index into an ExternalPointerTable that is shifted to the left to guarantee
362// that it is smaller than the size of the table.
363using ExternalPointerHandle = uint32_t;
364
365// ExternalPointers point to objects located outside the sandbox. When the V8
366// sandbox is enabled, these are stored on heap as ExternalPointerHandles,
367// otherwise they are simply raw pointers.
368#ifdef V8_ENABLE_SANDBOX
370#else
372#endif
373
376
377// See `ExternalPointerHandle` for the main documentation. The difference to
378// `ExternalPointerHandle` is that the handle does not represent an arbitrary
379// external pointer but always refers to an object managed by `CppHeap`. The
380// handles are using in combination with a dedicated table for `CppHeap`
381// references.
382using CppHeapPointerHandle = uint32_t;
383
384// The actual pointer to objects located on the `CppHeap`. When pointer
385// compression is enabled these pointers are stored as `CppHeapPointerHandle`.
386// In non-compressed configurations the pointers are simply stored as raw
387// pointers.
388#ifdef V8_COMPRESS_POINTERS
390#else
392#endif
393
396
397constexpr uint64_t kCppHeapPointerMarkBit = 1ULL;
398constexpr uint64_t kCppHeapPointerTagShift = 1;
399constexpr uint64_t kCppHeapPointerPayloadShift = 16;
400
401#ifdef V8_COMPRESS_POINTERS
402// CppHeapPointers use a dedicated pointer table. These constants control the
403// size and layout of the table. See the corresponding constants for the
404// external pointer table for further details.
405constexpr size_t kCppHeapPointerTableReservationSize =
406 kExternalPointerTableReservationSize;
407constexpr uint32_t kCppHeapPointerIndexShift = kExternalPointerIndexShift;
408
409constexpr int kCppHeapPointerTableEntrySize = 8;
410constexpr int kCppHeapPointerTableEntrySizeLog2 = 3;
411constexpr size_t kMaxCppHeapPointers =
412 kCppHeapPointerTableReservationSize / kCppHeapPointerTableEntrySize;
413static_assert((1 << (32 - kCppHeapPointerIndexShift)) == kMaxCppHeapPointers,
414 "kCppHeapPointerTableReservationSize and "
415 "kCppHeapPointerIndexShift don't match");
416
417#else // !V8_COMPRESS_POINTERS
418
419// Needed for the V8.SandboxedCppHeapPointersCount histogram.
420constexpr size_t kMaxCppHeapPointers = 0;
421
422#endif // V8_COMPRESS_POINTERS
423
424// The number of tags reserved for embedder data stored in internal fields. The
425// value is picked arbitrarily, and is slightly larger than the number of tags
426// currently used in Chrome.
427#define V8_EMBEDDER_DATA_TAG_COUNT 15
428
429// Generic tag range struct to represent ranges of type tags.
430//
431// When referencing external objects via pointer tables, type tags are
432// frequently necessary to guarantee type safety for the external objects. When
433// support for subtyping is necessary, range-based type checks are used in
434// which all subtypes of a given supertype use contiguous tags. This struct can
435// then be used to represent such a type range.
436//
437// As an example, consider the following type hierarchy:
438//
439// A F
440// / \
441// B E
442// / \
443// C D
444//
445// A potential type id assignment for range-based type checks is
446// {A: 0, B: 1, C: 2, D: 3, E: 4, F: 5}. With that, the type check for type A
447// would check for the range [A, E], while the check for B would check range
448// [B, D], and for F it would simply check [F, F].
449//
450// In addition, there is an option for performance tweaks: if the size of the
451// type range corresponding to a supertype is a power of two and starts at a
452// power of two (e.g. [0x100, 0x13f]), then the compiler can often optimize
453// the type check to use even fewer instructions (essentially replace a AND +
454// SUB with a single AND).
455//
456template <typename Tag>
457struct TagRange {
458 static_assert(std::is_enum_v<Tag> &&
459 std::is_same_v<std::underlying_type_t<Tag>, uint16_t>,
460 "Tag parameter must be an enum with base type uint16_t");
461
462 // Construct the inclusive tag range [first, last].
463 constexpr TagRange(Tag first, Tag last) : first(first), last(last) {}
464
465 // Construct a tag range consisting of a single tag.
466 //
467 // A single tag is always implicitly convertible to a tag range. This greatly
468 // increases readability as most of the time, the exact tag of a field is
469 // known and so no tag range needs to explicitly be created for it.
470 constexpr TagRange(Tag tag) // NOLINT(runtime/explicit)
471 : first(tag), last(tag) {}
472
473 // Construct an empty tag range.
474 constexpr TagRange() : TagRange(static_cast<Tag>(0)) {}
475
476 // A tag range is considered empty if it only contains the null tag.
477 constexpr bool IsEmpty() const { return first == 0 && last == 0; }
478
479 constexpr size_t Size() const {
480 if (IsEmpty()) {
481 return 0;
482 } else {
483 return last - first + 1;
484 }
485 }
486
487 constexpr bool Contains(Tag tag) const {
488 // Need to perform the math with uint32_t. Otherwise, the uint16_ts would
489 // be promoted to (signed) int, allowing the compiler to (wrongly) assume
490 // that an underflow cannot happen as that would be undefined behavior.
491 return static_cast<uint32_t>(tag) - first <=
492 static_cast<uint32_t>(last) - first;
493 }
494
495 constexpr bool Contains(TagRange tag_range) const {
496 return tag_range.first >= first && tag_range.last <= last;
497 }
498
499 constexpr bool operator==(const TagRange other) const {
500 return first == other.first && last == other.last;
501 }
502
503 constexpr size_t hash_value() const {
504 static_assert(std::is_same_v<std::underlying_type_t<Tag>, uint16_t>);
505 return (static_cast<size_t>(first) << 16) | last;
506 }
507
508 // Internally we represent tag ranges as half-open ranges [first, last).
509 const Tag first;
510 const Tag last;
511};
512
513//
514// External Pointers.
515//
516// When the sandbox is enabled, external pointers are stored in an external
517// pointer table and are referenced from HeapObjects through an index (a
518// "handle"). When stored in the table, the pointers are tagged with per-type
519// tags to prevent type confusion attacks between different external objects.
520//
521// When loading an external pointer, a range of allowed tags can be specified.
522// This way, type hierarchies can be supported. The main requirement for that
523// is that all (transitive) child classes of a given parent class have type ids
524// in the same range, and that there are no unrelated types in that range. For
525// more details about how to assign type tags to types, see the TagRange class.
526//
527// The external pointer sandboxing mechanism ensures that every access to an
528// external pointer field will result in a valid pointer of the expected type
529// even in the presence of an attacker able to corrupt memory inside the
530// sandbox. However, if any data related to the external object is stored
531// inside the sandbox it may still be corrupted and so must be validated before
532// use or moved into the external object. Further, an attacker will always be
533// able to substitute different external pointers of the same type for each
534// other. Therefore, code using external pointers must be written in a
535// "substitution-safe" way, i.e. it must always be possible to substitute
536// external pointers of the same type without causing memory corruption outside
537// of the sandbox. Generally this is achieved by referencing any group of
538// related external objects through a single external pointer.
539//
540// Currently we use bit 62 for the marking bit which should always be unused as
541// it's part of the non-canonical address range. When Arm's top-byte ignore
542// (TBI) is enabled, this bit will be part of the ignored byte, and we assume
543// that the Embedder is not using this byte (really only this one bit) for any
544// other purpose. This bit also does not collide with the memory tagging
545// extension (MTE) which would use bits [56, 60).
546//
547// External pointer tables are also available even when the sandbox is off but
548// pointer compression is on. In that case, the mechanism can be used to ease
549// alignment requirements as it turns unaligned 64-bit raw pointers into
550// aligned 32-bit indices. To "opt-in" to the external pointer table mechanism
551// for this purpose, instead of using the ExternalPointer accessors one needs to
552// use ExternalPointerHandles directly and use them to access the pointers in an
553// ExternalPointerTable.
554//
555// The tag is currently in practice limited to 15 bits since it needs to fit
556// together with a marking bit into the unused parts of a pointer.
557enum ExternalPointerTag : uint16_t {
560
561 // When adding new tags, please ensure that the code using these tags is
562 // "substitution-safe", i.e. still operate safely if external pointers of the
563 // same type are swapped by an attacker. See comment above for more details.
564
565 // Shared external pointers are owned by the shared Isolate and stored in the
566 // shared external pointer table associated with that Isolate, where they can
567 // be accessed from multiple threads at the same time. The objects referenced
568 // in this way must therefore always be thread-safe.
574
575 // External pointers using these tags are kept in a per-Isolate external
576 // pointer table and can only be accessed when this Isolate is active.
578
579 // Placeholders for embedder data.
582 // This tag essentially stands for a `void*` pointer in the V8 API, and it is
583 // the Embedder's responsibility to ensure type safety (against substitution)
584 // and lifetime validity of these objects.
590
591 // InterceptorInfo external pointers.
609
611
613
614 // Foreigns
617
627
628 // Managed
659 // External resources whose lifetime is tied to their entry in the external
660 // pointer table but which are not referenced via a Managed
663
667 // The tags are limited to 7 bits, so the last tag is 0x7f.
669};
670
672
689
690// True if the external pointer must be accessed from the shared isolate's
691// external pointer table.
692V8_INLINE static constexpr bool IsSharedExternalPointerType(
693 ExternalPointerTagRange tag_range) {
695}
696
697// True if the external pointer may live in a read-only object, in which case
698// the table entry will be in the shared read-only segment of the external
699// pointer table.
700V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
701 ExternalPointerTagRange tag_range) {
703}
704
705// True if the external pointer references an external object whose lifetime is
706// tied to the entry in the external pointer table.
707// In this case, the entry in the ExternalPointerTable always points to an
708// object derived from ExternalPointerTable::ManagedResource.
709V8_INLINE static constexpr bool IsManagedExternalPointerType(
710 ExternalPointerTagRange tag_range) {
712}
713
714// When an external poiner field can contain the null external pointer handle,
715// the type checking mechanism needs to also check for null.
716// TODO(saelo): this is mostly a temporary workaround to introduce range-based
717// type checks. In the future, we should either (a) change the type tagging
718// scheme so that null always passes or (b) (more likely) introduce dedicated
719// null entries for those tags that need them (similar to other well-known
720// empty value constants such as the empty fixed array).
721V8_INLINE static constexpr bool ExternalPointerCanBeEmpty(
722 ExternalPointerTagRange tag_range) {
723 return tag_range.Contains(kArrayBufferExtensionTag) ||
724 (tag_range.first <= kLastEmbedderDataTag &&
725 kFirstEmbedderDataTag <= tag_range.last) ||
727}
728
729// Indirect Pointers.
730//
731// When the sandbox is enabled, indirect pointers are used to reference
732// HeapObjects that live outside of the sandbox (but are still managed by V8's
733// garbage collector). When object A references an object B through an indirect
734// pointer, object A will contain a IndirectPointerHandle, i.e. a shifted
735// 32-bit index, which identifies an entry in a pointer table (either the
736// trusted pointer table for TrustedObjects, or the code pointer table if it is
737// a Code object). This table entry then contains the actual pointer to object
738// B. Further, object B owns this pointer table entry, and it is responsible
739// for updating the "self-pointer" in the entry when it is relocated in memory.
740// This way, in contrast to "normal" pointers, indirect pointers never need to
741// be tracked by the GC (i.e. there is no remembered set for them).
742// These pointers do not exist when the sandbox is disabled.
743
744// An IndirectPointerHandle represents a 32-bit index into a pointer table.
745using IndirectPointerHandle = uint32_t;
746
747// A null handle always references an entry that contains nullptr.
749
750// When the sandbox is enabled, indirect pointers are used to implement:
751// - TrustedPointers: an indirect pointer using the trusted pointer table (TPT)
752// and referencing a TrustedObject in one of the trusted heap spaces.
753// - CodePointers, an indirect pointer using the code pointer table (CPT) and
754// referencing a Code object together with its instruction stream.
755
756//
757// Trusted Pointers.
758//
759// A pointer to a TrustedObject.
760// When the sandbox is enabled, these are indirect pointers using the trusted
761// pointer table (TPT). They are used to reference trusted objects (located in
762// one of V8's trusted heap spaces, outside of the sandbox) from inside the
763// sandbox in a memory-safe way. When the sandbox is disabled, these are
764// regular tagged pointers.
766
767// The size of the virtual memory reservation for the trusted pointer table.
768// As with the external pointer table, a maximum table size in combination with
769// shifted indices allows omitting bounds checks.
771
772// The trusted pointer handles are stored shifted to the left by this amount
773// to guarantee that they are smaller than the maximum table size.
774constexpr uint32_t kTrustedPointerHandleShift = 9;
775
776// A null handle always references an entry that contains nullptr.
779
780// The maximum number of entries in an trusted pointer table.
783constexpr size_t kMaxTrustedPointers =
785static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
786 "kTrustedPointerTableReservationSize and "
787 "kTrustedPointerHandleShift don't match");
788
789//
790// Code Pointers.
791//
792// A pointer to a Code object.
793// Essentially a specialized version of a trusted pointer that (when the
794// sandbox is enabled) uses the code pointer table (CPT) instead of the TPT.
795// Each entry in the CPT contains both a pointer to a Code object as well as a
796// pointer to the Code's entrypoint. This allows calling/jumping into Code with
797// one fewer memory access (compared to the case where the entrypoint pointer
798// first needs to be loaded from the Code object). As such, a CodePointerHandle
799// can be used both to obtain the referenced Code object and to directly load
800// its entrypoint.
801//
802// When the sandbox is disabled, these are regular tagged pointers.
804
805// The size of the virtual memory reservation for the code pointer table.
806// As with the other tables, a maximum table size in combination with shifted
807// indices allows omitting bounds checks.
808constexpr size_t kCodePointerTableReservationSize = 128 * MB;
809
810// Code pointer handles are shifted by a different amount than indirect pointer
811// handles as the tables have a different maximum size.
812constexpr uint32_t kCodePointerHandleShift = 9;
813
814// A null handle always references an entry that contains nullptr.
816
817// It can sometimes be necessary to distinguish a code pointer handle from a
818// trusted pointer handle. A typical example would be a union trusted pointer
819// field that can refer to both Code objects and other trusted objects. To
820// support these use-cases, we use a simple marking scheme where some of the
821// low bits of a code pointer handle are set, while they will be unset on a
822// trusted pointer handle. This way, the correct table to resolve the handle
823// can be determined even in the absence of a type tag.
824constexpr uint32_t kCodePointerHandleMarker = 0x1;
825static_assert(kCodePointerHandleShift > 0);
826static_assert(kTrustedPointerHandleShift > 0);
827
828// The maximum number of entries in a code pointer table.
829constexpr int kCodePointerTableEntrySize = 16;
831constexpr size_t kMaxCodePointers =
833static_assert(
835 "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
836
839
840// Constants that can be used to mark places that should be modified once
841// certain types of objects are moved out of the sandbox and into trusted space.
847
848// {obj} must be the raw tagged pointer representation of a HeapObject
849// that's guaranteed to never be in ReadOnlySpace.
851 "Use GetCurrentIsolate() instead, which is guaranteed to return the same "
852 "isolate since https://crrev.com/c/6458560.")
854
855// Returns if we need to throw when an error occurs. This infers the language
856// mode based on the current context and the closure. This returns true if the
857// language mode is strict.
858V8_EXPORT bool ShouldThrowOnError(internal::Isolate* isolate);
859
860struct HandleScopeData final {
861 static constexpr uint32_t kSizeInBytes =
863
866 int level;
868
869 void Initialize() {
870 next = limit = nullptr;
871 sealed_level = level = 0;
872 }
873};
874
875static_assert(HandleScopeData::kSizeInBytes == sizeof(HandleScopeData));
876
883#ifdef V8_MAP_PACKING
884 V8_INLINE static constexpr Address UnpackMapWord(Address mapword) {
885 // TODO(wenyuzhao): Clear header metadata.
886 return mapword ^ kMapWordXorMask;
887 }
888#endif
889
890 public:
891 // These values match non-compiler-dependent values defined within
892 // the implementation of v8.
893 static const int kHeapObjectMapOffset = 0;
895 static const int kStringResourceOffset =
897
899 static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
900#ifdef V8_COMPRESS_POINTERS
903#else // !V8_COMPRESS_POINTERS
906#endif // !V8_COMPRESS_POINTERS
907 static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
910#ifdef V8_ENABLE_SANDBOX
912#else
914#endif
917 static const int kStringEncodingMask = 0x8;
918 static const int kExternalTwoByteRepresentationTag = 0x02;
919 static const int kExternalOneByteRepresentationTag = 0x0a;
920
921 static const uint32_t kNumIsolateDataSlots = 4;
923 static const int kNumberOfBooleanFlags = 6;
924 static const int kErrorMessageParamSize = 1;
925 static const int kTablesAlignmentPaddingSize = 1;
931 static const int kHandleScopeDataSize =
933
934 // ExternalPointerTable and TrustedPointerTable layout guarantees.
936 static const int kSegmentedTableSegmentPoolSize = 4;
937 static const int kExternalPointerTableSize =
939 kSegmentedTableSegmentPoolSize * sizeof(uint32_t);
940 static const int kTrustedPointerTableSize =
942 kSegmentedTableSegmentPoolSize * sizeof(uint32_t);
944
945 // IsolateData layout guarantees.
946 static const int kIsolateCageBaseOffset = 0;
947 static const int kIsolateStackGuardOffset =
949 static const int kVariousBooleanFlagsOffset =
951 static const int kErrorMessageParamOffset =
956 static const int kBuiltinTier0TableOffset =
958 static const int kNewAllocationInfoOffset =
960 static const int kOldAllocationInfoOffset =
962 static const int kLastYoungAllocationOffset =
964
981 static const int kIsolateEmbedderDataOffset =
983#ifdef V8_COMPRESS_POINTERS
984 static const int kIsolateExternalPointerTableOffset =
986 static const int kIsolateSharedExternalPointerTableAddressOffset =
987 kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
988 static const int kIsolateCppHeapPointerTableOffset =
989 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
990#ifdef V8_ENABLE_SANDBOX
991 static const int kIsolateTrustedCageBaseOffset =
992 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
993 static const int kIsolateTrustedPointerTableOffset =
994 kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
995 static const int kIsolateSharedTrustedPointerTableAddressOffset =
996 kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
997 static const int kIsolateTrustedPointerPublishingScopeOffset =
998 kIsolateSharedTrustedPointerTableAddressOffset + kApiSystemPointerSize;
999 static const int kIsolateCodePointerTableBaseAddressOffset =
1000 kIsolateTrustedPointerPublishingScopeOffset + kApiSystemPointerSize;
1002 kIsolateCodePointerTableBaseAddressOffset + kApiSystemPointerSize;
1003#else
1005 kIsolateCppHeapPointerTableOffset + kExternalPointerTableSize;
1006#endif // V8_ENABLE_SANDBOX
1007#else
1010#endif // V8_COMPRESS_POINTERS
1011 static const int kJSDispatchTableOffset =
1017 static const int kIsolateRootsOffset =
1019
1020 // Assert scopes
1021 static const int kDisallowGarbageCollectionAlign = alignof(uint32_t);
1022 static const int kDisallowGarbageCollectionSize = sizeof(uint32_t);
1023
1024#if V8_STATIC_ROOTS_BOOL
1025
1026// These constants are copied from static-roots.h and guarded by static asserts.
1027#define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
1028 V(UndefinedValue, 0x11) \
1029 V(NullValue, 0x2d) \
1030 V(TrueValue, 0x71) \
1031 V(FalseValue, 0x55) \
1032 V(EmptyString, 0x49) \
1033 /* The Hole moves around depending on build flags, so define it */ \
1034 /* separately inside StaticReadOnlyRoot using build macros */ \
1035 V(TheHoleValue, kBuildDependentTheHoleValue)
1036
1037 using Tagged_t = uint32_t;
1038 struct StaticReadOnlyRoot {
1039#ifdef V8_ENABLE_WEBASSEMBLY
1040 static constexpr Tagged_t kBuildDependentTheHoleValue = 0x20001;
1041#else
1042#ifdef V8_INTL_SUPPORT
1043 static constexpr Tagged_t kBuildDependentTheHoleValue = 0x6559;
1044#else
1045 static constexpr Tagged_t kBuildDependentTheHoleValue = 0x58bd;
1046#endif
1047#endif
1048
1049#define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
1050 EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
1051#undef DEF_ROOT
1052
1053 // Use 0 for kStringMapLowerBound since string maps are the first maps.
1054 static constexpr Tagged_t kStringMapLowerBound = 0;
1055 static constexpr Tagged_t kStringMapUpperBound = 0x425;
1056
1057#define PLUSONE(...) +1
1058 static constexpr size_t kNumberOfExportedStaticRoots =
1059 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
1060#undef PLUSONE
1061 };
1062
1063#endif // V8_STATIC_ROOTS_BOOL
1064
1065 static const int kUndefinedValueRootIndex = 0;
1066 static const int kTheHoleValueRootIndex = 1;
1067 static const int kNullValueRootIndex = 2;
1068 static const int kTrueValueRootIndex = 3;
1069 static const int kFalseValueRootIndex = 4;
1070 static const int kEmptyStringRootIndex = 5;
1071
1073 static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
1074 static const int kNodeStateMask = 0x3;
1075 static const int kNodeStateIsWeakValue = 2;
1076
1077 static const int kFirstNonstringType = 0x80;
1078 static const int kOddballType = 0x83;
1079 static const int kForeignType = 0xcc;
1080 static const int kJSSpecialApiObjectType = 0x410;
1081 static const int kJSObjectType = 0x421;
1082 static const int kFirstJSApiObjectType = 0x422;
1083 static const int kLastJSApiObjectType = 0x80A;
1084 // Defines a range [kFirstEmbedderJSApiObjectType, kJSApiObjectTypesCount]
1085 // of JSApiObject instance type values that an embedder can use.
1086 static const int kFirstEmbedderJSApiObjectType = 0;
1089
1090 static const int kUndefinedOddballKind = 4;
1091 static const int kNullOddballKind = 3;
1092
1093 // Constants used by PropertyCallbackInfo to check if we should throw when an
1094 // error occurs.
1095 static const int kDontThrow = 0;
1096 static const int kThrowOnError = 1;
1097 static const int kInferShouldThrowMode = 2;
1098
1099 // Soft limit for AdjustAmountofExternalAllocatedMemory. Trigger an
1100 // incremental GC once the external memory reaches this limit.
1101 static constexpr size_t kExternalAllocationSoftLimit = 64 * 1024 * 1024;
1102
1103#ifdef V8_MAP_PACKING
1104 static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
1105 // The lowest two bits of mapwords are always `0b10`
1106 static const uintptr_t kMapWordSignature = 0b10;
1107 // XORing a (non-compressed) map with this mask ensures that the two
1108 // low-order bits are 0b10. The 0 at the end makes this look like a Smi,
1109 // although real Smis have all lower 32 bits unset. We only rely on these
1110 // values passing as Smis in very few places.
1111 static const int kMapWordXorMask = 0b11;
1112#endif
1113
1116#ifdef V8_ENABLE_CHECKS
1117 CheckInitializedImpl(isolate);
1118#endif
1119 }
1120
1121 V8_INLINE static constexpr bool HasHeapObjectTag(Address value) {
1122 return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
1123 }
1124
1125 V8_INLINE static constexpr int SmiValue(Address value) {
1126 return PlatformSmiTagging::SmiToInt(value);
1127 }
1128
1129 V8_INLINE static constexpr Address AddressToSmi(Address value) {
1130 return (value << (kSmiTagSize + PlatformSmiTagging::kSmiShiftSize)) |
1131 kSmiTag;
1132 }
1133
1134 V8_INLINE static constexpr Address IntToSmi(int value) {
1135 return AddressToSmi(static_cast<Address>(value));
1136 }
1137
1138 template <typename T,
1139 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1140 V8_INLINE static constexpr Address IntegralToSmi(T value) {
1141 return AddressToSmi(static_cast<Address>(value));
1142 }
1143
1144 template <typename T,
1145 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1146 V8_INLINE static constexpr bool IsValidSmi(T value) {
1147 return PlatformSmiTagging::IsValidSmi(value);
1148 }
1149
1150 template <typename T,
1151 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1152 static constexpr std::optional<Address> TryIntegralToSmi(T value) {
1153 if (V8_LIKELY(PlatformSmiTagging::IsValidSmi(value))) {
1154 return {AddressToSmi(static_cast<Address>(value))};
1155 }
1156 return {};
1157 }
1158
1159#if V8_STATIC_ROOTS_BOOL
1160 V8_INLINE static bool is_identical(Address obj, Tagged_t constant) {
1161 return static_cast<Tagged_t>(obj) == constant;
1162 }
1163
1164 V8_INLINE static bool CheckInstanceMapRange(Address obj, Tagged_t first_map,
1165 Tagged_t last_map) {
1166 auto map = ReadRawField<Tagged_t>(obj, kHeapObjectMapOffset);
1167#ifdef V8_MAP_PACKING
1168 map = UnpackMapWord(map);
1169#endif
1170 return map >= first_map && map <= last_map;
1171 }
1172#endif
1173
1176#ifdef V8_MAP_PACKING
1177 map = UnpackMapWord(map);
1178#endif
1179 return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
1180 }
1181
1183 if (!HasHeapObjectTag(obj)) return kNullAddress;
1185#ifdef V8_MAP_PACKING
1186 map = UnpackMapWord(map);
1187#endif
1188 return map;
1189 }
1190
1193 }
1194
1195 V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
1196 int representation = (instance_type & kStringRepresentationAndEncodingMask);
1197 return representation == kExternalTwoByteRepresentationTag;
1198 }
1199
1200 V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
1201 static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
1202 static_assert(kJSObjectType < kLastJSApiObjectType);
1204 // Check for IsJSObject() || IsJSSpecialApiObject() || IsJSApiObject()
1205 return instance_type == kJSSpecialApiObjectType ||
1206 // inlined version of base::IsInRange
1207 (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
1208 static_cast<unsigned>(kJSObjectType)) <=
1209 static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
1210 }
1211
1212 V8_INLINE static uint8_t GetNodeFlag(Address* obj, int shift) {
1213 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1214 return *addr & static_cast<uint8_t>(1U << shift);
1215 }
1216
1217 V8_INLINE static void UpdateNodeFlag(Address* obj, bool value, int shift) {
1218 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1219 uint8_t mask = static_cast<uint8_t>(1U << shift);
1220 *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
1221 }
1222
1223 V8_INLINE static uint8_t GetNodeState(Address* obj) {
1224 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1225 return *addr & kNodeStateMask;
1226 }
1227
1228 V8_INLINE static void UpdateNodeState(Address* obj, uint8_t value) {
1229 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1230 *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
1231 }
1232
1233 V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
1234 void* data) {
1235 Address addr = reinterpret_cast<Address>(isolate) +
1237 *reinterpret_cast<void**>(addr) = data;
1238 }
1239
1240 V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
1241 uint32_t slot) {
1242 Address addr = reinterpret_cast<Address>(isolate) +
1244 return *reinterpret_cast<void* const*>(addr);
1245 }
1246
1248 Address addr =
1249 reinterpret_cast<Address>(isolate) + kIsolateHandleScopeDataOffset;
1250 return reinterpret_cast<HandleScopeData*>(addr);
1251 }
1252
1254 Address addr =
1255 reinterpret_cast<Address>(isolate) + kIsolateLongTaskStatsCounterOffset;
1256 ++(*reinterpret_cast<size_t*>(addr));
1257 }
1258
1259 V8_INLINE static Address* GetRootSlot(v8::Isolate* isolate, int index) {
1260 Address addr = reinterpret_cast<Address>(isolate) + kIsolateRootsOffset +
1261 index * kApiSystemPointerSize;
1262 return reinterpret_cast<Address*>(addr);
1263 }
1264
1265 V8_INLINE static Address GetRoot(v8::Isolate* isolate, int index) {
1266#if V8_STATIC_ROOTS_BOOL
1267 Address base = *reinterpret_cast<Address*>(
1268 reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
1269 switch (index) {
1270#define DECOMPRESS_ROOT(name, ...) \
1271 case k##name##RootIndex: \
1272 return base + StaticReadOnlyRoot::k##name;
1273 EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
1274#undef DECOMPRESS_ROOT
1275#undef EXPORTED_STATIC_ROOTS_PTR_LIST
1276 default:
1277 break;
1278 }
1279#endif // V8_STATIC_ROOTS_BOOL
1280 return *GetRootSlot(isolate, index);
1281 }
1282
1283#ifdef V8_ENABLE_SANDBOX
1284 V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) {
1285 Address addr = reinterpret_cast<Address>(isolate) +
1286 kIsolateExternalPointerTableOffset +
1288 return *reinterpret_cast<Address**>(addr);
1289 }
1290
1291 V8_INLINE static Address* GetSharedExternalPointerTableBase(
1292 v8::Isolate* isolate) {
1293 Address addr = reinterpret_cast<Address>(isolate) +
1294 kIsolateSharedExternalPointerTableAddressOffset;
1295 addr = *reinterpret_cast<Address*>(addr);
1297 return *reinterpret_cast<Address**>(addr);
1298 }
1299#endif
1300
1301 template <typename T>
1302 V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
1303 Address addr = heap_object_ptr + offset - kHeapObjectTag;
1304#ifdef V8_COMPRESS_POINTERS
1305 if constexpr (sizeof(T) > kApiTaggedSize) {
1306 // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
1307 // fields (external pointers, doubles and BigInt data) are only
1308 // kTaggedSize aligned so we have to use unaligned pointer friendly way of
1309 // accessing them in order to avoid undefined behavior in C++ code.
1310 T r;
1311 memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
1312 return r;
1313 }
1314#endif
1315 return *reinterpret_cast<const T*>(addr);
1316 }
1317
1319 int offset) {
1320#ifdef V8_COMPRESS_POINTERS
1321 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1322 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1323 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1324#else
1325 return ReadRawField<Address>(heap_object_ptr, offset);
1326#endif
1327 }
1328
1330 int offset) {
1331#ifdef V8_COMPRESS_POINTERS
1332 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1333 return static_cast<Address>(static_cast<uintptr_t>(value));
1334#else
1335 return ReadRawField<Address>(heap_object_ptr, offset);
1336#endif
1337 }
1338
1339 // Returns v8::Isolate::Current(), but without needing to include the
1340 // v8-isolate.h header.
1342
1344#ifdef V8_ENABLE_SANDBOX
1345 return GetCurrentIsolate();
1346#else
1347 // Not used in non-sandbox mode.
1348 return nullptr;
1349#endif
1350 }
1351
1352 template <ExternalPointerTagRange tag_range>
1354 Address heap_object_ptr,
1355 int offset) {
1356#ifdef V8_ENABLE_SANDBOX
1357 static_assert(!tag_range.IsEmpty());
1358 // See src/sandbox/external-pointer-table.h. Logic duplicated here so
1359 // it can be inlined and doesn't require an additional call.
1360 Address* table = IsSharedExternalPointerType(tag_range)
1361 ? GetSharedExternalPointerTableBase(isolate)
1362 : GetExternalPointerTableBase(isolate);
1364 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1365 uint32_t index = handle >> kExternalPointerIndexShift;
1366 std::atomic<Address>* ptr =
1367 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1368 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1369 ExternalPointerTag actual_tag = static_cast<ExternalPointerTag>(
1371 if (V8_LIKELY(tag_range.Contains(actual_tag))) {
1372 return entry & kExternalPointerPayloadMask;
1373 } else {
1374 return 0;
1375 }
1376 return entry;
1377#else
1378 return ReadRawField<Address>(heap_object_ptr, offset);
1379#endif // V8_ENABLE_SANDBOX
1380 }
1381
1383 v8::Isolate* isolate, Address heap_object_ptr, int offset,
1384 ExternalPointerTagRange tag_range) {
1385#ifdef V8_ENABLE_SANDBOX
1386 // See src/sandbox/external-pointer-table.h. Logic duplicated here so
1387 // it can be inlined and doesn't require an additional call.
1388 Address* table = IsSharedExternalPointerType(tag_range)
1389 ? GetSharedExternalPointerTableBase(isolate)
1390 : GetExternalPointerTableBase(isolate);
1392 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1393 uint32_t index = handle >> kExternalPointerIndexShift;
1394 std::atomic<Address>* ptr =
1395 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1396 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1397 ExternalPointerTag actual_tag = static_cast<ExternalPointerTag>(
1399 if (V8_LIKELY(tag_range.Contains(actual_tag))) {
1400 return entry & kExternalPointerPayloadMask;
1401 } else {
1402 return 0;
1403 }
1404 return entry;
1405#else
1406 return ReadRawField<Address>(heap_object_ptr, offset);
1407#endif // V8_ENABLE_SANDBOX
1408 }
1409
1410#ifdef V8_COMPRESS_POINTERS
1411 V8_INLINE static Address GetPtrComprCageBaseFromOnHeapAddress(Address addr) {
1412 return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
1413 }
1414
1415 V8_INLINE static uint32_t CompressTagged(Address value) {
1416 return static_cast<uint32_t>(value);
1417 }
1418
1419 V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
1420 uint32_t value) {
1421 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1422 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1423 }
1424
1425#endif // V8_COMPRESS_POINTERS
1426};
1427
1428// Only perform cast check for types derived from v8::Data since
1429// other types do not implement the Cast method.
1430template <bool PerformCheck>
1432 template <class T>
1433 static void Perform(T* data);
1434};
1435
1436template <>
1437template <class T>
1439 T::Cast(data);
1440}
1441
1442template <>
1443template <class T>
1445
1446template <class T>
1449 !std::is_same_v<Data, std::remove_cv_t<T>>>::Perform(data);
1450}
1451
1452// A base class for backing stores, which is needed due to vagaries of
1453// how static casts work with std::shared_ptr.
1455
1456// The maximum value in enum GarbageCollectionReason, defined in heap.h.
1457// This is needed for histograms sampling garbage collection reasons.
1459
1460// Base class for the address block allocator compatible with standard
1461// containers, which registers its allocated range as strong roots.
1463 public:
1464 Heap* heap() const { return heap_; }
1465
1467 const StrongRootAllocatorBase& b) {
1468 // TODO(pkasting): Replace this body with `= default` after dropping support
1469 // for old gcc versions.
1470 return a.heap_ == b.heap_;
1471 }
1472
1473 protected:
1474 explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
1475 explicit StrongRootAllocatorBase(LocalHeap* heap);
1478 explicit StrongRootAllocatorBase(LocalIsolate* isolate);
1479
1480 // Allocate/deallocate a range of n elements of type internal::Address.
1482 void deallocate_impl(Address* p, size_t n) noexcept;
1483
1484 private:
1485 Heap* heap_;
1486};
1487
1488// The general version of this template behaves just as std::allocator, with
1489// the exception that the constructor takes the isolate as parameter. Only
1490// specialized versions, e.g., internal::StrongRootAllocator<internal::Address>
1491// and internal::StrongRootAllocator<v8::Local<T>> register the allocated range
1492// as strong roots.
1493template <typename T>
1494class StrongRootAllocator : private std::allocator<T> {
1495 public:
1496 using value_type = T;
1497
1498 template <typename HeapOrIsolateT>
1499 explicit StrongRootAllocator(HeapOrIsolateT*) {}
1500 template <typename U>
1502
1503 using std::allocator<T>::allocate;
1504 using std::allocator<T>::deallocate;
1505};
1506
1507// TODO(pkasting): Replace with `requires` clauses after dropping support for
1508// old gcc versions.
1509template <typename Iterator, typename = void>
1510inline constexpr bool kHaveIteratorConcept = false;
1511template <typename Iterator>
1512inline constexpr bool kHaveIteratorConcept<
1513 Iterator, std::void_t<typename Iterator::iterator_concept>> = true;
1514
1515template <typename Iterator, typename = void>
1516inline constexpr bool kHaveIteratorCategory = false;
1517template <typename Iterator>
1518inline constexpr bool kHaveIteratorCategory<
1519 Iterator, std::void_t<typename Iterator::iterator_category>> = true;
1520
1521// Helper struct that contains an `iterator_concept` type alias only when either
1522// `Iterator` or `std::iterator_traits<Iterator>` do.
1523// Default: no alias.
1524template <typename Iterator, typename = void>
1526// Use `Iterator::iterator_concept` if available.
1527template <typename Iterator>
1529 Iterator, std::enable_if_t<kHaveIteratorConcept<Iterator>>> {
1530 using iterator_concept = typename Iterator::iterator_concept;
1531};
1532// Otherwise fall back to `std::iterator_traits<Iterator>` if possible.
1533template <typename Iterator>
1535 Iterator, std::enable_if_t<kHaveIteratorCategory<Iterator> &&
1536 !kHaveIteratorConcept<Iterator>>> {
1537 // There seems to be no feature-test macro covering this, so use the
1538 // presence of `<ranges>` as a crude proxy, since it was added to the
1539 // standard as part of the Ranges papers.
1540 // TODO(pkasting): Add this unconditionally after dropping support for old
1541 // libstdc++ versions.
1542#if __has_include(<ranges>)
1543 using iterator_concept =
1544 typename std::iterator_traits<Iterator>::iterator_concept;
1545#endif
1546};
1547
1548// A class of iterators that wrap some different iterator type.
1549// If specified, ElementType is the type of element accessed by the wrapper
1550// iterator; in this case, the actual reference and pointer types of Iterator
1551// must be convertible to ElementType& and ElementType*, respectively.
1552template <typename Iterator, typename ElementType = void>
1554 public:
1555 static_assert(
1556 std::is_void_v<ElementType> ||
1557 (std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
1558 std::add_pointer_t<ElementType>> &&
1559 std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
1560 std::add_lvalue_reference_t<ElementType>>));
1561
1563 typename std::iterator_traits<Iterator>::difference_type;
1565 std::conditional_t<std::is_void_v<ElementType>,
1566 typename std::iterator_traits<Iterator>::value_type,
1567 ElementType>;
1568 using pointer =
1569 std::conditional_t<std::is_void_v<ElementType>,
1570 typename std::iterator_traits<Iterator>::pointer,
1571 std::add_pointer_t<ElementType>>;
1573 std::conditional_t<std::is_void_v<ElementType>,
1574 typename std::iterator_traits<Iterator>::reference,
1575 std::add_lvalue_reference_t<ElementType>>;
1577 typename std::iterator_traits<Iterator>::iterator_category;
1578
1579 constexpr WrappedIterator() noexcept = default;
1580 constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
1581
1582 // TODO(pkasting): Switch to `requires` and concepts after dropping support
1583 // for old gcc and libstdc++ versions.
1584 template <typename OtherIterator, typename OtherElementType,
1585 typename = std::enable_if_t<
1586 std::is_convertible_v<OtherIterator, Iterator>>>
1589 : it_(other.base()) {}
1590
1591 [[nodiscard]] constexpr reference operator*() const noexcept { return *it_; }
1592 [[nodiscard]] constexpr pointer operator->() const noexcept {
1593 if constexpr (std::is_pointer_v<Iterator>) {
1594 return it_;
1595 } else {
1596 return it_.operator->();
1597 }
1598 }
1599
1600 template <typename OtherIterator, typename OtherElementType>
1601 [[nodiscard]] constexpr bool operator==(
1603 const noexcept {
1604 return it_ == other.base();
1605 }
1606#if V8_HAVE_SPACESHIP_OPERATOR
1607 template <typename OtherIterator, typename OtherElementType>
1608 [[nodiscard]] constexpr auto operator<=>(
1610 const noexcept {
1611 if constexpr (std::three_way_comparable_with<Iterator, OtherIterator>) {
1612 return it_ <=> other.base();
1613 } else if constexpr (std::totally_ordered_with<Iterator, OtherIterator>) {
1614 if (it_ < other.base()) {
1615 return std::strong_ordering::less;
1616 }
1617 return (it_ > other.base()) ? std::strong_ordering::greater
1618 : std::strong_ordering::equal;
1619 } else {
1620 if (it_ < other.base()) {
1621 return std::partial_ordering::less;
1622 }
1623 if (other.base() < it_) {
1624 return std::partial_ordering::greater;
1625 }
1626 return (it_ == other.base()) ? std::partial_ordering::equivalent
1627 : std::partial_ordering::unordered;
1628 }
1629 }
1630#else
1631 // Assume that if spaceship isn't present, operator rewriting might not be
1632 // either.
1633 template <typename OtherIterator, typename OtherElementType>
1634 [[nodiscard]] constexpr bool operator!=(
1636 const noexcept {
1637 return it_ != other.base();
1638 }
1639
1640 template <typename OtherIterator, typename OtherElementType>
1641 [[nodiscard]] constexpr bool operator<(
1643 const noexcept {
1644 return it_ < other.base();
1645 }
1646 template <typename OtherIterator, typename OtherElementType>
1647 [[nodiscard]] constexpr bool operator<=(
1649 const noexcept {
1650 return it_ <= other.base();
1651 }
1652 template <typename OtherIterator, typename OtherElementType>
1653 [[nodiscard]] constexpr bool operator>(
1655 const noexcept {
1656 return it_ > other.base();
1657 }
1658 template <typename OtherIterator, typename OtherElementType>
1659 [[nodiscard]] constexpr bool operator>=(
1661 const noexcept {
1662 return it_ >= other.base();
1663 }
1664#endif
1665
1666 constexpr WrappedIterator& operator++() noexcept {
1667 ++it_;
1668 return *this;
1669 }
1670 constexpr WrappedIterator operator++(int) noexcept {
1671 WrappedIterator result(*this);
1672 ++(*this);
1673 return result;
1674 }
1675
1676 constexpr WrappedIterator& operator--() noexcept {
1677 --it_;
1678 return *this;
1679 }
1680 constexpr WrappedIterator operator--(int) noexcept {
1681 WrappedIterator result(*this);
1682 --(*this);
1683 return result;
1684 }
1685 [[nodiscard]] constexpr WrappedIterator operator+(
1686 difference_type n) const noexcept {
1687 WrappedIterator result(*this);
1688 result += n;
1689 return result;
1690 }
1691 [[nodiscard]] friend constexpr WrappedIterator operator+(
1692 difference_type n, const WrappedIterator& x) noexcept {
1693 return x + n;
1694 }
1696 it_ += n;
1697 return *this;
1698 }
1699 [[nodiscard]] constexpr WrappedIterator operator-(
1700 difference_type n) const noexcept {
1701 return *this + -n;
1702 }
1704 return *this += -n;
1705 }
1706 template <typename OtherIterator, typename OtherElementType>
1707 [[nodiscard]] constexpr auto operator-(
1709 const noexcept {
1710 return it_ - other.base();
1711 }
1712 [[nodiscard]] constexpr reference operator[](
1713 difference_type n) const noexcept {
1714 return it_[n];
1715 }
1716
1717 [[nodiscard]] constexpr const Iterator& base() const noexcept { return it_; }
1718
1719 private:
1720 Iterator it_;
1721};
1722
1723// Helper functions about values contained in handles.
1724// A value is either an indirect pointer or a direct pointer, depending on
1725// whether direct local support is enabled.
1726class ValueHelper final {
1727 public:
1728 // ValueHelper::InternalRepresentationType is an abstract type that
1729 // corresponds to the internal representation of v8::Local and essentially
1730 // to what T* really is (these two are always in sync). This type is used in
1731 // methods like GetDataFromSnapshotOnce that need access to a handle's
1732 // internal representation. In particular, if `x` is a `v8::Local<T>`, then
1733 // `v8::Local<T>::FromRepr(x.repr())` gives exactly the same handle as `x`.
1734#ifdef V8_ENABLE_DIRECT_HANDLE
1735 static constexpr Address kTaggedNullAddress = 1;
1736
1738 static constexpr InternalRepresentationType kEmpty = kTaggedNullAddress;
1739#else
1741 static constexpr InternalRepresentationType kEmpty = nullptr;
1742#endif // V8_ENABLE_DIRECT_HANDLE
1743
1744 template <typename T>
1745 V8_INLINE static bool IsEmpty(T* value) {
1746 return ValueAsRepr(value) == kEmpty;
1747 }
1748
1749 // Returns a handle's "value" for all kinds of abstract handles. For Local,
1750 // it is equivalent to `*handle`. The variadic parameters support handle
1751 // types with extra type parameters, like `Persistent<T, M>`.
1752 template <template <typename T, typename... Ms> typename H, typename T,
1753 typename... Ms>
1754 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
1755 return handle.template value<T>();
1756 }
1757
1758#ifdef V8_ENABLE_DIRECT_HANDLE
1759
1760 template <typename T>
1761 V8_INLINE static Address ValueAsAddress(const T* value) {
1762 return reinterpret_cast<Address>(value);
1763 }
1764
1765 template <typename T, bool check_null = true, typename S>
1766 V8_INLINE static T* SlotAsValue(S* slot) {
1767 if (check_null && slot == nullptr) {
1768 return reinterpret_cast<T*>(kTaggedNullAddress);
1769 }
1770 return *reinterpret_cast<T**>(slot);
1771 }
1772
1773 template <typename T>
1774 V8_INLINE static InternalRepresentationType ValueAsRepr(const T* value) {
1775 return reinterpret_cast<InternalRepresentationType>(value);
1776 }
1777
1778 template <typename T>
1780 return reinterpret_cast<T*>(repr);
1781 }
1782
1783#else // !V8_ENABLE_DIRECT_HANDLE
1784
1785 template <typename T>
1786 V8_INLINE static Address ValueAsAddress(const T* value) {
1787 return *reinterpret_cast<const Address*>(value);
1788 }
1789
1790 template <typename T, bool check_null = true, typename S>
1791 V8_INLINE static T* SlotAsValue(S* slot) {
1792 return reinterpret_cast<T*>(slot);
1793 }
1794
1795 template <typename T>
1797 return const_cast<InternalRepresentationType>(
1798 reinterpret_cast<const Address*>(value));
1799 }
1800
1801 template <typename T>
1803 return reinterpret_cast<T*>(repr);
1804 }
1805
1806#endif // V8_ENABLE_DIRECT_HANDLE
1807};
1808
1812class HandleHelper final {
1813 public:
1824 template <typename T1, typename T2>
1825 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
1826 if (lhs.IsEmpty()) return rhs.IsEmpty();
1827 if (rhs.IsEmpty()) return false;
1828 return lhs.ptr() == rhs.ptr();
1829 }
1830};
1831
1833
1834// These functions are here just to match friend declarations in
1835// XxxCallbackInfo classes allowing these functions to access the internals
1836// of the info objects. These functions are supposed to be called by debugger
1837// macros.
1838void PrintFunctionCallbackInfo(void* function_callback_info);
1839void PrintPropertyCallbackInfo(void* property_callback_info);
1840
1841} // namespace internal
1842} // namespace v8
1843
1844#endif // INCLUDE_V8_INTERNAL_H_
Definition: v8-isolate.h:290
Definition: v8-internal.h:1454
Definition: v8-internal.h:1812
static bool EqualHandles(const T1 &lhs, const T2 &rhs)
Definition: v8-internal.h:1825
Definition: v8-internal.h:882
static Address LoadMap(Address obj)
Definition: v8-internal.h:1182
static constexpr size_t kExternalAllocationSoftLimit
Definition: v8-internal.h:1101
static bool IsExternalTwoByteString(int instance_type)
Definition: v8-internal.h:1195
static const int kIsolateCageBaseOffset
Definition: v8-internal.h:946
static const int kEmbedderDataArrayHeaderSize
Definition: v8-internal.h:908
static const int kHeapObjectMapOffset
Definition: v8-internal.h:893
static const int kEmbedderDataSlotSize
Definition: v8-internal.h:909
static const int kIsolateApiCallbackThunkArgumentOffset
Definition: v8-internal.h:1008
static Address ReadExternalPointerField(v8::Isolate *isolate, Address heap_object_ptr, int offset)
Definition: v8-internal.h:1353
static const int kJSAPIObjectWithEmbedderSlotsHeaderSize
Definition: v8-internal.h:904
static constexpr bool HasHeapObjectTag(Address value)
Definition: v8-internal.h:1121
static Address ReadExternalPointerField(v8::Isolate *isolate, Address heap_object_ptr, int offset, ExternalPointerTagRange tag_range)
Definition: v8-internal.h:1382
static const int kOddballType
Definition: v8-internal.h:1078
static const int kInferShouldThrowMode
Definition: v8-internal.h:1097
static const int kNewAllocationInfoOffset
Definition: v8-internal.h:958
static Address GetRoot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1265
static const int kStringEncodingMask
Definition: v8-internal.h:917
static const int kIsolateFastCCallCallerPcOffset
Definition: v8-internal.h:968
static uint8_t GetNodeFlag(Address *obj, int shift)
Definition: v8-internal.h:1212
static const int kIsolateThreadLocalTopOffset
Definition: v8-internal.h:977
static const uint32_t kNumIsolateDataSlots
Definition: v8-internal.h:921
static const int kForeignType
Definition: v8-internal.h:1079
static const int kJSDispatchTableOffset
Definition: v8-internal.h:1011
static const int kFirstEmbedderJSApiObjectType
Definition: v8-internal.h:1086
static const int kNumberOfBooleanFlags
Definition: v8-internal.h:923
static uint8_t GetNodeState(Address *obj)
Definition: v8-internal.h:1223
static const int kThreadLocalTopSize
Definition: v8-internal.h:930
static const int kIsolateRootsOffset
Definition: v8-internal.h:1017
static const int kExternalPointerTableSize
Definition: v8-internal.h:937
static const int kUndefinedOddballKind
Definition: v8-internal.h:1090
static const int kMapInstanceTypeOffset
Definition: v8-internal.h:894
static constexpr Address AddressToSmi(Address value)
Definition: v8-internal.h:1129
static const int kIsolateStackGuardOffset
Definition: v8-internal.h:947
static const int kLinearAllocationAreaSize
Definition: v8-internal.h:929
static const int kFastCCallAlignmentPaddingSize
Definition: v8-internal.h:965
static const int kDisallowGarbageCollectionAlign
Definition: v8-internal.h:1021
static const int kIsolateFastCCallCallerFpOffset
Definition: v8-internal.h:971
static const int kErrorMessageParamSize
Definition: v8-internal.h:924
static const int kSegmentedTableSegmentPoolSize
Definition: v8-internal.h:936
static void CheckInitialized(v8::Isolate *isolate)
Definition: v8-internal.h:1115
static void UpdateNodeState(Address *obj, uint8_t value)
Definition: v8-internal.h:1228
static constexpr Address IntegralToSmi(T value)
Definition: v8-internal.h:1140
static constexpr bool IsValidSmi(T value)
Definition: v8-internal.h:1146
static const int kJSObjectType
Definition: v8-internal.h:1081
static const int kBuiltinTier0TableOffset
Definition: v8-internal.h:956
static const int kIsolateLongTaskStatsCounterOffset
Definition: v8-internal.h:975
static const int kNativeContextEmbedderDataOffset
Definition: v8-internal.h:915
static const int kLastJSApiObjectType
Definition: v8-internal.h:1083
static constexpr bool CanHaveInternalField(int instance_type)
Definition: v8-internal.h:1200
static const int kIsolateHandleScopeDataOffset
Definition: v8-internal.h:979
static const int kFirstNonstringType
Definition: v8-internal.h:1077
static const int kEmptyStringRootIndex
Definition: v8-internal.h:1070
static const int kBuiltinTier0EntryTableOffset
Definition: v8-internal.h:953
static const int kFixedArrayHeaderSize
Definition: v8-internal.h:907
static const int kNullOddballKind
Definition: v8-internal.h:1091
static const int kUndefinedValueRootIndex
Definition: v8-internal.h:1065
static const int kExternalTwoByteRepresentationTag
Definition: v8-internal.h:918
static constexpr Address IntToSmi(int value)
Definition: v8-internal.h:1134
static const int kDontThrow
Definition: v8-internal.h:1095
static void CheckInitializedImpl(v8::Isolate *isolate)
static void * GetEmbedderData(const v8::Isolate *isolate, uint32_t slot)
Definition: v8-internal.h:1240
static const int kStackGuardSize
Definition: v8-internal.h:922
static const int kNodeStateMask
Definition: v8-internal.h:1074
static HandleScopeData * GetHandleScopeData(v8::Isolate *isolate)
Definition: v8-internal.h:1247
static const int kNodeStateIsWeakValue
Definition: v8-internal.h:1075
static const int kFirstJSApiObjectType
Definition: v8-internal.h:1082
static const int kStringResourceOffset
Definition: v8-internal.h:895
static const int kErrorMessageParamOffset
Definition: v8-internal.h:951
static const int kExternalPointerTableBasePointerOffset
Definition: v8-internal.h:935
static const int kFalseValueRootIndex
Definition: v8-internal.h:1069
static const int kIsolateRegexpExecVectorArgumentOffset
Definition: v8-internal.h:1013
static const int kIsolateFastApiCallTargetOffset
Definition: v8-internal.h:973
static const int kTrueValueRootIndex
Definition: v8-internal.h:1068
static int GetInstanceType(Address obj)
Definition: v8-internal.h:1174
static const int kThrowOnError
Definition: v8-internal.h:1096
static Address ReadTaggedSignedField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1329
static const int kOddballKindOffset
Definition: v8-internal.h:898
static const int kBuiltinTier0TableSize
Definition: v8-internal.h:928
static const int kContinuationPreservedEmbedderDataOffset
Definition: v8-internal.h:1015
static const int kLastYoungAllocationOffset
Definition: v8-internal.h:962
static Address ReadTaggedPointerField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1318
static const int kNullValueRootIndex
Definition: v8-internal.h:1067
static void SetEmbedderData(v8::Isolate *isolate, uint32_t slot, void *data)
Definition: v8-internal.h:1233
static Address * GetRootSlot(v8::Isolate *isolate, int index)
Definition: v8-internal.h:1259
static const int kTrustedPointerTableSize
Definition: v8-internal.h:940
static const int kTheHoleValueRootIndex
Definition: v8-internal.h:1066
static constexpr int SmiValue(Address value)
Definition: v8-internal.h:1125
static const int kTablesAlignmentPaddingSize
Definition: v8-internal.h:925
static const int kHandleScopeDataSize
Definition: v8-internal.h:931
static const int kExternalOneByteRepresentationTag
Definition: v8-internal.h:919
static const int kBuiltinTier0EntryTableSize
Definition: v8-internal.h:927
static void UpdateNodeFlag(Address *obj, bool value, int shift)
Definition: v8-internal.h:1217
static void IncrementLongTasksStatsCounter(v8::Isolate *isolate)
Definition: v8-internal.h:1253
static const int kDisallowGarbageCollectionSize
Definition: v8-internal.h:1022
static const int kOldAllocationInfoOffset
Definition: v8-internal.h:960
static const int kIsolateEmbedderDataOffset
Definition: v8-internal.h:981
static T ReadRawField(Address heap_object_ptr, int offset)
Definition: v8-internal.h:1302
static v8::Isolate * GetCurrentIsolate()
static const int kEmbedderDataSlotExternalPointerOffset
Definition: v8-internal.h:913
static v8::Isolate * GetCurrentIsolateForSandbox()
Definition: v8-internal.h:1343
static int GetOddballKind(Address obj)
Definition: v8-internal.h:1191
static const int kNodeFlagsOffset
Definition: v8-internal.h:1073
static const int kTrustedPointerTableBasePointerOffset
Definition: v8-internal.h:943
static const int kRegExpStaticResultOffsetsVectorSize
Definition: v8-internal.h:926
static const int kLastEmbedderJSApiObjectType
Definition: v8-internal.h:1087
static const int kVariousBooleanFlagsOffset
Definition: v8-internal.h:949
static constexpr std::optional< Address > TryIntegralToSmi(T value)
Definition: v8-internal.h:1152
static const int kNodeClassIdOffset
Definition: v8-internal.h:1072
static const int kStringRepresentationAndEncodingMask
Definition: v8-internal.h:916
static const int kJSObjectHeaderSize
Definition: v8-internal.h:899
static const int kJSSpecialApiObjectType
Definition: v8-internal.h:1080
Definition: v8-internal.h:1462
friend bool operator==(const StrongRootAllocatorBase &a, const StrongRootAllocatorBase &b)
Definition: v8-internal.h:1466
StrongRootAllocatorBase(Heap *heap)
Definition: v8-internal.h:1474
StrongRootAllocatorBase(v8::Isolate *isolate)
StrongRootAllocatorBase(LocalIsolate *isolate)
void deallocate_impl(Address *p, size_t n) noexcept
Heap * heap() const
Definition: v8-internal.h:1464
Definition: v8-internal.h:1494
StrongRootAllocator(HeapOrIsolateT *)
Definition: v8-internal.h:1499
T value_type
Definition: v8-internal.h:1496
StrongRootAllocator(const StrongRootAllocator< U > &other) noexcept
Definition: v8-internal.h:1501
Definition: v8-internal.h:1726
static Address ValueAsAddress(const T *value)
Definition: v8-internal.h:1786
static T * ReprAsValue(InternalRepresentationType repr)
Definition: v8-internal.h:1802
internal::Address * InternalRepresentationType
Definition: v8-internal.h:1740
static T * SlotAsValue(S *slot)
Definition: v8-internal.h:1791
static T * HandleAsValue(const H< T, Ms... > &handle)
Definition: v8-internal.h:1754
static InternalRepresentationType ValueAsRepr(const T *value)
Definition: v8-internal.h:1796
static bool IsEmpty(T *value)
Definition: v8-internal.h:1745
static constexpr InternalRepresentationType kEmpty
Definition: v8-internal.h:1741
Definition: v8-internal.h:1553
constexpr WrappedIterator & operator-=(difference_type n) noexcept
Definition: v8-internal.h:1703
constexpr WrappedIterator operator--(int) noexcept
Definition: v8-internal.h:1680
constexpr WrappedIterator & operator+=(difference_type n) noexcept
Definition: v8-internal.h:1695
constexpr const Iterator & base() const noexcept
Definition: v8-internal.h:1717
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::value_type, ElementType > value_type
Definition: v8-internal.h:1567
constexpr WrappedIterator & operator++() noexcept
Definition: v8-internal.h:1666
constexpr pointer operator->() const noexcept
Definition: v8-internal.h:1592
constexpr reference operator[](difference_type n) const noexcept
Definition: v8-internal.h:1712
typename std::iterator_traits< Iterator >::difference_type difference_type
Definition: v8-internal.h:1563
constexpr bool operator!=(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1634
constexpr bool operator>=(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1659
constexpr bool operator<(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1641
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:1575
constexpr WrappedIterator & operator--() noexcept
Definition: v8-internal.h:1676
constexpr WrappedIterator() noexcept=default
constexpr bool operator<=(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1647
constexpr WrappedIterator(const WrappedIterator< OtherIterator, OtherElementType > &other) noexcept
Definition: v8-internal.h:1587
constexpr bool operator>(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1653
typename std::iterator_traits< Iterator >::iterator_category iterator_category
Definition: v8-internal.h:1577
constexpr reference operator*() const noexcept
Definition: v8-internal.h:1591
constexpr auto operator-(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1707
friend constexpr WrappedIterator operator+(difference_type n, const WrappedIterator &x) noexcept
Definition: v8-internal.h:1691
constexpr WrappedIterator operator+(difference_type n) const noexcept
Definition: v8-internal.h:1685
constexpr WrappedIterator operator++(int) noexcept
Definition: v8-internal.h:1670
constexpr WrappedIterator operator-(difference_type n) const noexcept
Definition: v8-internal.h:1699
std::conditional_t< std::is_void_v< ElementType >, typename std::iterator_traits< Iterator >::pointer, std::add_pointer_t< ElementType > > pointer
Definition: v8-internal.h:1571
constexpr bool operator==(const WrappedIterator< OtherIterator, OtherElementType > &other) const noexcept
Definition: v8-internal.h:1601
const intptr_t kHeapObjectTagMask
Definition: v8-internal.h:75
constexpr uint64_t kCppHeapPointerMarkBit
Definition: v8-internal.h:397
constexpr int kCodePointerTableEntrySizeLog2
Definition: v8-internal.h:830
constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:842
internal::Isolate * IsolateFromNeverReadOnlySpaceObject(Address obj)
constexpr uint64_t kExternalPointerTagShift
Definition: v8-internal.h:347
IndirectPointerHandle TrustedPointerHandle
Definition: v8-internal.h:765
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:420
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:382
const intptr_t kForwardingTagMask
Definition: v8-internal.h:83
void PrintPropertyCallbackInfo(void *property_callback_info)
constexpr ExternalPointerTagRange kAnyManagedResourceExternalPointerTag(kFirstManagedResourceTag, kLastManagedResourceTag)
IndirectPointerHandle CodePointerHandle
Definition: v8-internal.h:803
constexpr uint64_t kExternalPointerPayloadMask
Definition: v8-internal.h:354
const int kSmiTagSize
Definition: v8-internal.h:87
const int kApiInt64Size
Definition: v8-internal.h:68
constexpr ExternalPointerTagRange kAnyExternalPointerTagRange(kFirstExternalPointerTag, kLastExternalPointerTag)
constexpr uint64_t kExternalPointerTagMask
Definition: v8-internal.h:348
constexpr int kCodePointerTableEntryCodeObjectOffset
Definition: v8-internal.h:838
constexpr int kTrustedPointerTableEntrySizeLog2
Definition: v8-internal.h:782
constexpr int kTrustedPointerTableEntrySize
Definition: v8-internal.h:781
constexpr uint64_t kCppHeapPointerPayloadShift
Definition: v8-internal.h:399
constexpr ExternalPointer_t kNullExternalPointer
Definition: v8-internal.h:374
Address ExternalPointer_t
Definition: v8-internal.h:371
uint32_t IndirectPointerHandle
Definition: v8-internal.h:745
constexpr CppHeapPointer_t kNullCppHeapPointer
Definition: v8-internal.h:394
constexpr ExternalPointerTagRange kAnySharedExternalPointerTagRange(kFirstSharedExternalPointerTag, kLastSharedExternalPointerTag)
const int kApiSizetSize
Definition: v8-internal.h:69
constexpr uint64_t kExternalPointerTagAndMarkbitMask
Definition: v8-internal.h:353
constexpr int kCodePointerTableEntryEntrypointOffset
Definition: v8-internal.h:837
constexpr size_t kMaxExternalPointers
Definition: v8-internal.h:342
constexpr size_t kCodePointerTableReservationSize
Definition: v8-internal.h:808
constexpr TrustedPointerHandle kNullTrustedPointerHandle
Definition: v8-internal.h:777
const int kWeakHeapObjectTag
Definition: v8-internal.h:73
constexpr ExternalPointerHandle kNullExternalPointerHandle
Definition: v8-internal.h:375
constexpr ExternalPointerTagRange kAnyMaybeReadOnlyExternalPointerTagRange(kFirstMaybeReadOnlyExternalPointerTag, kLastMaybeReadOnlyExternalPointerTag)
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:783
bool ShouldThrowOnError(internal::Isolate *isolate)
constexpr uint64_t kCppHeapPointerTagShift
Definition: v8-internal.h:398
constexpr ExternalPointerTagRange kAnyInterceptorInfoExternalPointerTagRange(kFirstInterceptorInfoExternalPointerTag, kLastInterceptorInfoExternalPointerTag)
constexpr int KB
Definition: v8-internal.h:55
constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace
Definition: v8-internal.h:843
constexpr uint32_t kTrustedPointerHandleShift
Definition: v8-internal.h:774
constexpr uint32_t kCodePointerHandleShift
Definition: v8-internal.h:812
constexpr ExternalPointerTagRange kAnyManagedExternalPointerTagRange(kFirstManagedExternalPointerTag, kLastManagedExternalPointerTag)
const int kHeapObjectTag
Definition: v8-internal.h:72
const int kSmiShiftSize
Definition: v8-internal.h:204
constexpr size_t kMaxCodePointers
Definition: v8-internal.h:831
constexpr bool kHaveIteratorCategory
Definition: v8-internal.h:1516
SmiTagging< kApiTaggedSize > PlatformSmiTagging
Definition: v8-internal.h:199
ExternalPointerTag
Definition: v8-internal.h:557
@ kLastForeignExternalPointerTag
Definition: v8-internal.h:657
@ kApiIndexedPropertyDescriptorCallbackTag
Definition: v8-internal.h:603
@ kGenericForeignTag
Definition: v8-internal.h:616
@ kFirstMaybeReadOnlyExternalPointerTag
Definition: v8-internal.h:586
@ kTemporalInstantTag
Definition: v8-internal.h:647
@ kTemporalPlainYearMonthTag
Definition: v8-internal.h:651
@ kExternalPointerEvacuationEntryTag
Definition: v8-internal.h:665
@ kFirstSharedExternalPointerTag
Definition: v8-internal.h:569
@ kApiNamedPropertyDefinerCallbackTag
Definition: v8-internal.h:597
@ kLastSharedExternalPointerTag
Definition: v8-internal.h:573
@ kD8WorkerTag
Definition: v8-internal.h:655
@ kApiIndexedPropertySetterCallbackTag
Definition: v8-internal.h:602
@ kWasmManagedDataTag
Definition: v8-internal.h:634
@ kLastExternalPointerTag
Definition: v8-internal.h:668
@ kIcuBreakIteratorTag
Definition: v8-internal.h:636
@ kMicrotaskCallbackDataTag
Definition: v8-internal.h:622
@ kWasmNativeModuleTag
Definition: v8-internal.h:635
@ kApiIndexedPropertyGetterCallbackTag
Definition: v8-internal.h:601
@ kApiNamedPropertyDescriptorCallbackTag
Definition: v8-internal.h:596
@ kAccessorInfoGetterTag
Definition: v8-internal.h:588
@ kTemporalPlainMonthDayTag
Definition: v8-internal.h:652
@ kIcuCollatorTag
Definition: v8-internal.h:645
@ kIcuSimpleDateFormatTag
Definition: v8-internal.h:640
@ kApiIndexedPropertyDefinerCallbackTag
Definition: v8-internal.h:604
@ kSyntheticModuleTag
Definition: v8-internal.h:620
@ kD8ModuleEmbedderDataTag
Definition: v8-internal.h:656
@ kExternalStringResourceTag
Definition: v8-internal.h:571
@ kWasmFuncDataTag
Definition: v8-internal.h:633
@ kExternalObjectValueTag
Definition: v8-internal.h:585
@ kWaiterQueueForeignTag
Definition: v8-internal.h:626
@ kAccessorInfoSetterTag
Definition: v8-internal.h:589
@ kApiNamedPropertyDeleterCallbackTag
Definition: v8-internal.h:598
@ kApiAccessCheckCallbackTag
Definition: v8-internal.h:618
@ kApiAbortScriptExecutionCallbackTag
Definition: v8-internal.h:619
@ kMicrotaskCallbackTag
Definition: v8-internal.h:621
@ kIcuLocalizedNumberFormatterTag
Definition: v8-internal.h:643
@ kApiNamedPropertyGetterCallbackTag
Definition: v8-internal.h:594
@ kApiNamedPropertySetterCallbackTag
Definition: v8-internal.h:595
@ kApiIndexedPropertyEnumeratorCallbackTag
Definition: v8-internal.h:606
@ kExternalPointerFreeEntryTag
Definition: v8-internal.h:666
@ kFirstInterceptorInfoExternalPointerTag
Definition: v8-internal.h:592
@ kCFunctionTag
Definition: v8-internal.h:623
@ kIcuUnicodeStringTag
Definition: v8-internal.h:637
@ kLastManagedExternalPointerTag
Definition: v8-internal.h:658
@ kWaiterQueueNodeTag
Definition: v8-internal.h:570
@ kGenericManagedTag
Definition: v8-internal.h:631
@ kExternalPointerNullTag
Definition: v8-internal.h:559
@ kExternalStringResourceDataTag
Definition: v8-internal.h:572
@ kTemporalZonedDateTimeTag
Definition: v8-internal.h:653
@ kWasmStackMemoryTag
Definition: v8-internal.h:612
@ kLastManagedResourceTag
Definition: v8-internal.h:662
@ kExternalPointerZappedEntryTag
Definition: v8-internal.h:664
@ kApiNamedPropertyQueryCallbackTag
Definition: v8-internal.h:593
@ kFirstForeignExternalPointerTag
Definition: v8-internal.h:615
@ kTemporalPlainDateTimeTag
Definition: v8-internal.h:650
@ kIcuListFormatterTag
Definition: v8-internal.h:638
@ kDisplayNamesInternalTag
Definition: v8-internal.h:654
@ kFirstManagedResourceTag
Definition: v8-internal.h:629
@ kFirstManagedExternalPointerTag
Definition: v8-internal.h:630
@ kTemporalPlainTimeTag
Definition: v8-internal.h:649
@ kIcuPluralRulesTag
Definition: v8-internal.h:644
@ kFirstEmbedderDataTag
Definition: v8-internal.h:580
@ kApiIndexedPropertyQueryCallbackTag
Definition: v8-internal.h:600
@ kIcuLocaleTag
Definition: v8-internal.h:639
@ kMessageListenerTag
Definition: v8-internal.h:625
@ kApiIndexedPropertyDeleterCallbackTag
Definition: v8-internal.h:605
@ kTemporalDurationTag
Definition: v8-internal.h:646
@ kLastInterceptorInfoExternalPointerTag
Definition: v8-internal.h:607
@ kIcuRelativeDateTimeFormatterTag
Definition: v8-internal.h:642
@ kWasmWasmStreamingTag
Definition: v8-internal.h:632
@ kNativeContextMicrotaskQueueTag
Definition: v8-internal.h:577
@ kLastMaybeReadOnlyExternalPointerTag
Definition: v8-internal.h:610
@ kLastEmbedderDataTag
Definition: v8-internal.h:581
@ kArrayBufferExtensionTag
Definition: v8-internal.h:661
@ kIcuDateIntervalFormatTag
Definition: v8-internal.h:641
@ kCFunctionInfoTag
Definition: v8-internal.h:624
@ kFirstExternalPointerTag
Definition: v8-internal.h:558
@ kApiNamedPropertyEnumeratorCallbackTag
Definition: v8-internal.h:599
@ kFunctionTemplateInfoCallbackTag
Definition: v8-internal.h:587
@ kTemporalPlainDateTag
Definition: v8-internal.h:648
const int kSmiValueSize
Definition: v8-internal.h:205
constexpr ExternalPointerTagRange kAnyForeignExternalPointerTagRange(kFirstForeignExternalPointerTag, kLastForeignExternalPointerTag)
constexpr bool SmiValuesAre32Bits()
Definition: v8-internal.h:209
TagRange< ExternalPointerTag > ExternalPointerTagRange
Definition: v8-internal.h:671
constexpr IndirectPointerHandle kNullIndirectPointerHandle
Definition: v8-internal.h:748
uintptr_t Address
Definition: v8-internal.h:52
void PerformCastCheck(T *data)
Definition: v8-internal.h:1447
void PrintFunctionCallbackInfo(void *function_callback_info)
constexpr size_t kTrustedPointerTableReservationSize
Definition: v8-internal.h:770
uint32_t ExternalPointerHandle
Definition: v8-internal.h:363
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:844
const int kSmiTag
Definition: v8-internal.h:86
constexpr CodePointerHandle kNullCodePointerHandle
Definition: v8-internal.h:815
Address CppHeapPointer_t
Definition: v8-internal.h:391
constexpr CppHeapPointerHandle kNullCppHeapPointerHandle
Definition: v8-internal.h:395
constexpr int kGarbageCollectionReasonMaxValue
Definition: v8-internal.h:1458
constexpr int kCodePointerTableEntrySize
Definition: v8-internal.h:829
constexpr uint32_t kCodePointerHandleMarker
Definition: v8-internal.h:824
const int kSmiMinValue
Definition: v8-internal.h:206
constexpr bool kHaveIteratorConcept
Definition: v8-internal.h:1510
constexpr int MB
Definition: v8-internal.h:56
constexpr uint64_t kExternalPointerShiftedTagMask
Definition: v8-internal.h:349
constexpr uint64_t kExternalPointerMarkBit
Definition: v8-internal.h:346
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:1431
static void Perform(T *data)
Definition: v8-internal.h:860
Address * next
Definition: v8-internal.h:864
int level
Definition: v8-internal.h:866
Address * limit
Definition: v8-internal.h:865
int sealed_level
Definition: v8-internal.h:867
static constexpr uint32_t kSizeInBytes
Definition: v8-internal.h:861
void Initialize()
Definition: v8-internal.h:869
Definition: v8-internal.h:1525
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
Definition: v8-internal.h:457
constexpr size_t Size() const
Definition: v8-internal.h:479
constexpr bool IsEmpty() const
Definition: v8-internal.h:477
const Tag last
Definition: v8-internal.h:510
constexpr bool operator==(const TagRange other) const
Definition: v8-internal.h:499
constexpr bool Contains(Tag tag) const
Definition: v8-internal.h:487
const Tag first
Definition: v8-internal.h:509
constexpr TagRange()
Definition: v8-internal.h:474
constexpr TagRange(Tag tag)
Definition: v8-internal.h:470
constexpr size_t hash_value() const
Definition: v8-internal.h:503
constexpr TagRange(Tag first, Tag last)
Definition: v8-internal.h:463
constexpr bool Contains(TagRange tag_range) const
Definition: v8-internal.h:495
#define V8_EMBEDDER_DATA_TAG_COUNT
Definition: v8-internal.h:427
#define V8_EXPORT
Definition: v8config.h:855
#define V8_INLINE
Definition: v8config.h:508
#define V8_DEPRECATE_SOON(message)
Definition: v8config.h:622
#define V8_LIKELY(condition)
Definition: v8config.h:669