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