File indexing completed on 2026-09-20 09:15:48
0001
0002
0003
0004
0005 #ifndef INCLUDE_V8_INTERNAL_H_
0006 #define INCLUDE_V8_INTERNAL_H_
0007
0008 #include <stddef.h>
0009 #include <stdint.h>
0010 #include <string.h>
0011
0012 #include <atomic>
0013 #include <compare>
0014 #include <concepts>
0015 #include <iterator>
0016 #include <limits>
0017 #include <memory>
0018 #include <optional>
0019 #include <type_traits>
0020
0021 #include "v8config.h" // NOLINT(build/include_directory)
0022
0023 namespace v8 {
0024
0025 class Array;
0026 class Context;
0027 class Data;
0028 class Isolate;
0029
0030 namespace internal {
0031
0032 class Heap;
0033 class LocalHeap;
0034 class Isolate;
0035 class IsolateGroup;
0036 class LocalIsolate;
0037
0038 typedef uintptr_t Address;
0039 static constexpr Address kNullAddress = 0;
0040
0041 constexpr int KB = 1024;
0042 constexpr int MB = KB * 1024;
0043 constexpr int GB = MB * 1024;
0044 #ifdef V8_TARGET_ARCH_X64
0045 constexpr size_t TB = size_t{GB} * 1024;
0046 #endif
0047
0048
0049
0050
0051 const int kApiSystemPointerSize = sizeof(void*);
0052 const int kApiDoubleSize = sizeof(double);
0053 const int kApiInt32Size = sizeof(int32_t);
0054 const int kApiInt64Size = sizeof(int64_t);
0055 const int kApiSizetSize = sizeof(size_t);
0056
0057
0058 const int kHeapObjectTag = 1;
0059 const int kWeakHeapObjectTag = 3;
0060 const int kHeapObjectTagSize = 2;
0061 const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
0062 const intptr_t kHeapObjectReferenceTagMask = 1 << (kHeapObjectTagSize - 1);
0063
0064
0065
0066
0067 const int kForwardingTag = 0;
0068 const int kForwardingTagSize = 2;
0069 const intptr_t kForwardingTagMask = (1 << kForwardingTagSize) - 1;
0070
0071
0072 const int kSmiTag = 0;
0073 const int kSmiTagSize = 1;
0074 const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
0075
0076 template <size_t tagged_ptr_size>
0077 struct SmiTagging;
0078
0079 constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1};
0080 constexpr uintptr_t kUintptrAllBitsSet =
0081 static_cast<uintptr_t>(kIntptrAllBitsSet);
0082
0083
0084 template <>
0085 struct SmiTagging<4> {
0086 enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
0087
0088 static constexpr intptr_t kSmiMinValue =
0089 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
0090 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
0091
0092 V8_INLINE static constexpr int SmiToInt(Address value) {
0093 int shift_bits = kSmiTagSize + kSmiShiftSize;
0094
0095 return static_cast<int32_t>(static_cast<uint32_t>(value)) >> shift_bits;
0096 }
0097
0098 template <class T, typename std::enable_if_t<std::is_integral_v<T> &&
0099 std::is_signed_v<T>>* = nullptr>
0100 V8_INLINE static constexpr bool IsValidSmi(T value) {
0101
0102
0103
0104 return (static_cast<uintptr_t>(value) -
0105 static_cast<uintptr_t>(kSmiMinValue)) <=
0106 (static_cast<uintptr_t>(kSmiMaxValue) -
0107 static_cast<uintptr_t>(kSmiMinValue));
0108 }
0109
0110 template <class T,
0111 typename std::enable_if_t<std::is_integral_v<T> &&
0112 std::is_unsigned_v<T>>* = nullptr>
0113 V8_INLINE static constexpr bool IsValidSmi(T value) {
0114 static_assert(kSmiMaxValue <= std::numeric_limits<uintptr_t>::max());
0115 return value <= static_cast<uintptr_t>(kSmiMaxValue);
0116 }
0117
0118
0119
0120 V8_INLINE static constexpr bool IsValidSmi(int64_t value) {
0121 return (static_cast<uint64_t>(value) -
0122 static_cast<uint64_t>(kSmiMinValue)) <=
0123 (static_cast<uint64_t>(kSmiMaxValue) -
0124 static_cast<uint64_t>(kSmiMinValue));
0125 }
0126
0127 V8_INLINE static constexpr bool IsValidSmi(uint64_t value) {
0128 static_assert(kSmiMaxValue <= std::numeric_limits<uint64_t>::max());
0129 return value <= static_cast<uint64_t>(kSmiMaxValue);
0130 }
0131 };
0132
0133
0134 template <>
0135 struct SmiTagging<8> {
0136 enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
0137
0138 static constexpr intptr_t kSmiMinValue =
0139 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
0140 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
0141
0142 V8_INLINE static constexpr int SmiToInt(Address value) {
0143 int shift_bits = kSmiTagSize + kSmiShiftSize;
0144
0145 return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
0146 }
0147
0148 template <class T, typename std::enable_if_t<std::is_integral_v<T> &&
0149 std::is_signed_v<T>>* = nullptr>
0150 V8_INLINE static constexpr bool IsValidSmi(T value) {
0151
0152 return std::numeric_limits<int32_t>::min() <= value &&
0153 value <= std::numeric_limits<int32_t>::max();
0154 }
0155
0156 template <class T,
0157 typename std::enable_if_t<std::is_integral_v<T> &&
0158 std::is_unsigned_v<T>>* = nullptr>
0159 V8_INLINE static constexpr bool IsValidSmi(T value) {
0160 return value <= std::numeric_limits<int32_t>::max();
0161 }
0162 };
0163
0164 #ifdef V8_COMPRESS_POINTERS
0165
0166
0167 constexpr size_t kPtrComprCageReservationSize = size_t{1} << 32;
0168 constexpr size_t kPtrComprCageBaseAlignment = size_t{1} << 32;
0169
0170 static_assert(
0171 kApiSystemPointerSize == kApiInt64Size,
0172 "Pointer compression can be enabled only for 64-bit architectures");
0173 const int kApiTaggedSize = kApiInt32Size;
0174 #else
0175 const int kApiTaggedSize = kApiSystemPointerSize;
0176 #endif
0177
0178 constexpr bool PointerCompressionIsEnabled() {
0179 return kApiTaggedSize != kApiSystemPointerSize;
0180 }
0181
0182 #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
0183 using PlatformSmiTagging = SmiTagging<kApiInt32Size>;
0184 #else
0185 using PlatformSmiTagging = SmiTagging<kApiTaggedSize>;
0186 #endif
0187
0188
0189
0190 const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
0191 const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
0192 const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue);
0193 const int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue);
0194 constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
0195 constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
0196 constexpr bool Is64() { return kApiSystemPointerSize == sizeof(int64_t); }
0197
0198 V8_INLINE static constexpr Address IntToSmi(int value) {
0199 return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
0200 kSmiTag;
0201 }
0202
0203
0204
0205
0206 constexpr bool SandboxIsEnabled() {
0207 #ifdef V8_ENABLE_SANDBOX
0208 return true;
0209 #else
0210 return false;
0211 #endif
0212 }
0213
0214
0215
0216 using SandboxedPointer_t = Address;
0217
0218 #ifdef V8_ENABLE_SANDBOX
0219
0220
0221 #if defined(V8_TARGET_OS_ANDROID)
0222
0223
0224
0225 constexpr size_t kSandboxSizeLog2 = 37;
0226 #elif defined(V8_TARGET_OS_IOS)
0227
0228
0229
0230
0231 constexpr size_t kSandboxSizeLog2 = 34;
0232 #else
0233
0234 constexpr size_t kSandboxSizeLog2 = 40;
0235 #endif
0236 constexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2;
0237
0238
0239
0240
0241
0242
0243 constexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment;
0244
0245
0246
0247
0248
0249 constexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2;
0250
0251
0252
0253
0254
0255
0256
0257 constexpr size_t kSandboxGuardRegionSize = 32ULL * GB + 4ULL * GB;
0258
0259 static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
0260 "The size of the guard regions around the sandbox must be a "
0261 "multiple of its required alignment.");
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 constexpr size_t kSandboxMinimumReservationSize = 8ULL * GB;
0274
0275 static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
0276 "The minimum reservation size for a sandbox must be larger than "
0277 "the pointer compression cage contained within it.");
0278
0279
0280
0281
0282
0283 constexpr size_t kMaxSafeBufferSizeForSandbox = 32ULL * GB - 1;
0284 static_assert(kMaxSafeBufferSizeForSandbox <= kSandboxGuardRegionSize,
0285 "The maximum allowed buffer size must not be larger than the "
0286 "sandbox's guard regions");
0287
0288 constexpr size_t kBoundedSizeShift = 29;
0289 static_assert(1ULL << (64 - kBoundedSizeShift) ==
0290 kMaxSafeBufferSizeForSandbox + 1,
0291 "The maximum size of a BoundedSize must be synchronized with the "
0292 "kMaxSafeBufferSizeForSandbox");
0293
0294 #endif
0295
0296 #ifdef V8_COMPRESS_POINTERS
0297
0298 #ifdef V8_TARGET_OS_ANDROID
0299
0300
0301
0302
0303
0304 constexpr size_t kExternalPointerTableReservationSize = 256 * MB;
0305
0306
0307
0308
0309
0310 constexpr uint32_t kExternalPointerIndexShift = 7;
0311 #elif defined(V8_TARGET_OS_IOS)
0312
0313
0314
0315
0316 constexpr size_t kExternalPointerTableReservationSize = 128 * MB;
0317 constexpr uint32_t kExternalPointerIndexShift = 8;
0318 #else
0319 constexpr size_t kExternalPointerTableReservationSize = 512 * MB;
0320 constexpr uint32_t kExternalPointerIndexShift = 6;
0321 #endif
0322
0323
0324 constexpr int kExternalPointerTableEntrySize = 8;
0325 constexpr int kExternalPointerTableEntrySizeLog2 = 3;
0326 constexpr size_t kMaxExternalPointers =
0327 kExternalPointerTableReservationSize / kExternalPointerTableEntrySize;
0328 static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers,
0329 "kExternalPointerTableReservationSize and "
0330 "kExternalPointerIndexShift don't match");
0331
0332 #else
0333
0334
0335 constexpr size_t kMaxExternalPointers = 0;
0336
0337 #endif
0338
0339 constexpr uint64_t kExternalPointerMarkBit = 1ULL << 48;
0340 constexpr uint64_t kExternalPointerTagShift = 49;
0341 constexpr uint64_t kExternalPointerTagMask = 0x00fe000000000000ULL;
0342 constexpr uint64_t kExternalPointerShiftedTagMask =
0343 kExternalPointerTagMask >> kExternalPointerTagShift;
0344 static_assert(kExternalPointerShiftedTagMask << kExternalPointerTagShift ==
0345 kExternalPointerTagMask);
0346 constexpr uint64_t kExternalPointerTagAndMarkbitMask = 0x00ff000000000000ULL;
0347 constexpr uint64_t kExternalPointerPayloadMask = 0xff00ffffffffffffULL;
0348
0349
0350
0351
0352
0353
0354
0355
0356 using ExternalPointerHandle = uint32_t;
0357
0358
0359
0360
0361 #ifdef V8_ENABLE_SANDBOX
0362 using ExternalPointer_t = ExternalPointerHandle;
0363 #else
0364 using ExternalPointer_t = Address;
0365 #endif
0366
0367 constexpr ExternalPointer_t kNullExternalPointer = 0;
0368 constexpr ExternalPointerHandle kNullExternalPointerHandle = 0;
0369
0370
0371
0372
0373
0374
0375 using CppHeapPointerHandle = uint32_t;
0376
0377
0378
0379
0380
0381 #ifdef V8_COMPRESS_POINTERS
0382 using CppHeapPointer_t = CppHeapPointerHandle;
0383 #else
0384 using CppHeapPointer_t = Address;
0385 #endif
0386
0387 constexpr CppHeapPointer_t kNullCppHeapPointer = 0;
0388 constexpr CppHeapPointerHandle kNullCppHeapPointerHandle = 0;
0389
0390 constexpr uint64_t kCppHeapPointerMarkBit = 1ULL;
0391 constexpr uint64_t kCppHeapPointerTagShift = 1;
0392 constexpr uint64_t kCppHeapPointerPayloadShift = 16;
0393
0394 #ifdef V8_COMPRESS_POINTERS
0395
0396
0397
0398 constexpr size_t kCppHeapPointerTableReservationSize =
0399 kExternalPointerTableReservationSize;
0400 constexpr uint32_t kCppHeapPointerIndexShift = kExternalPointerIndexShift;
0401
0402 constexpr int kCppHeapPointerTableEntrySize = 8;
0403 constexpr int kCppHeapPointerTableEntrySizeLog2 = 3;
0404 constexpr size_t kMaxCppHeapPointers =
0405 kCppHeapPointerTableReservationSize / kCppHeapPointerTableEntrySize;
0406 static_assert((1 << (32 - kCppHeapPointerIndexShift)) == kMaxCppHeapPointers,
0407 "kCppHeapPointerTableReservationSize and "
0408 "kCppHeapPointerIndexShift don't match");
0409
0410 #else
0411
0412
0413 constexpr size_t kMaxCppHeapPointers = 0;
0414
0415 #endif
0416
0417
0418
0419
0420 #define V8_EMBEDDER_DATA_TAG_COUNT 15
0421
0422
0423
0424
0425 #define V8_EXTERNAL_POINTER_TAG_COUNT 40
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 template <typename Tag>
0471 struct TagRange {
0472 static_assert(std::is_enum_v<Tag> &&
0473 std::is_same_v<std::underlying_type_t<Tag>, uint16_t>,
0474 "Tag parameter must be an enum with base type uint16_t");
0475
0476
0477 constexpr TagRange(Tag first, Tag last) : first(first), last(last) {
0478 #ifdef V8_ENABLE_CHECKS
0479
0480 #if V8_HAS_BUILTIN_UNREACHABLE
0481 if (first > last) __builtin_unreachable();
0482 #elif defined(_MSC_VER)
0483 if (first > last) __assume(0);
0484 #endif
0485 #endif
0486 }
0487
0488
0489
0490
0491
0492
0493 constexpr TagRange(Tag tag)
0494 : first(tag), last(tag) {}
0495
0496
0497 constexpr TagRange() : TagRange(static_cast<Tag>(0)) {}
0498
0499
0500 constexpr bool IsEmpty() const { return first == 0 && last == 0; }
0501
0502 constexpr size_t Size() const {
0503 if (IsEmpty()) {
0504 return 0;
0505 } else {
0506 return last - first + 1;
0507 }
0508 }
0509
0510 constexpr bool Contains(Tag tag) const {
0511
0512
0513
0514 return static_cast<uint32_t>(tag) - static_cast<uint32_t>(first) <=
0515 static_cast<uint32_t>(last) - static_cast<uint32_t>(first);
0516 }
0517
0518 constexpr bool Contains(TagRange tag_range) const {
0519 return tag_range.first >= first && tag_range.last <= last;
0520 }
0521
0522 constexpr bool operator==(const TagRange other) const {
0523 return first == other.first && last == other.last;
0524 }
0525
0526 constexpr size_t hash_value() const {
0527 static_assert(std::is_same_v<std::underlying_type_t<Tag>, uint16_t>);
0528 return (static_cast<size_t>(first) << 16) | last;
0529 }
0530
0531
0532 Tag first;
0533 Tag last;
0534 };
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580 enum ExternalPointerTag : uint16_t {
0581 kFirstExternalPointerTag = 0,
0582 kExternalPointerNullTag = 0,
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592 kFirstSharedExternalPointerTag,
0593 kWaiterQueueNodeTag = kFirstSharedExternalPointerTag,
0594 kExternalStringResourceTag,
0595 kExternalStringResourceDataTag,
0596 kLastSharedExternalPointerTag = kExternalStringResourceDataTag,
0597
0598
0599
0600 kNativeContextMicrotaskQueueTag,
0601
0602
0603 kFirstEmbedderDataTag,
0604 kLastEmbedderDataTag = kFirstEmbedderDataTag + V8_EMBEDDER_DATA_TAG_COUNT - 1,
0605
0606
0607 kFirstExternalTypeTag,
0608 kLastExternalTypeTag =
0609 kFirstExternalTypeTag + V8_EXTERNAL_POINTER_TAG_COUNT - 1,
0610
0611
0612
0613 kFastApiExternalTypeTag = kLastExternalTypeTag,
0614 kFirstMaybeReadOnlyExternalPointerTag,
0615 kFunctionTemplateInfoCallbackTag = kFirstMaybeReadOnlyExternalPointerTag,
0616 kAccessorInfoGetterTag,
0617 kAccessorInfoSetterTag,
0618
0619
0620 kFirstInterceptorInfoExternalPointerTag,
0621 kApiNamedPropertyQueryCallbackTag = kFirstInterceptorInfoExternalPointerTag,
0622 kApiNamedPropertyGetterCallbackTag,
0623 kApiNamedPropertySetterCallbackTag,
0624 kApiNamedPropertyDescriptorCallbackTag,
0625 kApiNamedPropertyDefinerCallbackTag,
0626 kApiNamedPropertyDeleterCallbackTag,
0627 kApiNamedPropertyEnumeratorCallbackTag,
0628 kApiIndexedPropertyQueryCallbackTag,
0629 kApiIndexedPropertyGetterCallbackTag,
0630 kApiIndexedPropertySetterCallbackTag,
0631 kApiIndexedPropertyDescriptorCallbackTag,
0632 kApiIndexedPropertyDefinerCallbackTag,
0633 kApiIndexedPropertyDeleterCallbackTag,
0634 kApiIndexedPropertyEnumeratorCallbackTag,
0635 kLastInterceptorInfoExternalPointerTag =
0636 kApiIndexedPropertyEnumeratorCallbackTag,
0637
0638 kLastMaybeReadOnlyExternalPointerTag = kLastInterceptorInfoExternalPointerTag,
0639
0640 kWasmStackMemoryTag,
0641
0642
0643 kFirstForeignExternalPointerTag,
0644 kGenericForeignTag = kFirstForeignExternalPointerTag,
0645
0646 kApiAccessCheckCallbackTag,
0647 kApiAbortScriptExecutionCallbackTag,
0648 kSyntheticModuleTag,
0649 kMicrotaskCallbackTag,
0650 kMicrotaskCallbackDataTag,
0651 kCFunctionTag,
0652 kCFunctionInfoTag,
0653 kMessageListenerTag,
0654 kWaiterQueueForeignTag,
0655
0656
0657 kFirstManagedResourceTag,
0658 kFirstManagedExternalPointerTag = kFirstManagedResourceTag,
0659 kGenericManagedTag = kFirstManagedExternalPointerTag,
0660 kWasmWasmStreamingTag,
0661 kWasmFuncDataTag,
0662 kWasmManagedDataTag,
0663 kWasmNativeModuleTag,
0664 kBackingStoreTag,
0665 kIcuBreakIteratorTag,
0666 kIcuUnicodeStringTag,
0667 kIcuListFormatterTag,
0668 kIcuLocaleTag,
0669 kIcuSimpleDateFormatTag,
0670 kIcuDateIntervalFormatTag,
0671 kIcuRelativeDateTimeFormatterTag,
0672 kIcuLocalizedNumberFormatterTag,
0673 kIcuPluralRulesTag,
0674 kIcuCollatorTag,
0675 kTemporalDurationTag,
0676 kTemporalInstantTag,
0677 kTemporalPlainDateTag,
0678 kTemporalPlainTimeTag,
0679 kTemporalPlainDateTimeTag,
0680 kTemporalPlainYearMonthTag,
0681 kTemporalPlainMonthDayTag,
0682 kTemporalZonedDateTimeTag,
0683 kDisplayNamesInternalTag,
0684 kD8WorkerTag,
0685 kD8ModuleEmbedderDataTag,
0686 kLastForeignExternalPointerTag = kD8ModuleEmbedderDataTag,
0687 kLastManagedExternalPointerTag = kLastForeignExternalPointerTag,
0688
0689
0690 kArrayBufferExtensionTag,
0691 kLastManagedResourceTag = kArrayBufferExtensionTag,
0692
0693 kExternalPointerZappedEntryTag = 0x7d,
0694 kExternalPointerEvacuationEntryTag = 0x7e,
0695 kExternalPointerFreeEntryTag = 0x7f,
0696
0697 kLastExternalPointerTag = 0x7f,
0698 };
0699
0700 using ExternalPointerTagRange = TagRange<ExternalPointerTag>;
0701
0702 constexpr ExternalPointerTagRange kAnyExternalPointerTagRange(
0703 kFirstExternalPointerTag, kLastExternalPointerTag);
0704 constexpr ExternalPointerTagRange kAnySharedExternalPointerTagRange(
0705 kFirstSharedExternalPointerTag, kLastSharedExternalPointerTag);
0706 constexpr ExternalPointerTagRange kAnyForeignExternalPointerTagRange(
0707 kFirstForeignExternalPointerTag, kLastForeignExternalPointerTag);
0708 constexpr ExternalPointerTagRange kAnyInterceptorInfoExternalPointerTagRange(
0709 kFirstInterceptorInfoExternalPointerTag,
0710 kLastInterceptorInfoExternalPointerTag);
0711 constexpr ExternalPointerTagRange kAnyManagedExternalPointerTagRange(
0712 kFirstManagedExternalPointerTag, kLastManagedExternalPointerTag);
0713 constexpr ExternalPointerTagRange kAnyMaybeReadOnlyExternalPointerTagRange(
0714 kFirstMaybeReadOnlyExternalPointerTag,
0715 kLastMaybeReadOnlyExternalPointerTag);
0716 constexpr ExternalPointerTagRange kAnyManagedResourceExternalPointerTag(
0717 kFirstManagedResourceTag, kLastManagedResourceTag);
0718
0719
0720
0721 V8_INLINE static constexpr bool IsSharedExternalPointerType(
0722 ExternalPointerTagRange tag_range) {
0723 return kAnySharedExternalPointerTagRange.Contains(tag_range);
0724 }
0725
0726
0727
0728
0729 V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
0730 ExternalPointerTagRange tag_range) {
0731 return kAnyMaybeReadOnlyExternalPointerTagRange.Contains(tag_range);
0732 }
0733
0734
0735
0736
0737
0738 V8_INLINE static constexpr bool IsManagedExternalPointerType(
0739 ExternalPointerTagRange tag_range) {
0740 return kAnyManagedResourceExternalPointerTag.Contains(tag_range);
0741 }
0742
0743
0744
0745
0746
0747
0748
0749
0750 V8_INLINE static constexpr bool ExternalPointerCanBeEmpty(
0751 ExternalPointerTagRange tag_range) {
0752 return tag_range.Contains(kArrayBufferExtensionTag) ||
0753 (tag_range.first <= kLastEmbedderDataTag &&
0754 kFirstEmbedderDataTag <= tag_range.last) ||
0755 kAnyInterceptorInfoExternalPointerTagRange.Contains(tag_range);
0756 }
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774 using IndirectPointerHandle = uint32_t;
0775
0776
0777 constexpr IndirectPointerHandle kNullIndirectPointerHandle = 0;
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794 using TrustedPointerHandle = IndirectPointerHandle;
0795
0796
0797
0798
0799 constexpr size_t kTrustedPointerTableReservationSize = 64 * MB;
0800
0801
0802
0803 constexpr uint32_t kTrustedPointerHandleShift = 9;
0804
0805
0806 constexpr TrustedPointerHandle kNullTrustedPointerHandle =
0807 kNullIndirectPointerHandle;
0808
0809
0810 constexpr int kTrustedPointerTableEntrySize = 8;
0811 constexpr int kTrustedPointerTableEntrySizeLog2 = 3;
0812 constexpr size_t kMaxTrustedPointers =
0813 kTrustedPointerTableReservationSize / kTrustedPointerTableEntrySize;
0814 static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
0815 "kTrustedPointerTableReservationSize and "
0816 "kTrustedPointerHandleShift don't match");
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832 using CodePointerHandle = IndirectPointerHandle;
0833
0834
0835
0836
0837 constexpr size_t kCodePointerTableReservationSize = 128 * MB;
0838
0839
0840
0841 constexpr uint32_t kCodePointerHandleShift = 9;
0842
0843
0844 constexpr CodePointerHandle kNullCodePointerHandle = kNullIndirectPointerHandle;
0845
0846
0847
0848
0849
0850
0851
0852
0853 constexpr uint32_t kCodePointerHandleMarker = 0x1;
0854 static_assert(kCodePointerHandleShift > 0);
0855 static_assert(kTrustedPointerHandleShift > 0);
0856
0857
0858 constexpr int kCodePointerTableEntrySize = 16;
0859 constexpr int kCodePointerTableEntrySizeLog2 = 4;
0860 constexpr size_t kMaxCodePointers =
0861 kCodePointerTableReservationSize / kCodePointerTableEntrySize;
0862 static_assert(
0863 (1 << (32 - kCodePointerHandleShift)) == kMaxCodePointers,
0864 "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
0865
0866 constexpr int kCodePointerTableEntryEntrypointOffset = 0;
0867 constexpr int kCodePointerTableEntryCodeObjectOffset = 8;
0868
0869
0870
0871 constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace = true;
0872 constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace = false;
0873 constexpr bool kAllCodeObjectsLiveInTrustedSpace =
0874 kRuntimeGeneratedCodeObjectsLiveInTrustedSpace &&
0875 kBuiltinCodeObjectsLiveInTrustedSpace;
0876
0877
0878
0879 V8_DEPRECATE_SOON(
0880 "Use GetCurrentIsolate() instead, which is guaranteed to return the same "
0881 "isolate since https://crrev.com/c/6458560.")
0882 V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
0883
0884
0885
0886
0887 V8_EXPORT bool ShouldThrowOnError(internal::Isolate* isolate);
0888
0889 struct HandleScopeData final {
0890 static constexpr uint32_t kSizeInBytes =
0891 2 * kApiSystemPointerSize + 2 * kApiInt32Size;
0892
0893 Address* next;
0894 Address* limit;
0895 int level;
0896 int sealed_level;
0897
0898 void Initialize() {
0899 next = limit = nullptr;
0900 sealed_level = level = 0;
0901 }
0902 };
0903
0904 static_assert(HandleScopeData::kSizeInBytes == sizeof(HandleScopeData));
0905
0906
0907
0908
0909
0910
0911 class Internals {
0912 #ifdef V8_MAP_PACKING
0913 V8_INLINE static constexpr Address UnpackMapWord(Address mapword) {
0914
0915 return mapword ^ kMapWordXorMask;
0916 }
0917 #endif
0918
0919 public:
0920
0921
0922 static const int kHeapObjectMapOffset = 0;
0923 static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiInt32Size;
0924 static const int kStringResourceOffset =
0925 1 * kApiTaggedSize + 2 * kApiInt32Size;
0926
0927 static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
0928 static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
0929 #ifdef V8_COMPRESS_POINTERS
0930 static const int kJSAPIObjectWithEmbedderSlotsHeaderSize =
0931 kJSObjectHeaderSize + kApiInt32Size;
0932 #else
0933 static const int kJSAPIObjectWithEmbedderSlotsHeaderSize =
0934 kJSObjectHeaderSize + kApiTaggedSize;
0935 #endif
0936 static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
0937 static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
0938 static const int kEmbedderDataSlotSize = kApiSystemPointerSize;
0939 #ifdef V8_ENABLE_SANDBOX
0940 static const int kEmbedderDataSlotExternalPointerOffset = kApiTaggedSize;
0941 #else
0942 static const int kEmbedderDataSlotExternalPointerOffset = 0;
0943 #endif
0944 static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize;
0945 static const int kStringRepresentationAndEncodingMask = 0x0f;
0946 static const int kStringEncodingMask = 0x8;
0947 static const int kExternalTwoByteRepresentationTag = 0x02;
0948 static const int kExternalOneByteRepresentationTag = 0x0a;
0949
0950
0951 static const int kCallbackInfoDataOffset = 1 * kApiTaggedSize;
0952
0953 static const uint32_t kNumIsolateDataSlots = 4;
0954 static const int kStackGuardSize = 8 * kApiSystemPointerSize;
0955 static const int kNumberOfBooleanFlags = 6;
0956 static const int kErrorMessageParamSize = 1;
0957 static const int kTablesAlignmentPaddingSize = 1;
0958 static const int kRegExpStaticResultOffsetsVectorSize = kApiSystemPointerSize;
0959 static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize;
0960 static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
0961 static const int kLinearAllocationAreaSize = 3 * kApiSystemPointerSize;
0962 static const int kThreadLocalTopSize = 29 * kApiSystemPointerSize;
0963 static const int kHandleScopeDataSize =
0964 2 * kApiSystemPointerSize + 2 * kApiInt32Size;
0965
0966
0967 static const int kExternalEntityTableBasePointerOffset = 0;
0968 static const int kSegmentedTableSegmentPoolSize = 4;
0969 static const int kExternalEntityTableSize =
0970 4 * kApiSystemPointerSize +
0971 kSegmentedTableSegmentPoolSize * sizeof(uint32_t);
0972
0973
0974 static const int kIsolateCageBaseOffset = 0;
0975 static const int kIsolateStackGuardOffset =
0976 kIsolateCageBaseOffset + kApiSystemPointerSize;
0977 static const int kVariousBooleanFlagsOffset =
0978 kIsolateStackGuardOffset + kStackGuardSize;
0979 static const int kErrorMessageParamOffset =
0980 kVariousBooleanFlagsOffset + kNumberOfBooleanFlags;
0981 static const int kBuiltinTier0EntryTableOffset =
0982 kErrorMessageParamOffset + kErrorMessageParamSize +
0983 kTablesAlignmentPaddingSize + kRegExpStaticResultOffsetsVectorSize;
0984 static const int kBuiltinTier0TableOffset =
0985 kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize;
0986 static const int kNewAllocationInfoOffset =
0987 kBuiltinTier0TableOffset + kBuiltinTier0TableSize;
0988 static const int kOldAllocationInfoOffset =
0989 kNewAllocationInfoOffset + kLinearAllocationAreaSize;
0990 static const int kLastYoungAllocationOffset =
0991 kOldAllocationInfoOffset + kApiSystemPointerSize;
0992
0993 static const int kFastCCallAlignmentPaddingSize =
0994 kApiSystemPointerSize == 8 ? 5 * kApiSystemPointerSize
0995 : 1 * kApiSystemPointerSize;
0996 static const int kIsolateFastCCallCallerPcOffset =
0997 kLastYoungAllocationOffset + kLinearAllocationAreaSize +
0998 kFastCCallAlignmentPaddingSize;
0999 static const int kIsolateFastCCallCallerFpOffset =
1000 kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize;
1001 static const int kIsolateFastApiCallTargetOffset =
1002 kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
1003 static const int kIsolateLongTaskStatsCounterOffset =
1004 kIsolateFastApiCallTargetOffset + kApiSystemPointerSize;
1005 static const int kIsolateThreadLocalTopOffset =
1006 kIsolateLongTaskStatsCounterOffset + kApiSizetSize;
1007 static const int kIsolateHandleScopeDataOffset =
1008 kIsolateThreadLocalTopOffset + kThreadLocalTopSize;
1009 static const int kIsolateEmbedderDataOffset =
1010 kIsolateHandleScopeDataOffset + kHandleScopeDataSize;
1011 #ifdef V8_COMPRESS_POINTERS
1012 static const int kIsolateExternalPointerTableOffset =
1013 kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
1014 static const int kIsolateSharedExternalPointerTableAddressOffset =
1015 kIsolateExternalPointerTableOffset + kExternalEntityTableSize;
1016 static const int kIsolateCppHeapPointerTableOffset =
1017 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
1018 #ifdef V8_ENABLE_SANDBOX
1019 static const int kIsolateTrustedCageBaseOffset =
1020 kIsolateCppHeapPointerTableOffset + kExternalEntityTableSize;
1021 static const int kIsolateTrustedPointerTableOffset =
1022 kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
1023 static const int kIsolateSharedTrustedPointerTableAddressOffset =
1024 kIsolateTrustedPointerTableOffset + kExternalEntityTableSize;
1025 static const int kIsolateTrustedPointerPublishingScopeOffset =
1026 kIsolateSharedTrustedPointerTableAddressOffset + kApiSystemPointerSize;
1027 static const int kIsolateCodePointerTableBaseAddressOffset =
1028 kIsolateTrustedPointerPublishingScopeOffset + kApiSystemPointerSize;
1029 static const int kIsolateJSDispatchTableOffset =
1030 kIsolateCodePointerTableBaseAddressOffset + kApiSystemPointerSize;
1031 #else
1032 static const int kIsolateJSDispatchTableOffset =
1033 kIsolateCppHeapPointerTableOffset + kExternalEntityTableSize;
1034 #endif
1035 #else
1036 static const int kIsolateJSDispatchTableOffset =
1037 kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
1038 #endif
1039 static const int kIsolateApiCallbackThunkArgumentOffset =
1040 kIsolateJSDispatchTableOffset + kExternalEntityTableSize;
1041 static const int kIsolateRegexpExecVectorArgumentOffset =
1042 kIsolateApiCallbackThunkArgumentOffset + kApiSystemPointerSize;
1043 static const int kContinuationPreservedEmbedderDataOffset =
1044 kIsolateRegexpExecVectorArgumentOffset + kApiSystemPointerSize;
1045 static const int kIsolateRootsOffset =
1046 kContinuationPreservedEmbedderDataOffset + kApiSystemPointerSize;
1047
1048 #if V8_TARGET_ARCH_PPC64
1049 static constexpr int kFrameCPSlotCount = 1;
1050 #else
1051 static constexpr int kFrameCPSlotCount = 0;
1052 #endif
1053
1054 #if V8_TARGET_ARCH_ARM64
1055
1056 static constexpr int kSPAlignmentSlotCount = 1;
1057 #else
1058 static constexpr int kSPAlignmentSlotCount = 0;
1059 #endif
1060
1061 static const int kFrameTypeApiCallExit = 18;
1062 static const int kFrameTypeApiConstructExit = 19;
1063 static const int kFrameTypeApiNamedAccessorExit = 20;
1064 static const int kFrameTypeApiIndexedAccessorExit = 21;
1065
1066
1067 static const int kDisallowGarbageCollectionAlign = alignof(uint32_t);
1068 static const int kDisallowGarbageCollectionSize = sizeof(uint32_t);
1069
1070 #if V8_STATIC_ROOTS_BOOL
1071
1072
1073 #define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
1074 V(UndefinedValue, 0x11) \
1075 V(NullValue, 0x2d) \
1076 V(TrueValue, 0x71) \
1077 V(FalseValue, 0x55) \
1078 V(EmptyString, 0x49) \
1079 \
1080 \
1081 V(TheHoleValue, kBuildDependentTheHoleValue)
1082
1083 using Tagged_t = uint32_t;
1084 struct StaticReadOnlyRoot {
1085 #ifdef V8_ENABLE_WEBASSEMBLY
1086 static constexpr Tagged_t kBuildDependentTheHoleValue = 0x2fffd;
1087 #else
1088 static constexpr Tagged_t kBuildDependentTheHoleValue = 0xfffd;
1089 #endif
1090
1091 #define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
1092 EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
1093 #undef DEF_ROOT
1094
1095
1096 static constexpr Tagged_t kStringMapLowerBound = 0;
1097 static constexpr Tagged_t kStringMapUpperBound = 0x425;
1098
1099 #define PLUSONE(...) +1
1100 static constexpr size_t kNumberOfExportedStaticRoots =
1101 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
1102 #undef PLUSONE
1103 };
1104
1105 #endif
1106
1107 static const int kUndefinedValueRootIndex = 0;
1108 static const int kTheHoleValueRootIndex = 1;
1109 static const int kNullValueRootIndex = 2;
1110 static const int kTrueValueRootIndex = 3;
1111 static const int kFalseValueRootIndex = 4;
1112 static const int kEmptyStringRootIndex = 5;
1113
1114 static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
1115 static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
1116 static const int kNodeStateMask = 0x3;
1117 static const int kNodeStateIsWeakValue = 2;
1118
1119 static const int kFirstNonstringType = 0x80;
1120 static const int kOddballType = 0x83;
1121 static const int kForeignType = 0xcc;
1122 static const int kJSSpecialApiObjectType = 0x410;
1123 static const int kJSObjectType = 0x421;
1124 static const int kFirstJSApiObjectType = 0x422;
1125 static const int kLastJSApiObjectType = 0x80A;
1126
1127
1128 static const int kFirstEmbedderJSApiObjectType = 0;
1129 static const int kLastEmbedderJSApiObjectType =
1130 kLastJSApiObjectType - kFirstJSApiObjectType;
1131
1132 static const int kUndefinedOddballKind = 4;
1133 static const int kNullOddballKind = 3;
1134
1135
1136
1137 static const int kDontThrow = 0;
1138 static const int kThrowOnError = 1;
1139 static const int kInferShouldThrowMode = 2;
1140
1141
1142
1143 static constexpr size_t kExternalAllocationSoftLimit = 64 * 1024 * 1024;
1144
1145 #ifdef V8_MAP_PACKING
1146 static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
1147
1148 static const uintptr_t kMapWordSignature = 0b10;
1149
1150
1151
1152
1153 static const int kMapWordXorMask = 0b11;
1154 #endif
1155
1156 V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
1157 V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
1158 #ifdef V8_ENABLE_CHECKS
1159 CheckInitializedImpl(isolate);
1160 #endif
1161 }
1162
1163 V8_INLINE static constexpr bool HasHeapObjectTag(Address value) {
1164 return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
1165 }
1166
1167 V8_INLINE static constexpr int SmiValue(Address value) {
1168 return PlatformSmiTagging::SmiToInt(value);
1169 }
1170
1171 V8_INLINE static constexpr Address AddressToSmi(Address value) {
1172 return (value << (kSmiTagSize + PlatformSmiTagging::kSmiShiftSize)) |
1173 kSmiTag;
1174 }
1175
1176 V8_INLINE static constexpr Address IntToSmi(int value) {
1177 return AddressToSmi(static_cast<Address>(value));
1178 }
1179
1180 template <typename T,
1181 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1182 V8_INLINE static constexpr Address IntegralToSmi(T value) {
1183 return AddressToSmi(static_cast<Address>(value));
1184 }
1185
1186 template <typename T,
1187 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1188 V8_INLINE static constexpr bool IsValidSmi(T value) {
1189 return PlatformSmiTagging::IsValidSmi(value);
1190 }
1191
1192 template <typename T,
1193 typename std::enable_if_t<std::is_integral_v<T>>* = nullptr>
1194 static constexpr std::optional<Address> TryIntegralToSmi(T value) {
1195 if (V8_LIKELY(PlatformSmiTagging::IsValidSmi(value))) {
1196 return {AddressToSmi(static_cast<Address>(value))};
1197 }
1198 return {};
1199 }
1200
1201 #if V8_STATIC_ROOTS_BOOL
1202 V8_INLINE static bool is_identical(Address obj, Tagged_t constant) {
1203 return static_cast<Tagged_t>(obj) == constant;
1204 }
1205
1206 V8_INLINE static bool CheckInstanceMapRange(Address obj, Tagged_t first_map,
1207 Tagged_t last_map) {
1208 auto map = ReadRawField<Tagged_t>(obj, kHeapObjectMapOffset);
1209 #ifdef V8_MAP_PACKING
1210 map = UnpackMapWord(map);
1211 #endif
1212 return map >= first_map && map <= last_map;
1213 }
1214 #endif
1215
1216 V8_INLINE static int GetInstanceType(Address obj) {
1217 Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
1218 #ifdef V8_MAP_PACKING
1219 map = UnpackMapWord(map);
1220 #endif
1221 return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
1222 }
1223
1224 V8_INLINE static Address LoadMap(Address obj) {
1225 if (!HasHeapObjectTag(obj)) return kNullAddress;
1226 Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
1227 #ifdef V8_MAP_PACKING
1228 map = UnpackMapWord(map);
1229 #endif
1230 return map;
1231 }
1232
1233 V8_INLINE static int GetOddballKind(Address obj) {
1234 return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
1235 }
1236
1237 V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
1238 int representation = (instance_type & kStringRepresentationAndEncodingMask);
1239 return representation == kExternalTwoByteRepresentationTag;
1240 }
1241
1242 V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
1243 static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
1244 static_assert(kJSObjectType < kLastJSApiObjectType);
1245 static_assert(kFirstJSApiObjectType < kLastJSApiObjectType);
1246
1247 return instance_type == kJSSpecialApiObjectType ||
1248
1249 (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
1250 static_cast<unsigned>(kJSObjectType)) <=
1251 static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
1252 }
1253
1254 V8_INLINE static uint8_t GetNodeFlag(Address* obj, int shift) {
1255 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1256 return *addr & static_cast<uint8_t>(1U << shift);
1257 }
1258
1259 V8_INLINE static void UpdateNodeFlag(Address* obj, bool value, int shift) {
1260 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1261 uint8_t mask = static_cast<uint8_t>(1U << shift);
1262 *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
1263 }
1264
1265 V8_INLINE static uint8_t GetNodeState(Address* obj) {
1266 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1267 return *addr & kNodeStateMask;
1268 }
1269
1270 V8_INLINE static void UpdateNodeState(Address* obj, uint8_t value) {
1271 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
1272 *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
1273 }
1274
1275 V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
1276 void* data) {
1277 Address addr = reinterpret_cast<Address>(isolate) +
1278 kIsolateEmbedderDataOffset + slot * kApiSystemPointerSize;
1279 *reinterpret_cast<void**>(addr) = data;
1280 }
1281
1282 V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
1283 uint32_t slot) {
1284 Address addr = reinterpret_cast<Address>(isolate) +
1285 kIsolateEmbedderDataOffset + slot * kApiSystemPointerSize;
1286 return *reinterpret_cast<void* const*>(addr);
1287 }
1288
1289 V8_INLINE static HandleScopeData* GetHandleScopeData(v8::Isolate* isolate) {
1290 Address addr =
1291 reinterpret_cast<Address>(isolate) + kIsolateHandleScopeDataOffset;
1292 return reinterpret_cast<HandleScopeData*>(addr);
1293 }
1294
1295 V8_INLINE static void IncrementLongTasksStatsCounter(v8::Isolate* isolate) {
1296 Address addr =
1297 reinterpret_cast<Address>(isolate) + kIsolateLongTaskStatsCounterOffset;
1298 ++(*reinterpret_cast<size_t*>(addr));
1299 }
1300
1301 V8_INLINE static Address* GetRootSlot(v8::Isolate* isolate, int index) {
1302 Address addr = reinterpret_cast<Address>(isolate) + kIsolateRootsOffset +
1303 index * kApiSystemPointerSize;
1304 return reinterpret_cast<Address*>(addr);
1305 }
1306
1307 V8_INLINE static Address GetRoot(v8::Isolate* isolate, int index) {
1308 #if V8_STATIC_ROOTS_BOOL
1309 Address base = *reinterpret_cast<Address*>(
1310 reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
1311 switch (index) {
1312 #define DECOMPRESS_ROOT(name, ...) \
1313 case k##name##RootIndex: \
1314 return base + StaticReadOnlyRoot::k##name;
1315 EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
1316 #undef DECOMPRESS_ROOT
1317 #undef EXPORTED_STATIC_ROOTS_PTR_LIST
1318 default:
1319 break;
1320 }
1321 #endif
1322 return *GetRootSlot(isolate, index);
1323 }
1324
1325 #ifdef V8_ENABLE_SANDBOX
1326 V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) {
1327 Address addr = reinterpret_cast<Address>(isolate) +
1328 kIsolateExternalPointerTableOffset +
1329 kExternalEntityTableBasePointerOffset;
1330 return *reinterpret_cast<Address**>(addr);
1331 }
1332
1333 V8_INLINE static Address* GetSharedExternalPointerTableBase(
1334 v8::Isolate* isolate) {
1335 Address addr = reinterpret_cast<Address>(isolate) +
1336 kIsolateSharedExternalPointerTableAddressOffset;
1337 addr = *reinterpret_cast<Address*>(addr);
1338 addr += kExternalEntityTableBasePointerOffset;
1339 return *reinterpret_cast<Address**>(addr);
1340 }
1341 #endif
1342
1343 template <typename T>
1344 V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
1345 Address addr = heap_object_ptr + offset - kHeapObjectTag;
1346 #ifdef V8_COMPRESS_POINTERS
1347 if constexpr (sizeof(T) > kApiTaggedSize) {
1348
1349
1350
1351
1352 T r;
1353 memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
1354 return r;
1355 }
1356 #endif
1357 return *reinterpret_cast<const T*>(addr);
1358 }
1359
1360 V8_INLINE static Address ReadTaggedPointerField(Address heap_object_ptr,
1361 int offset) {
1362 #ifdef V8_COMPRESS_POINTERS
1363 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1364 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1365 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1366 #else
1367 return ReadRawField<Address>(heap_object_ptr, offset);
1368 #endif
1369 }
1370
1371 V8_INLINE static Address ReadTaggedSignedField(Address heap_object_ptr,
1372 int offset) {
1373 #ifdef V8_COMPRESS_POINTERS
1374 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1375 return static_cast<Address>(static_cast<uintptr_t>(value));
1376 #else
1377 return ReadRawField<Address>(heap_object_ptr, offset);
1378 #endif
1379 }
1380
1381
1382
1383 V8_EXPORT static v8::Isolate* GetCurrentIsolate();
1384
1385 V8_INLINE static v8::Isolate* GetCurrentIsolateForSandbox() {
1386 #ifdef V8_ENABLE_SANDBOX
1387 return GetCurrentIsolate();
1388 #else
1389
1390 return nullptr;
1391 #endif
1392 }
1393
1394 template <ExternalPointerTagRange tag_range>
1395 V8_INLINE static Address ReadExternalPointerField(v8::Isolate* isolate,
1396 Address heap_object_ptr,
1397 int offset) {
1398 #ifdef V8_ENABLE_SANDBOX
1399 static_assert(!tag_range.IsEmpty());
1400
1401
1402 Address* table = IsSharedExternalPointerType(tag_range)
1403 ? GetSharedExternalPointerTableBase(isolate)
1404 : GetExternalPointerTableBase(isolate);
1405 internal::ExternalPointerHandle handle =
1406 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1407 uint32_t index = handle >> kExternalPointerIndexShift;
1408 std::atomic<Address>* ptr =
1409 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1410 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1411 ExternalPointerTag actual_tag = static_cast<ExternalPointerTag>(
1412 (entry & kExternalPointerTagMask) >> kExternalPointerTagShift);
1413 if (V8_LIKELY(tag_range.Contains(actual_tag))) {
1414 return entry & kExternalPointerPayloadMask;
1415 } else {
1416 return 0;
1417 }
1418 return entry;
1419 #else
1420 return ReadRawField<Address>(heap_object_ptr, offset);
1421 #endif
1422 }
1423
1424 V8_INLINE static Address ReadExternalPointerField(
1425 v8::Isolate* isolate, Address heap_object_ptr, int offset,
1426 ExternalPointerTagRange tag_range) {
1427 #ifdef V8_ENABLE_SANDBOX
1428
1429
1430 Address* table = IsSharedExternalPointerType(tag_range)
1431 ? GetSharedExternalPointerTableBase(isolate)
1432 : GetExternalPointerTableBase(isolate);
1433 internal::ExternalPointerHandle handle =
1434 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1435 uint32_t index = handle >> kExternalPointerIndexShift;
1436 std::atomic<Address>* ptr =
1437 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1438 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1439 ExternalPointerTag actual_tag = static_cast<ExternalPointerTag>(
1440 (entry & kExternalPointerTagMask) >> kExternalPointerTagShift);
1441 if (V8_LIKELY(tag_range.Contains(actual_tag))) {
1442 return entry & kExternalPointerPayloadMask;
1443 } else {
1444 return 0;
1445 }
1446 return entry;
1447 #else
1448 return ReadRawField<Address>(heap_object_ptr, offset);
1449 #endif
1450 }
1451
1452 #ifdef V8_COMPRESS_POINTERS
1453 V8_INLINE static Address GetPtrComprCageBaseFromOnHeapAddress(Address addr) {
1454 return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
1455 }
1456
1457 V8_INLINE static uint32_t CompressTagged(Address value) {
1458 return static_cast<uint32_t>(value);
1459 }
1460
1461 V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
1462 uint32_t value) {
1463 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1464 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1465 }
1466
1467 #endif
1468 };
1469
1470
1471
1472 template <bool PerformCheck>
1473 struct CastCheck {
1474 template <class T>
1475 static void Perform(T* data);
1476 };
1477
1478 template <>
1479 template <class T>
1480 void CastCheck<true>::Perform(T* data) {
1481 T::Cast(data);
1482 }
1483
1484 template <>
1485 template <class T>
1486 void CastCheck<false>::Perform(T* data) {}
1487
1488 template <class T>
1489 V8_INLINE void PerformCastCheck(T* data) {
1490 CastCheck<std::is_base_of_v<Data, T> &&
1491 !std::is_same_v<Data, std::remove_cv_t<T>>>::Perform(data);
1492 }
1493
1494
1495
1496 class BackingStoreBase {};
1497
1498
1499
1500 constexpr int kGarbageCollectionReasonMaxValue = 30;
1501
1502
1503
1504 class V8_EXPORT StrongRootAllocatorBase {
1505 public:
1506 Heap* heap() const { return heap_; }
1507
1508 constexpr bool operator==(const StrongRootAllocatorBase&) const = default;
1509
1510 protected:
1511 explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
1512 explicit StrongRootAllocatorBase(LocalHeap* heap);
1513 explicit StrongRootAllocatorBase(Isolate* isolate);
1514 explicit StrongRootAllocatorBase(v8::Isolate* isolate);
1515 explicit StrongRootAllocatorBase(LocalIsolate* isolate);
1516
1517
1518 Address* allocate_impl(size_t n);
1519 void deallocate_impl(Address* p, size_t n) noexcept;
1520
1521 private:
1522 Heap* heap_;
1523 };
1524
1525
1526
1527
1528
1529
1530 template <typename T>
1531 class StrongRootAllocator : private std::allocator<T> {
1532 public:
1533 using value_type = T;
1534
1535 template <typename HeapOrIsolateT>
1536 explicit StrongRootAllocator(HeapOrIsolateT*) {}
1537 template <typename U>
1538 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept {}
1539
1540 using std::allocator<T>::allocate;
1541 using std::allocator<T>::deallocate;
1542 };
1543
1544 template <typename Iterator>
1545 concept HasIteratorConcept = requires { typename Iterator::iterator_concept; };
1546
1547 template <typename Iterator>
1548 concept HasIteratorCategory =
1549 requires { typename Iterator::iterator_category; };
1550
1551
1552
1553
1554 template <typename Iterator>
1555 struct MaybeDefineIteratorConcept {};
1556
1557 template <HasIteratorConcept Iterator>
1558 struct MaybeDefineIteratorConcept<Iterator> {
1559 using iterator_concept = typename Iterator::iterator_concept;
1560 };
1561
1562 template <typename Iterator>
1563 requires(HasIteratorCategory<Iterator> && !HasIteratorConcept<Iterator>)
1564 struct MaybeDefineIteratorConcept<Iterator> {
1565 using iterator_concept =
1566 typename std::iterator_traits<Iterator>::iterator_concept;
1567 };
1568
1569
1570
1571
1572
1573 template <typename Iterator, typename ElementType = void>
1574 class WrappedIterator : public MaybeDefineIteratorConcept<Iterator> {
1575 public:
1576 static_assert(
1577 std::is_void_v<ElementType> ||
1578 (std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
1579 std::add_pointer_t<ElementType>> &&
1580 std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
1581 std::add_lvalue_reference_t<ElementType>>));
1582
1583 using difference_type =
1584 typename std::iterator_traits<Iterator>::difference_type;
1585 using value_type =
1586 std::conditional_t<std::is_void_v<ElementType>,
1587 typename std::iterator_traits<Iterator>::value_type,
1588 ElementType>;
1589 using pointer =
1590 std::conditional_t<std::is_void_v<ElementType>,
1591 typename std::iterator_traits<Iterator>::pointer,
1592 std::add_pointer_t<ElementType>>;
1593 using reference =
1594 std::conditional_t<std::is_void_v<ElementType>,
1595 typename std::iterator_traits<Iterator>::reference,
1596 std::add_lvalue_reference_t<ElementType>>;
1597 using iterator_category =
1598 typename std::iterator_traits<Iterator>::iterator_category;
1599
1600 constexpr WrappedIterator() noexcept = default;
1601 constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
1602
1603 template <typename OtherIterator, typename OtherElementType>
1604 requires std::is_convertible_v<OtherIterator, Iterator>
1605 constexpr WrappedIterator(
1606 const WrappedIterator<OtherIterator, OtherElementType>& other) noexcept
1607 : it_(other.base()) {}
1608
1609 [[nodiscard]] constexpr reference operator*() const noexcept { return *it_; }
1610 [[nodiscard]] constexpr pointer operator->() const noexcept {
1611 if constexpr (std::is_pointer_v<Iterator>) {
1612 return it_;
1613 } else {
1614 return it_.operator->();
1615 }
1616 }
1617
1618 template <typename OtherIterator, typename OtherElementType>
1619 [[nodiscard]] constexpr bool operator==(
1620 const WrappedIterator<OtherIterator, OtherElementType>& other)
1621 const noexcept {
1622 return it_ == other.base();
1623 }
1624
1625 template <typename OtherIterator, typename OtherElementType>
1626 [[nodiscard]] constexpr auto operator<=>(
1627 const WrappedIterator<OtherIterator, OtherElementType>& other)
1628 const noexcept {
1629 if constexpr (std::three_way_comparable_with<Iterator, OtherIterator>) {
1630 return it_ <=> other.base();
1631 } else if constexpr (std::totally_ordered_with<Iterator, OtherIterator>) {
1632 if (it_ < other.base()) {
1633 return std::strong_ordering::less;
1634 }
1635 return (it_ > other.base()) ? std::strong_ordering::greater
1636 : std::strong_ordering::equal;
1637 } else {
1638 if (it_ < other.base()) {
1639 return std::partial_ordering::less;
1640 }
1641 if (other.base() < it_) {
1642 return std::partial_ordering::greater;
1643 }
1644 return (it_ == other.base()) ? std::partial_ordering::equivalent
1645 : std::partial_ordering::unordered;
1646 }
1647 }
1648
1649 constexpr WrappedIterator& operator++() noexcept {
1650 ++it_;
1651 return *this;
1652 }
1653 constexpr WrappedIterator operator++(int) noexcept {
1654 WrappedIterator result(*this);
1655 ++(*this);
1656 return result;
1657 }
1658
1659 constexpr WrappedIterator& operator--() noexcept {
1660 --it_;
1661 return *this;
1662 }
1663 constexpr WrappedIterator operator--(int) noexcept {
1664 WrappedIterator result(*this);
1665 --(*this);
1666 return result;
1667 }
1668 [[nodiscard]] constexpr WrappedIterator operator+(
1669 difference_type n) const noexcept {
1670 WrappedIterator result(*this);
1671 result += n;
1672 return result;
1673 }
1674 [[nodiscard]] friend constexpr WrappedIterator operator+(
1675 difference_type n, const WrappedIterator& x) noexcept {
1676 return x + n;
1677 }
1678 constexpr WrappedIterator& operator+=(difference_type n) noexcept {
1679 it_ += n;
1680 return *this;
1681 }
1682 [[nodiscard]] constexpr WrappedIterator operator-(
1683 difference_type n) const noexcept {
1684 return *this + -n;
1685 }
1686 constexpr WrappedIterator& operator-=(difference_type n) noexcept {
1687 return *this += -n;
1688 }
1689 template <typename OtherIterator, typename OtherElementType>
1690 [[nodiscard]] constexpr auto operator-(
1691 const WrappedIterator<OtherIterator, OtherElementType>& other)
1692 const noexcept {
1693 return it_ - other.base();
1694 }
1695 [[nodiscard]] constexpr reference operator[](
1696 difference_type n) const noexcept {
1697 return it_[n];
1698 }
1699
1700 [[nodiscard]] constexpr const Iterator& base() const noexcept { return it_; }
1701
1702 private:
1703 Iterator it_;
1704 };
1705
1706
1707
1708
1709 class ValueHelper final {
1710 public:
1711
1712
1713
1714
1715
1716
1717 #ifdef V8_ENABLE_DIRECT_HANDLE
1718 static constexpr Address kTaggedNullAddress = 1;
1719
1720 using InternalRepresentationType = internal::Address;
1721 static constexpr InternalRepresentationType kEmpty = kTaggedNullAddress;
1722 #else
1723 using InternalRepresentationType = internal::Address*;
1724 static constexpr InternalRepresentationType kEmpty = nullptr;
1725 #endif
1726
1727 template <typename T>
1728 V8_INLINE static bool IsEmpty(T* value) {
1729 return ValueAsRepr(value) == kEmpty;
1730 }
1731
1732
1733
1734
1735 template <template <typename T, typename... Ms> typename H, typename T,
1736 typename... Ms>
1737 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
1738 return handle.template value<T>();
1739 }
1740
1741 #ifdef V8_ENABLE_DIRECT_HANDLE
1742
1743 template <typename T>
1744 V8_INLINE static Address ValueAsAddress(const T* value) {
1745 return reinterpret_cast<Address>(value);
1746 }
1747
1748 template <typename T, bool check_null = true, typename S>
1749 V8_INLINE static T* SlotAsValue(S* slot) {
1750 if (check_null && slot == nullptr) {
1751 return reinterpret_cast<T*>(kTaggedNullAddress);
1752 }
1753 return *reinterpret_cast<T**>(slot);
1754 }
1755
1756 template <typename T>
1757 V8_INLINE static InternalRepresentationType ValueAsRepr(const T* value) {
1758 return reinterpret_cast<InternalRepresentationType>(value);
1759 }
1760
1761 template <typename T>
1762 V8_INLINE static T* ReprAsValue(InternalRepresentationType repr) {
1763 return reinterpret_cast<T*>(repr);
1764 }
1765
1766 #else
1767
1768 template <typename T>
1769 V8_INLINE static Address ValueAsAddress(const T* value) {
1770 return *reinterpret_cast<const Address*>(value);
1771 }
1772
1773 template <typename T, bool check_null = true, typename S>
1774 V8_INLINE static T* SlotAsValue(S* slot) {
1775 return reinterpret_cast<T*>(slot);
1776 }
1777
1778 template <typename T>
1779 V8_INLINE static InternalRepresentationType ValueAsRepr(const T* value) {
1780 return const_cast<InternalRepresentationType>(
1781 reinterpret_cast<const Address*>(value));
1782 }
1783
1784 template <typename T>
1785 V8_INLINE static T* ReprAsValue(InternalRepresentationType repr) {
1786 return reinterpret_cast<T*>(repr);
1787 }
1788
1789 #endif
1790 };
1791
1792
1793
1794
1795 class HandleHelper final {
1796 public:
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807 template <typename T1, typename T2>
1808 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
1809 if (lhs.IsEmpty()) return rhs.IsEmpty();
1810 if (rhs.IsEmpty()) return false;
1811 return lhs.ptr() == rhs.ptr();
1812 }
1813 };
1814
1815 V8_EXPORT void VerifyHandleIsNonEmpty(bool is_empty);
1816
1817
1818
1819
1820
1821 void PrintFunctionCallbackInfo(void* function_callback_info);
1822 void PrintPropertyCallbackInfo(void* property_callback_info);
1823
1824 }
1825 }
1826
1827 #endif