File indexing completed on 2025-02-21 10:05:24
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 <memory>
0015 #include <type_traits>
0016
0017 #include "v8config.h" // NOLINT(build/include_directory)
0018
0019 namespace v8 {
0020
0021 class Array;
0022 class Context;
0023 class Data;
0024 class Isolate;
0025
0026 namespace internal {
0027
0028 class Heap;
0029 class Isolate;
0030
0031 typedef uintptr_t Address;
0032 static constexpr Address kNullAddress = 0;
0033
0034 constexpr int KB = 1024;
0035 constexpr int MB = KB * 1024;
0036 constexpr int GB = MB * 1024;
0037 #ifdef V8_TARGET_ARCH_X64
0038 constexpr size_t TB = size_t{GB} * 1024;
0039 #endif
0040
0041
0042
0043
0044 const int kApiSystemPointerSize = sizeof(void*);
0045 const int kApiDoubleSize = sizeof(double);
0046 const int kApiInt32Size = sizeof(int32_t);
0047 const int kApiInt64Size = sizeof(int64_t);
0048 const int kApiSizetSize = sizeof(size_t);
0049
0050
0051 const int kHeapObjectTag = 1;
0052 const int kWeakHeapObjectTag = 3;
0053 const int kHeapObjectTagSize = 2;
0054 const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
0055 const intptr_t kHeapObjectReferenceTagMask = 1 << (kHeapObjectTagSize - 1);
0056
0057
0058
0059
0060 const int kForwardingTag = 0;
0061 const int kForwardingTagSize = 2;
0062 const intptr_t kForwardingTagMask = (1 << kForwardingTagSize) - 1;
0063
0064
0065 const int kSmiTag = 0;
0066 const int kSmiTagSize = 1;
0067 const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
0068
0069 template <size_t tagged_ptr_size>
0070 struct SmiTagging;
0071
0072 constexpr intptr_t kIntptrAllBitsSet = intptr_t{-1};
0073 constexpr uintptr_t kUintptrAllBitsSet =
0074 static_cast<uintptr_t>(kIntptrAllBitsSet);
0075
0076
0077 template <>
0078 struct SmiTagging<4> {
0079 enum { kSmiShiftSize = 0, kSmiValueSize = 31 };
0080
0081 static constexpr intptr_t kSmiMinValue =
0082 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
0083 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
0084
0085 V8_INLINE static constexpr int SmiToInt(Address value) {
0086 int shift_bits = kSmiTagSize + kSmiShiftSize;
0087
0088 return static_cast<int32_t>(static_cast<uint32_t>(value)) >> shift_bits;
0089 }
0090 V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
0091
0092
0093
0094 return (static_cast<uintptr_t>(value) -
0095 static_cast<uintptr_t>(kSmiMinValue)) <=
0096 (static_cast<uintptr_t>(kSmiMaxValue) -
0097 static_cast<uintptr_t>(kSmiMinValue));
0098 }
0099 };
0100
0101
0102 template <>
0103 struct SmiTagging<8> {
0104 enum { kSmiShiftSize = 31, kSmiValueSize = 32 };
0105
0106 static constexpr intptr_t kSmiMinValue =
0107 static_cast<intptr_t>(kUintptrAllBitsSet << (kSmiValueSize - 1));
0108 static constexpr intptr_t kSmiMaxValue = -(kSmiMinValue + 1);
0109
0110 V8_INLINE static constexpr int SmiToInt(Address value) {
0111 int shift_bits = kSmiTagSize + kSmiShiftSize;
0112
0113 return static_cast<int>(static_cast<intptr_t>(value) >> shift_bits);
0114 }
0115 V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
0116
0117 return (value == static_cast<int32_t>(value));
0118 }
0119 };
0120
0121 #ifdef V8_COMPRESS_POINTERS
0122
0123
0124 constexpr size_t kPtrComprCageReservationSize = size_t{1} << 32;
0125 constexpr size_t kPtrComprCageBaseAlignment = size_t{1} << 32;
0126
0127 static_assert(
0128 kApiSystemPointerSize == kApiInt64Size,
0129 "Pointer compression can be enabled only for 64-bit architectures");
0130 const int kApiTaggedSize = kApiInt32Size;
0131 #else
0132 const int kApiTaggedSize = kApiSystemPointerSize;
0133 #endif
0134
0135 constexpr bool PointerCompressionIsEnabled() {
0136 return kApiTaggedSize != kApiSystemPointerSize;
0137 }
0138
0139 #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH
0140 using PlatformSmiTagging = SmiTagging<kApiInt32Size>;
0141 #else
0142 using PlatformSmiTagging = SmiTagging<kApiTaggedSize>;
0143 #endif
0144
0145
0146
0147 const int kSmiShiftSize = PlatformSmiTagging::kSmiShiftSize;
0148 const int kSmiValueSize = PlatformSmiTagging::kSmiValueSize;
0149 const int kSmiMinValue = static_cast<int>(PlatformSmiTagging::kSmiMinValue);
0150 const int kSmiMaxValue = static_cast<int>(PlatformSmiTagging::kSmiMaxValue);
0151 constexpr bool SmiValuesAre31Bits() { return kSmiValueSize == 31; }
0152 constexpr bool SmiValuesAre32Bits() { return kSmiValueSize == 32; }
0153 constexpr bool Is64() { return kApiSystemPointerSize == sizeof(int64_t); }
0154
0155 V8_INLINE static constexpr Address IntToSmi(int value) {
0156 return (static_cast<Address>(value) << (kSmiTagSize + kSmiShiftSize)) |
0157 kSmiTag;
0158 }
0159
0160
0161
0162
0163 constexpr bool SandboxIsEnabled() {
0164 #ifdef V8_ENABLE_SANDBOX
0165 return true;
0166 #else
0167 return false;
0168 #endif
0169 }
0170
0171
0172
0173 using SandboxedPointer_t = Address;
0174
0175 #ifdef V8_ENABLE_SANDBOX
0176
0177
0178 #if defined(V8_TARGET_OS_ANDROID)
0179
0180
0181
0182 constexpr size_t kSandboxSizeLog2 = 37;
0183 #elif defined(V8_TARGET_ARCH_LOONG64)
0184
0185
0186 constexpr size_t kSandboxSizeLog2 = 38;
0187 #else
0188
0189 constexpr size_t kSandboxSizeLog2 = 40;
0190 #endif
0191 constexpr size_t kSandboxSize = 1ULL << kSandboxSizeLog2;
0192
0193
0194
0195
0196
0197
0198 constexpr size_t kSandboxAlignment = kPtrComprCageBaseAlignment;
0199
0200
0201
0202
0203
0204 constexpr uint64_t kSandboxedPointerShift = 64 - kSandboxSizeLog2;
0205
0206
0207
0208
0209 constexpr size_t kSandboxGuardRegionSize = 32ULL * GB;
0210
0211 static_assert((kSandboxGuardRegionSize % kSandboxAlignment) == 0,
0212 "The size of the guard regions around the sandbox must be a "
0213 "multiple of its required alignment.");
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 constexpr size_t kSandboxMinimumReservationSize = 8ULL * GB;
0226
0227 static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
0228 "The minimum reservation size for a sandbox must be larger than "
0229 "the pointer compression cage contained within it.");
0230
0231
0232
0233
0234
0235 constexpr size_t kMaxSafeBufferSizeForSandbox = 32ULL * GB - 1;
0236 static_assert(kMaxSafeBufferSizeForSandbox <= kSandboxGuardRegionSize,
0237 "The maximum allowed buffer size must not be larger than the "
0238 "sandbox's guard regions");
0239
0240 constexpr size_t kBoundedSizeShift = 29;
0241 static_assert(1ULL << (64 - kBoundedSizeShift) ==
0242 kMaxSafeBufferSizeForSandbox + 1,
0243 "The maximum size of a BoundedSize must be synchronized with the "
0244 "kMaxSafeBufferSizeForSandbox");
0245
0246 #endif
0247
0248 #ifdef V8_COMPRESS_POINTERS
0249
0250 #ifdef V8_TARGET_OS_ANDROID
0251
0252
0253
0254
0255
0256 constexpr size_t kExternalPointerTableReservationSize = 512 * MB;
0257
0258
0259
0260
0261 constexpr uint32_t kExternalPointerIndexShift = 6;
0262 #else
0263 constexpr size_t kExternalPointerTableReservationSize = 1024 * MB;
0264 constexpr uint32_t kExternalPointerIndexShift = 5;
0265 #endif
0266
0267
0268 constexpr int kExternalPointerTableEntrySize = 8;
0269 constexpr int kExternalPointerTableEntrySizeLog2 = 3;
0270 constexpr size_t kMaxExternalPointers =
0271 kExternalPointerTableReservationSize / kExternalPointerTableEntrySize;
0272 static_assert((1 << (32 - kExternalPointerIndexShift)) == kMaxExternalPointers,
0273 "kExternalPointerTableReservationSize and "
0274 "kExternalPointerIndexShift don't match");
0275
0276 #else
0277
0278
0279 constexpr size_t kMaxExternalPointers = 0;
0280
0281 #endif
0282
0283
0284
0285
0286
0287
0288
0289
0290 using ExternalPointerHandle = uint32_t;
0291
0292
0293
0294
0295 #ifdef V8_ENABLE_SANDBOX
0296 using ExternalPointer_t = ExternalPointerHandle;
0297 #else
0298 using ExternalPointer_t = Address;
0299 #endif
0300
0301 constexpr ExternalPointer_t kNullExternalPointer = 0;
0302 constexpr ExternalPointerHandle kNullExternalPointerHandle = 0;
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 constexpr uint64_t kExternalPointerMarkBit = 1ULL << 62;
0375 constexpr uint64_t kExternalPointerTagMask = 0x40ff000000000000;
0376 constexpr uint64_t kExternalPointerTagMaskWithoutMarkBit = 0xff000000000000;
0377 constexpr uint64_t kExternalPointerTagShift = 48;
0378
0379
0380
0381
0382
0383 constexpr uint64_t kAllExternalPointerTypeTags[] = {
0384 0b00001111, 0b00010111, 0b00011011, 0b00011101, 0b00011110, 0b00100111,
0385 0b00101011, 0b00101101, 0b00101110, 0b00110011, 0b00110101, 0b00110110,
0386 0b00111001, 0b00111010, 0b00111100, 0b01000111, 0b01001011, 0b01001101,
0387 0b01001110, 0b01010011, 0b01010101, 0b01010110, 0b01011001, 0b01011010,
0388 0b01011100, 0b01100011, 0b01100101, 0b01100110, 0b01101001, 0b01101010,
0389 0b01101100, 0b01110001, 0b01110010, 0b01110100, 0b01111000, 0b10000111,
0390 0b10001011, 0b10001101, 0b10001110, 0b10010011, 0b10010101, 0b10010110,
0391 0b10011001, 0b10011010, 0b10011100, 0b10100011, 0b10100101, 0b10100110,
0392 0b10101001, 0b10101010, 0b10101100, 0b10110001, 0b10110010, 0b10110100,
0393 0b10111000, 0b11000011, 0b11000101, 0b11000110, 0b11001001, 0b11001010,
0394 0b11001100, 0b11010001, 0b11010010, 0b11010100, 0b11011000, 0b11100001,
0395 0b11100010, 0b11100100, 0b11101000, 0b11110000};
0396
0397 #define TAG(i) \
0398 ((kAllExternalPointerTypeTags[i] << kExternalPointerTagShift) | \
0399 kExternalPointerMarkBit)
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 #define SHARED_EXTERNAL_POINTER_TAGS(V) \
0412 V(kFirstSharedTag, TAG(0)) \
0413 V(kWaiterQueueNodeTag, TAG(0)) \
0414 V(kExternalStringResourceTag, TAG(1)) \
0415 V(kExternalStringResourceDataTag, TAG(2)) \
0416 V(kLastSharedTag, TAG(2))
0417
0418
0419
0420 #define PER_ISOLATE_EXTERNAL_POINTER_TAGS(V) \
0421 V(kForeignForeignAddressTag, TAG(10)) \
0422 V(kNativeContextMicrotaskQueueTag, TAG(11)) \
0423 V(kEmbedderDataSlotPayloadTag, TAG(12)) \
0424 \
0425 \
0426 \
0427 V(kExternalObjectValueTag, TAG(13)) \
0428 V(kFunctionTemplateInfoCallbackTag, TAG(14)) \
0429 V(kAccessorInfoGetterTag, TAG(15)) \
0430 V(kAccessorInfoSetterTag, TAG(16)) \
0431 V(kWasmInternalFunctionCallTargetTag, TAG(17)) \
0432 V(kWasmTypeInfoNativeTypeTag, TAG(18)) \
0433 V(kWasmExportedFunctionDataSignatureTag, TAG(19)) \
0434 V(kWasmContinuationJmpbufTag, TAG(20)) \
0435 V(kWasmIndirectFunctionTargetTag, TAG(21)) \
0436 V(kArrayBufferExtensionTag, TAG(22))
0437
0438
0439 #define ALL_EXTERNAL_POINTER_TAGS(V) \
0440 SHARED_EXTERNAL_POINTER_TAGS(V) \
0441 PER_ISOLATE_EXTERNAL_POINTER_TAGS(V)
0442
0443 #define EXTERNAL_POINTER_TAG_ENUM(Name, Tag) Name = Tag,
0444 #define MAKE_TAG(HasMarkBit, TypeTag) \
0445 ((static_cast<uint64_t>(TypeTag) << kExternalPointerTagShift) | \
0446 (HasMarkBit ? kExternalPointerMarkBit : 0))
0447 enum ExternalPointerTag : uint64_t {
0448
0449 kExternalPointerNullTag = MAKE_TAG(1, 0b00000000),
0450
0451 kAnyExternalPointerTag = MAKE_TAG(1, 0b11111111),
0452
0453
0454
0455 kExternalPointerFreeEntryTag = MAKE_TAG(0, 0b11111111),
0456
0457 kExternalPointerEvacuationEntryTag = MAKE_TAG(1, 0b11100111),
0458
0459 ALL_EXTERNAL_POINTER_TAGS(EXTERNAL_POINTER_TAG_ENUM)
0460 };
0461
0462 #undef MAKE_TAG
0463 #undef TAG
0464 #undef EXTERNAL_POINTER_TAG_ENUM
0465
0466
0467
0468
0469
0470 V8_INLINE static constexpr bool IsSharedExternalPointerType(
0471 ExternalPointerTag tag) {
0472 return tag >= kFirstSharedTag && tag <= kLastSharedTag;
0473 }
0474
0475
0476
0477
0478 V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
0479 ExternalPointerTag tag) {
0480 return tag == kAccessorInfoGetterTag || tag == kAccessorInfoSetterTag ||
0481 tag == kFunctionTemplateInfoCallbackTag;
0482 }
0483
0484
0485 #define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
0486 static_assert(IsSharedExternalPointerType(Tag));
0487 #define CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
0488 static_assert(!IsSharedExternalPointerType(Tag));
0489
0490 SHARED_EXTERNAL_POINTER_TAGS(CHECK_SHARED_EXTERNAL_POINTER_TAGS)
0491 PER_ISOLATE_EXTERNAL_POINTER_TAGS(CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS)
0492
0493 #undef CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS
0494 #undef CHECK_SHARED_EXTERNAL_POINTER_TAGS
0495
0496 #undef SHARED_EXTERNAL_POINTER_TAGS
0497 #undef EXTERNAL_POINTER_TAGS
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516 using IndirectPointerHandle = uint32_t;
0517
0518
0519 constexpr IndirectPointerHandle kNullIndirectPointerHandle = 0;
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536 using TrustedPointerHandle = IndirectPointerHandle;
0537
0538
0539
0540
0541 constexpr size_t kTrustedPointerTableReservationSize = 64 * MB;
0542
0543
0544
0545 constexpr uint32_t kTrustedPointerHandleShift = 9;
0546
0547
0548 constexpr TrustedPointerHandle kNullTrustedPointerHandle =
0549 kNullIndirectPointerHandle;
0550
0551
0552 constexpr int kTrustedPointerTableEntrySize = 8;
0553 constexpr int kTrustedPointerTableEntrySizeLog2 = 3;
0554 constexpr size_t kMaxTrustedPointers =
0555 kTrustedPointerTableReservationSize / kTrustedPointerTableEntrySize;
0556 static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
0557 "kTrustedPointerTableReservationSize and "
0558 "kTrustedPointerHandleShift don't match");
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574 using CodePointerHandle = IndirectPointerHandle;
0575
0576
0577
0578
0579 constexpr size_t kCodePointerTableReservationSize = 16 * MB;
0580
0581
0582
0583 constexpr uint32_t kCodePointerHandleShift = 12;
0584
0585
0586 constexpr CodePointerHandle kNullCodePointerHandle = kNullIndirectPointerHandle;
0587
0588
0589
0590
0591
0592
0593
0594
0595 constexpr uint32_t kCodePointerHandleMarker = 0x1;
0596 static_assert(kCodePointerHandleShift > 0);
0597 static_assert(kTrustedPointerHandleShift > 0);
0598
0599
0600 constexpr int kCodePointerTableEntrySize = 16;
0601 constexpr int kCodePointerTableEntrySizeLog2 = 4;
0602 constexpr size_t kMaxCodePointers =
0603 kCodePointerTableReservationSize / kCodePointerTableEntrySize;
0604 static_assert(
0605 (1 << (32 - kCodePointerHandleShift)) == kMaxCodePointers,
0606 "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
0607
0608 constexpr int kCodePointerTableEntryEntrypointOffset = 0;
0609 constexpr int kCodePointerTableEntryCodeObjectOffset = 8;
0610
0611
0612
0613 constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace = true;
0614 constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace = false;
0615 constexpr bool kAllCodeObjectsLiveInTrustedSpace =
0616 kRuntimeGeneratedCodeObjectsLiveInTrustedSpace &&
0617 kBuiltinCodeObjectsLiveInTrustedSpace;
0618
0619
0620
0621 V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
0622
0623
0624
0625
0626 V8_EXPORT bool ShouldThrowOnError(internal::Isolate* isolate);
0627
0628
0629
0630
0631
0632 class Internals {
0633 #ifdef V8_MAP_PACKING
0634 V8_INLINE static constexpr Address UnpackMapWord(Address mapword) {
0635
0636 return mapword ^ kMapWordXorMask;
0637 }
0638 #endif
0639
0640 public:
0641
0642
0643 static const int kHeapObjectMapOffset = 0;
0644 static const int kMapInstanceTypeOffset = 1 * kApiTaggedSize + kApiInt32Size;
0645 static const int kStringResourceOffset =
0646 1 * kApiTaggedSize + 2 * kApiInt32Size;
0647
0648 static const int kOddballKindOffset = 4 * kApiTaggedSize + kApiDoubleSize;
0649 static const int kJSObjectHeaderSize = 3 * kApiTaggedSize;
0650 static const int kFixedArrayHeaderSize = 2 * kApiTaggedSize;
0651 static const int kEmbedderDataArrayHeaderSize = 2 * kApiTaggedSize;
0652 static const int kEmbedderDataSlotSize = kApiSystemPointerSize;
0653 #ifdef V8_ENABLE_SANDBOX
0654 static const int kEmbedderDataSlotExternalPointerOffset = kApiTaggedSize;
0655 #else
0656 static const int kEmbedderDataSlotExternalPointerOffset = 0;
0657 #endif
0658 static const int kNativeContextEmbedderDataOffset = 6 * kApiTaggedSize;
0659 static const int kStringRepresentationAndEncodingMask = 0x0f;
0660 static const int kStringEncodingMask = 0x8;
0661 static const int kExternalTwoByteRepresentationTag = 0x02;
0662 static const int kExternalOneByteRepresentationTag = 0x0a;
0663
0664 static const uint32_t kNumIsolateDataSlots = 4;
0665 static const int kStackGuardSize = 8 * kApiSystemPointerSize;
0666 static const int kNumberOfBooleanFlags = 6;
0667 static const int kErrorMessageParamSize = 1;
0668 static const int kTablesAlignmentPaddingSize = 1;
0669 static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize;
0670 static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
0671 static const int kLinearAllocationAreaSize = 3 * kApiSystemPointerSize;
0672 static const int kThreadLocalTopSize = 30 * kApiSystemPointerSize;
0673 static const int kHandleScopeDataSize =
0674 2 * kApiSystemPointerSize + 2 * kApiInt32Size;
0675
0676
0677 static const int kExternalPointerTableBasePointerOffset = 0;
0678 static const int kExternalPointerTableSize = 2 * kApiSystemPointerSize;
0679 static const int kTrustedPointerTableSize = 2 * kApiSystemPointerSize;
0680 static const int kTrustedPointerTableBasePointerOffset = 0;
0681
0682
0683 static const int kIsolateCageBaseOffset = 0;
0684 static const int kIsolateStackGuardOffset =
0685 kIsolateCageBaseOffset + kApiSystemPointerSize;
0686 static const int kVariousBooleanFlagsOffset =
0687 kIsolateStackGuardOffset + kStackGuardSize;
0688 static const int kErrorMessageParamOffset =
0689 kVariousBooleanFlagsOffset + kNumberOfBooleanFlags;
0690 static const int kBuiltinTier0EntryTableOffset = kErrorMessageParamOffset +
0691 kErrorMessageParamSize +
0692 kTablesAlignmentPaddingSize;
0693 static const int kBuiltinTier0TableOffset =
0694 kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize;
0695 static const int kNewAllocationInfoOffset =
0696 kBuiltinTier0TableOffset + kBuiltinTier0TableSize;
0697 static const int kOldAllocationInfoOffset =
0698 kNewAllocationInfoOffset + kLinearAllocationAreaSize;
0699
0700 static const int kFastCCallAlignmentPaddingSize =
0701 kApiSystemPointerSize == 8 ? 0 : kApiSystemPointerSize;
0702 static const int kIsolateFastCCallCallerFpOffset =
0703 kOldAllocationInfoOffset + kLinearAllocationAreaSize +
0704 kFastCCallAlignmentPaddingSize;
0705 static const int kIsolateFastCCallCallerPcOffset =
0706 kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
0707 static const int kIsolateFastApiCallTargetOffset =
0708 kIsolateFastCCallCallerPcOffset + kApiSystemPointerSize;
0709 static const int kIsolateLongTaskStatsCounterOffset =
0710 kIsolateFastApiCallTargetOffset + kApiSystemPointerSize;
0711 static const int kIsolateThreadLocalTopOffset =
0712 kIsolateLongTaskStatsCounterOffset + kApiSizetSize;
0713 static const int kIsolateHandleScopeDataOffset =
0714 kIsolateThreadLocalTopOffset + kThreadLocalTopSize;
0715 static const int kIsolateEmbedderDataOffset =
0716 kIsolateHandleScopeDataOffset + kHandleScopeDataSize;
0717 #ifdef V8_COMPRESS_POINTERS
0718 static const int kIsolateExternalPointerTableOffset =
0719 kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
0720 static const int kIsolateSharedExternalPointerTableAddressOffset =
0721 kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
0722 #ifdef V8_ENABLE_SANDBOX
0723 static const int kIsolateTrustedCageBaseOffset =
0724 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
0725 static const int kIsolateTrustedPointerTableOffset =
0726 kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
0727 static const int kIsolateApiCallbackThunkArgumentOffset =
0728 kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
0729 #else
0730 static const int kIsolateApiCallbackThunkArgumentOffset =
0731 kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
0732 #endif
0733 #else
0734 static const int kIsolateApiCallbackThunkArgumentOffset =
0735 kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
0736 #endif
0737 static const int kContinuationPreservedEmbedderDataOffset =
0738 kIsolateApiCallbackThunkArgumentOffset + kApiSystemPointerSize;
0739
0740 static const int kWasm64OOBOffsetAlignmentPaddingSize = 0;
0741 static const int kWasm64OOBOffsetOffset =
0742 kContinuationPreservedEmbedderDataOffset + kApiSystemPointerSize +
0743 kWasm64OOBOffsetAlignmentPaddingSize;
0744 static const int kIsolateRootsOffset =
0745 kWasm64OOBOffsetOffset + sizeof(int64_t);
0746
0747 #if V8_STATIC_ROOTS_BOOL
0748
0749
0750 #define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
0751 V(UndefinedValue, 0x69) \
0752 V(NullValue, 0x85) \
0753 V(TrueValue, 0xc9) \
0754 V(FalseValue, 0xad) \
0755 V(EmptyString, 0xa1) \
0756 V(TheHoleValue, 0x719)
0757
0758 using Tagged_t = uint32_t;
0759 struct StaticReadOnlyRoot {
0760 #define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
0761 EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
0762 #undef DEF_ROOT
0763
0764 static constexpr Tagged_t kFirstStringMap = 0xe5;
0765 static constexpr Tagged_t kLastStringMap = 0x47d;
0766
0767 #define PLUSONE(...) +1
0768 static constexpr size_t kNumberOfExportedStaticRoots =
0769 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
0770 #undef PLUSONE
0771 };
0772
0773 #endif
0774
0775 static const int kUndefinedValueRootIndex = 4;
0776 static const int kTheHoleValueRootIndex = 5;
0777 static const int kNullValueRootIndex = 6;
0778 static const int kTrueValueRootIndex = 7;
0779 static const int kFalseValueRootIndex = 8;
0780 static const int kEmptyStringRootIndex = 9;
0781
0782 static const int kNodeClassIdOffset = 1 * kApiSystemPointerSize;
0783 static const int kNodeFlagsOffset = 1 * kApiSystemPointerSize + 3;
0784 static const int kNodeStateMask = 0x3;
0785 static const int kNodeStateIsWeakValue = 2;
0786
0787 static const int kFirstNonstringType = 0x80;
0788 static const int kOddballType = 0x83;
0789 static const int kForeignType = 0xcc;
0790 static const int kJSSpecialApiObjectType = 0x410;
0791 static const int kJSObjectType = 0x421;
0792 static const int kFirstJSApiObjectType = 0x422;
0793 static const int kLastJSApiObjectType = 0x80A;
0794
0795
0796 static const int kFirstEmbedderJSApiObjectType = 0;
0797 static const int kLastEmbedderJSApiObjectType =
0798 kLastJSApiObjectType - kFirstJSApiObjectType;
0799
0800 static const int kUndefinedOddballKind = 4;
0801 static const int kNullOddballKind = 3;
0802
0803
0804
0805 static const int kThrowOnError = 0;
0806 static const int kDontThrow = 1;
0807 static const int kInferShouldThrowMode = 2;
0808
0809
0810
0811 static constexpr int kExternalAllocationSoftLimit = 64 * 1024 * 1024;
0812
0813 #ifdef V8_MAP_PACKING
0814 static const uintptr_t kMapWordMetadataMask = 0xffffULL << 48;
0815
0816 static const uintptr_t kMapWordSignature = 0b10;
0817
0818
0819
0820
0821 static const int kMapWordXorMask = 0b11;
0822 #endif
0823
0824 V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
0825 V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
0826 #ifdef V8_ENABLE_CHECKS
0827 CheckInitializedImpl(isolate);
0828 #endif
0829 }
0830
0831 V8_INLINE static constexpr bool HasHeapObjectTag(Address value) {
0832 return (value & kHeapObjectTagMask) == static_cast<Address>(kHeapObjectTag);
0833 }
0834
0835 V8_INLINE static constexpr int SmiValue(Address value) {
0836 return PlatformSmiTagging::SmiToInt(value);
0837 }
0838
0839 V8_INLINE static constexpr Address IntToSmi(int value) {
0840 return internal::IntToSmi(value);
0841 }
0842
0843 V8_INLINE static constexpr bool IsValidSmi(intptr_t value) {
0844 return PlatformSmiTagging::IsValidSmi(value);
0845 }
0846
0847 #if V8_STATIC_ROOTS_BOOL
0848 V8_INLINE static bool is_identical(Address obj, Tagged_t constant) {
0849 return static_cast<Tagged_t>(obj) == constant;
0850 }
0851
0852 V8_INLINE static bool CheckInstanceMapRange(Address obj, Tagged_t first_map,
0853 Tagged_t last_map) {
0854 auto map = ReadRawField<Tagged_t>(obj, kHeapObjectMapOffset);
0855 #ifdef V8_MAP_PACKING
0856 map = UnpackMapWord(map);
0857 #endif
0858 return map >= first_map && map <= last_map;
0859 }
0860 #endif
0861
0862 V8_INLINE static int GetInstanceType(Address obj) {
0863 Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
0864 #ifdef V8_MAP_PACKING
0865 map = UnpackMapWord(map);
0866 #endif
0867 return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
0868 }
0869
0870 V8_INLINE static Address LoadMap(Address obj) {
0871 if (!HasHeapObjectTag(obj)) return kNullAddress;
0872 Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
0873 #ifdef V8_MAP_PACKING
0874 map = UnpackMapWord(map);
0875 #endif
0876 return map;
0877 }
0878
0879 V8_INLINE static int GetOddballKind(Address obj) {
0880 return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
0881 }
0882
0883 V8_INLINE static bool IsExternalTwoByteString(int instance_type) {
0884 int representation = (instance_type & kStringRepresentationAndEncodingMask);
0885 return representation == kExternalTwoByteRepresentationTag;
0886 }
0887
0888 V8_INLINE static constexpr bool CanHaveInternalField(int instance_type) {
0889 static_assert(kJSObjectType + 1 == kFirstJSApiObjectType);
0890 static_assert(kJSObjectType < kLastJSApiObjectType);
0891 static_assert(kFirstJSApiObjectType < kLastJSApiObjectType);
0892
0893 return instance_type == kJSSpecialApiObjectType ||
0894
0895 (static_cast<unsigned>(static_cast<unsigned>(instance_type) -
0896 static_cast<unsigned>(kJSObjectType)) <=
0897 static_cast<unsigned>(kLastJSApiObjectType - kJSObjectType));
0898 }
0899
0900 V8_INLINE static uint8_t GetNodeFlag(Address* obj, int shift) {
0901 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
0902 return *addr & static_cast<uint8_t>(1U << shift);
0903 }
0904
0905 V8_INLINE static void UpdateNodeFlag(Address* obj, bool value, int shift) {
0906 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
0907 uint8_t mask = static_cast<uint8_t>(1U << shift);
0908 *addr = static_cast<uint8_t>((*addr & ~mask) | (value << shift));
0909 }
0910
0911 V8_INLINE static uint8_t GetNodeState(Address* obj) {
0912 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
0913 return *addr & kNodeStateMask;
0914 }
0915
0916 V8_INLINE static void UpdateNodeState(Address* obj, uint8_t value) {
0917 uint8_t* addr = reinterpret_cast<uint8_t*>(obj) + kNodeFlagsOffset;
0918 *addr = static_cast<uint8_t>((*addr & ~kNodeStateMask) | value);
0919 }
0920
0921 V8_INLINE static void SetEmbedderData(v8::Isolate* isolate, uint32_t slot,
0922 void* data) {
0923 Address addr = reinterpret_cast<Address>(isolate) +
0924 kIsolateEmbedderDataOffset + slot * kApiSystemPointerSize;
0925 *reinterpret_cast<void**>(addr) = data;
0926 }
0927
0928 V8_INLINE static void* GetEmbedderData(const v8::Isolate* isolate,
0929 uint32_t slot) {
0930 Address addr = reinterpret_cast<Address>(isolate) +
0931 kIsolateEmbedderDataOffset + slot * kApiSystemPointerSize;
0932 return *reinterpret_cast<void* const*>(addr);
0933 }
0934
0935 V8_INLINE static void IncrementLongTasksStatsCounter(v8::Isolate* isolate) {
0936 Address addr =
0937 reinterpret_cast<Address>(isolate) + kIsolateLongTaskStatsCounterOffset;
0938 ++(*reinterpret_cast<size_t*>(addr));
0939 }
0940
0941 V8_INLINE static Address* GetRootSlot(v8::Isolate* isolate, int index) {
0942 Address addr = reinterpret_cast<Address>(isolate) + kIsolateRootsOffset +
0943 index * kApiSystemPointerSize;
0944 return reinterpret_cast<Address*>(addr);
0945 }
0946
0947 V8_INLINE static Address GetRoot(v8::Isolate* isolate, int index) {
0948 #if V8_STATIC_ROOTS_BOOL
0949 Address base = *reinterpret_cast<Address*>(
0950 reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
0951 switch (index) {
0952 #define DECOMPRESS_ROOT(name, ...) \
0953 case k##name##RootIndex: \
0954 return base + StaticReadOnlyRoot::k##name;
0955 EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
0956 #undef DECOMPRESS_ROOT
0957 #undef EXPORTED_STATIC_ROOTS_PTR_LIST
0958 default:
0959 break;
0960 }
0961 #endif
0962 return *GetRootSlot(isolate, index);
0963 }
0964
0965 #ifdef V8_ENABLE_SANDBOX
0966 V8_INLINE static Address* GetExternalPointerTableBase(v8::Isolate* isolate) {
0967 Address addr = reinterpret_cast<Address>(isolate) +
0968 kIsolateExternalPointerTableOffset +
0969 kExternalPointerTableBasePointerOffset;
0970 return *reinterpret_cast<Address**>(addr);
0971 }
0972
0973 V8_INLINE static Address* GetSharedExternalPointerTableBase(
0974 v8::Isolate* isolate) {
0975 Address addr = reinterpret_cast<Address>(isolate) +
0976 kIsolateSharedExternalPointerTableAddressOffset;
0977 addr = *reinterpret_cast<Address*>(addr);
0978 addr += kExternalPointerTableBasePointerOffset;
0979 return *reinterpret_cast<Address**>(addr);
0980 }
0981 #endif
0982
0983 template <typename T>
0984 V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
0985 Address addr = heap_object_ptr + offset - kHeapObjectTag;
0986 #ifdef V8_COMPRESS_POINTERS
0987 if (sizeof(T) > kApiTaggedSize) {
0988
0989
0990
0991
0992 T r;
0993 memcpy(&r, reinterpret_cast<void*>(addr), sizeof(T));
0994 return r;
0995 }
0996 #endif
0997 return *reinterpret_cast<const T*>(addr);
0998 }
0999
1000 V8_INLINE static Address ReadTaggedPointerField(Address heap_object_ptr,
1001 int offset) {
1002 #ifdef V8_COMPRESS_POINTERS
1003 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1004 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1005 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1006 #else
1007 return ReadRawField<Address>(heap_object_ptr, offset);
1008 #endif
1009 }
1010
1011 V8_INLINE static Address ReadTaggedSignedField(Address heap_object_ptr,
1012 int offset) {
1013 #ifdef V8_COMPRESS_POINTERS
1014 uint32_t value = ReadRawField<uint32_t>(heap_object_ptr, offset);
1015 return static_cast<Address>(static_cast<uintptr_t>(value));
1016 #else
1017 return ReadRawField<Address>(heap_object_ptr, offset);
1018 #endif
1019 }
1020
1021 V8_INLINE static v8::Isolate* GetIsolateForSandbox(Address obj) {
1022 #ifdef V8_ENABLE_SANDBOX
1023 return reinterpret_cast<v8::Isolate*>(
1024 internal::IsolateFromNeverReadOnlySpaceObject(obj));
1025 #else
1026
1027 return nullptr;
1028 #endif
1029 }
1030
1031 template <ExternalPointerTag tag>
1032 V8_INLINE static Address ReadExternalPointerField(v8::Isolate* isolate,
1033 Address heap_object_ptr,
1034 int offset) {
1035 #ifdef V8_ENABLE_SANDBOX
1036 static_assert(tag != kExternalPointerNullTag);
1037
1038
1039 Address* table = IsSharedExternalPointerType(tag)
1040 ? GetSharedExternalPointerTableBase(isolate)
1041 : GetExternalPointerTableBase(isolate);
1042 internal::ExternalPointerHandle handle =
1043 ReadRawField<ExternalPointerHandle>(heap_object_ptr, offset);
1044 uint32_t index = handle >> kExternalPointerIndexShift;
1045 std::atomic<Address>* ptr =
1046 reinterpret_cast<std::atomic<Address>*>(&table[index]);
1047 Address entry = std::atomic_load_explicit(ptr, std::memory_order_relaxed);
1048 return entry & ~tag;
1049 #else
1050 return ReadRawField<Address>(heap_object_ptr, offset);
1051 #endif
1052 }
1053
1054 #ifdef V8_COMPRESS_POINTERS
1055 V8_INLINE static Address GetPtrComprCageBaseFromOnHeapAddress(Address addr) {
1056 return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
1057 }
1058
1059 V8_INLINE static uint32_t CompressTagged(Address value) {
1060 return static_cast<uint32_t>(value);
1061 }
1062
1063 V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
1064 uint32_t value) {
1065 Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
1066 return base + static_cast<Address>(static_cast<uintptr_t>(value));
1067 }
1068
1069 #endif
1070 };
1071
1072
1073
1074 template <bool PerformCheck>
1075 struct CastCheck {
1076 template <class T>
1077 static void Perform(T* data);
1078 };
1079
1080 template <>
1081 template <class T>
1082 void CastCheck<true>::Perform(T* data) {
1083 T::Cast(data);
1084 }
1085
1086 template <>
1087 template <class T>
1088 void CastCheck<false>::Perform(T* data) {}
1089
1090 template <class T>
1091 V8_INLINE void PerformCastCheck(T* data) {
1092 CastCheck<std::is_base_of<Data, T>::value &&
1093 !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data);
1094 }
1095
1096
1097
1098 class BackingStoreBase {};
1099
1100
1101
1102 constexpr int kGarbageCollectionReasonMaxValue = 27;
1103
1104
1105
1106 class V8_EXPORT StrongRootAllocatorBase {
1107 public:
1108 Heap* heap() const { return heap_; }
1109
1110 bool operator==(const StrongRootAllocatorBase& other) const {
1111 return heap_ == other.heap_;
1112 }
1113 bool operator!=(const StrongRootAllocatorBase& other) const {
1114 return heap_ != other.heap_;
1115 }
1116
1117 protected:
1118 explicit StrongRootAllocatorBase(Heap* heap) : heap_(heap) {}
1119 explicit StrongRootAllocatorBase(v8::Isolate* isolate);
1120
1121
1122 Address* allocate_impl(size_t n);
1123 void deallocate_impl(Address* p, size_t n) noexcept;
1124
1125 private:
1126 Heap* heap_;
1127 };
1128
1129
1130
1131
1132
1133
1134 template <typename T>
1135 class StrongRootAllocator : public StrongRootAllocatorBase,
1136 private std::allocator<T> {
1137 public:
1138 using value_type = T;
1139
1140 explicit StrongRootAllocator(Heap* heap) : StrongRootAllocatorBase(heap) {}
1141 explicit StrongRootAllocator(v8::Isolate* isolate)
1142 : StrongRootAllocatorBase(isolate) {}
1143 template <typename U>
1144 StrongRootAllocator(const StrongRootAllocator<U>& other) noexcept
1145 : StrongRootAllocatorBase(other) {}
1146
1147 using std::allocator<T>::allocate;
1148 using std::allocator<T>::deallocate;
1149 };
1150
1151
1152
1153
1154
1155 template <typename Iterator, typename ElementType = void>
1156 class WrappedIterator {
1157 public:
1158 static_assert(
1159 !std::is_void_v<ElementType> ||
1160 (std::is_convertible_v<typename std::iterator_traits<Iterator>::pointer,
1161 ElementType*> &&
1162 std::is_convertible_v<typename std::iterator_traits<Iterator>::reference,
1163 ElementType&>));
1164
1165 using iterator_category =
1166 typename std::iterator_traits<Iterator>::iterator_category;
1167 using difference_type =
1168 typename std::iterator_traits<Iterator>::difference_type;
1169 using value_type =
1170 std::conditional_t<std::is_void_v<ElementType>,
1171 typename std::iterator_traits<Iterator>::value_type,
1172 ElementType>;
1173 using pointer =
1174 std::conditional_t<std::is_void_v<ElementType>,
1175 typename std::iterator_traits<Iterator>::pointer,
1176 ElementType*>;
1177 using reference =
1178 std::conditional_t<std::is_void_v<ElementType>,
1179 typename std::iterator_traits<Iterator>::reference,
1180 ElementType&>;
1181
1182 constexpr WrappedIterator() noexcept : it_() {}
1183 constexpr explicit WrappedIterator(Iterator it) noexcept : it_(it) {}
1184
1185 template <typename OtherIterator, typename OtherElementType,
1186 std::enable_if_t<std::is_convertible_v<OtherIterator, Iterator>,
1187 bool> = true>
1188 constexpr WrappedIterator(
1189 const WrappedIterator<OtherIterator, OtherElementType>& it) noexcept
1190 : it_(it.base()) {}
1191
1192 constexpr reference operator*() const noexcept { return *it_; }
1193 constexpr pointer operator->() const noexcept { return it_.operator->(); }
1194
1195 constexpr WrappedIterator& operator++() noexcept {
1196 ++it_;
1197 return *this;
1198 }
1199 constexpr WrappedIterator operator++(int) noexcept {
1200 WrappedIterator result(*this);
1201 ++(*this);
1202 return result;
1203 }
1204
1205 constexpr WrappedIterator& operator--() noexcept {
1206 --it_;
1207 return *this;
1208 }
1209 constexpr WrappedIterator operator--(int) noexcept {
1210 WrappedIterator result(*this);
1211 --(*this);
1212 return result;
1213 }
1214 constexpr WrappedIterator operator+(difference_type n) const noexcept {
1215 WrappedIterator result(*this);
1216 result += n;
1217 return result;
1218 }
1219 constexpr WrappedIterator& operator+=(difference_type n) noexcept {
1220 it_ += n;
1221 return *this;
1222 }
1223 constexpr WrappedIterator operator-(difference_type n) const noexcept {
1224 return *this + (-n);
1225 }
1226 constexpr WrappedIterator& operator-=(difference_type n) noexcept {
1227 *this += -n;
1228 return *this;
1229 }
1230 constexpr reference operator[](difference_type n) const noexcept {
1231 return it_[n];
1232 }
1233
1234 constexpr Iterator base() const noexcept { return it_; }
1235
1236 private:
1237 template <typename OtherIterator, typename OtherElementType>
1238 friend class WrappedIterator;
1239
1240 private:
1241 Iterator it_;
1242 };
1243
1244 template <typename Iterator, typename ElementType, typename OtherIterator,
1245 typename OtherElementType>
1246 constexpr bool operator==(
1247 const WrappedIterator<Iterator, ElementType>& x,
1248 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1249 return x.base() == y.base();
1250 }
1251
1252 template <typename Iterator, typename ElementType, typename OtherIterator,
1253 typename OtherElementType>
1254 constexpr bool operator<(
1255 const WrappedIterator<Iterator, ElementType>& x,
1256 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1257 return x.base() < y.base();
1258 }
1259
1260 template <typename Iterator, typename ElementType, typename OtherIterator,
1261 typename OtherElementType>
1262 constexpr bool operator!=(
1263 const WrappedIterator<Iterator, ElementType>& x,
1264 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1265 return !(x == y);
1266 }
1267
1268 template <typename Iterator, typename ElementType, typename OtherIterator,
1269 typename OtherElementType>
1270 constexpr bool operator>(
1271 const WrappedIterator<Iterator, ElementType>& x,
1272 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1273 return y < x;
1274 }
1275
1276 template <typename Iterator, typename ElementType, typename OtherIterator,
1277 typename OtherElementType>
1278 constexpr bool operator>=(
1279 const WrappedIterator<Iterator, ElementType>& x,
1280 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1281 return !(x < y);
1282 }
1283
1284 template <typename Iterator, typename ElementType, typename OtherIterator,
1285 typename OtherElementType>
1286 constexpr bool operator<=(
1287 const WrappedIterator<Iterator, ElementType>& x,
1288 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept {
1289 return !(y < x);
1290 }
1291
1292 template <typename Iterator, typename ElementType, typename OtherIterator,
1293 typename OtherElementType>
1294 constexpr auto operator-(
1295 const WrappedIterator<Iterator, ElementType>& x,
1296 const WrappedIterator<OtherIterator, OtherElementType>& y) noexcept
1297 -> decltype(x.base() - y.base()) {
1298 return x.base() - y.base();
1299 }
1300
1301 template <typename Iterator, typename ElementType>
1302 constexpr WrappedIterator<Iterator> operator+(
1303 typename WrappedIterator<Iterator, ElementType>::difference_type n,
1304 const WrappedIterator<Iterator, ElementType>& x) noexcept {
1305 x += n;
1306 return x;
1307 }
1308
1309
1310
1311
1312 class ValueHelper final {
1313 public:
1314 #ifdef V8_ENABLE_DIRECT_LOCAL
1315 static constexpr Address kTaggedNullAddress = 1;
1316 static constexpr Address kEmpty = kTaggedNullAddress;
1317 #else
1318 static constexpr Address kEmpty = kNullAddress;
1319 #endif
1320
1321 template <typename T>
1322 V8_INLINE static bool IsEmpty(T* value) {
1323 return reinterpret_cast<Address>(value) == kEmpty;
1324 }
1325
1326
1327
1328
1329 template <template <typename T, typename... Ms> typename H, typename T,
1330 typename... Ms>
1331 V8_INLINE static T* HandleAsValue(const H<T, Ms...>& handle) {
1332 return handle.template value<T>();
1333 }
1334
1335 #ifdef V8_ENABLE_DIRECT_LOCAL
1336
1337 template <typename T>
1338 V8_INLINE static Address ValueAsAddress(const T* value) {
1339 return reinterpret_cast<Address>(value);
1340 }
1341
1342 template <typename T, bool check_null = true, typename S>
1343 V8_INLINE static T* SlotAsValue(S* slot) {
1344 if (check_null && slot == nullptr) {
1345 return reinterpret_cast<T*>(kTaggedNullAddress);
1346 }
1347 return *reinterpret_cast<T**>(slot);
1348 }
1349
1350 #else
1351
1352 template <typename T>
1353 V8_INLINE static Address ValueAsAddress(const T* value) {
1354 return *reinterpret_cast<const Address*>(value);
1355 }
1356
1357 template <typename T, bool check_null = true, typename S>
1358 V8_INLINE static T* SlotAsValue(S* slot) {
1359 return reinterpret_cast<T*>(slot);
1360 }
1361
1362 #endif
1363 };
1364
1365
1366
1367
1368 class HandleHelper final {
1369 public:
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380 template <typename T1, typename T2>
1381 V8_INLINE static bool EqualHandles(const T1& lhs, const T2& rhs) {
1382 if (lhs.IsEmpty()) return rhs.IsEmpty();
1383 if (rhs.IsEmpty()) return false;
1384 return lhs.ptr() == rhs.ptr();
1385 }
1386
1387 static V8_EXPORT bool IsOnStack(const void* ptr);
1388 static V8_EXPORT void VerifyOnStack(const void* ptr);
1389 static V8_EXPORT void VerifyOnMainThread();
1390 };
1391
1392 V8_EXPORT void VerifyHandleIsNonEmpty(bool is_empty);
1393
1394 }
1395 }
1396
1397 #endif