libv8-node 21.7.2.0-x86_64-darwin → 22.5.1.0-x86_64-darwin

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/libv8/node/version.rb +3 -3
  3. data/vendor/v8/include/cppgc/internal/api-constants.h +1 -1
  4. data/vendor/v8/include/cppgc/type-traits.h +25 -4
  5. data/vendor/v8/include/v8-array-buffer.h +6 -0
  6. data/vendor/v8/include/v8-callbacks.h +6 -12
  7. data/vendor/v8/include/v8-container.h +54 -0
  8. data/vendor/v8/include/v8-context.h +51 -22
  9. data/vendor/v8/include/v8-embedder-heap.h +19 -3
  10. data/vendor/v8/include/v8-embedder-state-scope.h +2 -1
  11. data/vendor/v8/include/v8-exception.h +15 -9
  12. data/vendor/v8/include/v8-fast-api-calls.h +35 -26
  13. data/vendor/v8/include/v8-forward.h +1 -0
  14. data/vendor/v8/include/v8-function-callback.h +129 -20
  15. data/vendor/v8/include/v8-handle-base.h +32 -80
  16. data/vendor/v8/include/v8-inspector.h +16 -24
  17. data/vendor/v8/include/v8-internal.h +472 -65
  18. data/vendor/v8/include/v8-isolate.h +86 -51
  19. data/vendor/v8/include/v8-local-handle.h +257 -31
  20. data/vendor/v8/include/v8-memory-span.h +157 -2
  21. data/vendor/v8/include/v8-message.h +22 -3
  22. data/vendor/v8/include/v8-metrics.h +1 -0
  23. data/vendor/v8/include/v8-object.h +29 -10
  24. data/vendor/v8/include/v8-persistent-handle.h +5 -3
  25. data/vendor/v8/include/v8-platform.h +81 -44
  26. data/vendor/v8/include/v8-script.h +61 -11
  27. data/vendor/v8/include/v8-snapshot.h +94 -23
  28. data/vendor/v8/include/v8-statistics.h +10 -24
  29. data/vendor/v8/include/v8-template.h +410 -131
  30. data/vendor/v8/include/v8-traced-handle.h +81 -46
  31. data/vendor/v8/include/v8-typed-array.h +115 -7
  32. data/vendor/v8/include/v8-util.h +13 -12
  33. data/vendor/v8/include/v8-value.h +92 -4
  34. data/vendor/v8/include/v8-version.h +4 -4
  35. data/vendor/v8/include/v8config.h +35 -10
  36. data/vendor/v8/x86_64-darwin/libv8/obj/libv8_monolith.a +0 -0
  37. metadata +3 -3
@@ -10,9 +10,11 @@
10
10
  #include <string.h>
11
11
 
12
12
  #include <atomic>
13
+ #include <iterator>
14
+ #include <memory>
13
15
  #include <type_traits>
14
16
 
15
- #include "v8config.h" // NOLINT(build/include_directory)
17
+ #include "v8config.h" // NOLINT(build/include_directory)
16
18
 
17
19
  namespace v8 {
18
20
 
@@ -23,6 +25,7 @@ class Isolate;
23
25
 
24
26
  namespace internal {
25
27
 
28
+ class Heap;
26
29
  class Isolate;
27
30
 
28
31
  typedef uintptr_t Address;
@@ -172,11 +175,15 @@ using SandboxedPointer_t = Address;
172
175
  #ifdef V8_ENABLE_SANDBOX
173
176
 
174
177
  // Size of the sandbox, excluding the guard regions surrounding it.
175
- #ifdef V8_TARGET_OS_ANDROID
178
+ #if defined(V8_TARGET_OS_ANDROID)
176
179
  // On Android, most 64-bit devices seem to be configured with only 39 bits of
177
180
  // virtual address space for userspace. As such, limit the sandbox to 128GB (a
178
181
  // quarter of the total available address space).
179
182
  constexpr size_t kSandboxSizeLog2 = 37; // 128 GB
183
+ #elif defined(V8_TARGET_ARCH_LOONG64)
184
+ // Some Linux distros on LoongArch64 configured with only 40 bits of virtual
185
+ // address space for userspace. Limit the sandbox to 256GB here.
186
+ constexpr size_t kSandboxSizeLog2 = 38; // 256 GB
180
187
  #else
181
188
  // Everywhere else use a 1TB sandbox.
182
189
  constexpr size_t kSandboxSizeLog2 = 40; // 1 TB
@@ -418,7 +425,7 @@ constexpr uint64_t kAllExternalPointerTypeTags[] = {
418
425
  /* it is the Embedder's responsibility to ensure type safety (against */ \
419
426
  /* substitution) and lifetime validity of these objects. */ \
420
427
  V(kExternalObjectValueTag, TAG(13)) \
421
- V(kCallHandlerInfoCallbackTag, TAG(14)) \
428
+ V(kFunctionTemplateInfoCallbackTag, TAG(14)) \
422
429
  V(kAccessorInfoGetterTag, TAG(15)) \
423
430
  V(kAccessorInfoSetterTag, TAG(16)) \
424
431
  V(kWasmInternalFunctionCallTargetTag, TAG(17)) \
@@ -465,6 +472,15 @@ V8_INLINE static constexpr bool IsSharedExternalPointerType(
465
472
  return tag >= kFirstSharedTag && tag <= kLastSharedTag;
466
473
  }
467
474
 
475
+ // True if the external pointer may live in a read-only object, in which case
476
+ // the table entry will be in the shared read-only segment of the external
477
+ // pointer table.
478
+ V8_INLINE static constexpr bool IsMaybeReadOnlyExternalPointerType(
479
+ ExternalPointerTag tag) {
480
+ return tag == kAccessorInfoGetterTag || tag == kAccessorInfoSetterTag ||
481
+ tag == kFunctionTemplateInfoCallbackTag;
482
+ }
483
+
468
484
  // Sanity checks.
469
485
  #define CHECK_SHARED_EXTERNAL_POINTER_TAGS(Tag, ...) \
470
486
  static_assert(IsSharedExternalPointerType(Tag));
@@ -484,70 +500,122 @@ PER_ISOLATE_EXTERNAL_POINTER_TAGS(CHECK_NON_SHARED_EXTERNAL_POINTER_TAGS)
484
500
  // Indirect Pointers.
485
501
  //
486
502
  // When the sandbox is enabled, indirect pointers are used to reference
487
- // HeapObjects that live outside of the sandbox (but are still managed through
488
- // the GC). When object A references an object B through an indirect pointer,
489
- // object A will contain a IndirectPointerHandle, i.e. a shifted 32-bit index,
490
- // which identifies an entry in a pointer table (such as the CodePointerTable).
491
- // This table entry then contains the actual pointer to object B. Further,
492
- // object B owns this pointer table entry, and it is responsible for updating
493
- // the "self-pointer" in the entry when it is relocated in memory. This way, in
494
- // contrast to "normal" pointers, indirect pointers never need to be tracked by
495
- // the GC (i.e. there is no remembered set for them).
496
- // Currently there is only one type of object referenced through indirect
497
- // pointers (Code objects), but once there are different types of such objects,
498
- // the pointer table entry would probably also contain the type of the target
499
- // object (e.g. by XORing the instance type into the top bits of the pointer).
503
+ // HeapObjects that live outside of the sandbox (but are still managed by V8's
504
+ // garbage collector). When object A references an object B through an indirect
505
+ // pointer, object A will contain a IndirectPointerHandle, i.e. a shifted
506
+ // 32-bit index, which identifies an entry in a pointer table (either the
507
+ // trusted pointer table for TrustedObjects, or the code pointer table if it is
508
+ // a Code object). This table entry then contains the actual pointer to object
509
+ // B. Further, object B owns this pointer table entry, and it is responsible
510
+ // for updating the "self-pointer" in the entry when it is relocated in memory.
511
+ // This way, in contrast to "normal" pointers, indirect pointers never need to
512
+ // be tracked by the GC (i.e. there is no remembered set for them).
513
+ // These pointers do not exist when the sandbox is disabled.
500
514
 
501
515
  // An IndirectPointerHandle represents a 32-bit index into a pointer table.
502
516
  using IndirectPointerHandle = uint32_t;
503
517
 
504
- // The indirect pointer handles are stores shifted to the left by this amount
505
- // to guarantee that they are smaller than the maximum table size.
506
- constexpr uint32_t kIndirectPointerHandleShift = 6;
507
-
508
518
  // A null handle always references an entry that contains nullptr.
509
519
  constexpr IndirectPointerHandle kNullIndirectPointerHandle = 0;
510
520
 
511
- // Currently only Code objects can be referenced through indirect pointers and
512
- // various places rely on that assumption. They will all static_assert against
513
- // this constant to make them easy to find and fix once we reference other types
514
- // of objects indirectly.
515
- constexpr bool kAllIndirectPointerObjectsAreCode = true;
521
+ // When the sandbox is enabled, indirect pointers are used to implement:
522
+ // - TrustedPointers: an indirect pointer using the trusted pointer table (TPT)
523
+ // and referencing a TrustedObject in one of the trusted heap spaces.
524
+ // - CodePointers, an indirect pointer using the code pointer table (CPT) and
525
+ // referencing a Code object together with its instruction stream.
526
+
527
+ //
528
+ // Trusted Pointers.
529
+ //
530
+ // A pointer to a TrustedObject.
531
+ // When the sandbox is enabled, these are indirect pointers using the trusted
532
+ // pointer table (TPT). They are used to reference trusted objects (located in
533
+ // one of V8's trusted heap spaces, outside of the sandbox) from inside the
534
+ // sandbox in a memory-safe way. When the sandbox is disabled, these are
535
+ // regular tagged pointers.
536
+ using TrustedPointerHandle = IndirectPointerHandle;
537
+
538
+ // The size of the virtual memory reservation for the trusted pointer table.
539
+ // As with the external pointer table, a maximum table size in combination with
540
+ // shifted indices allows omitting bounds checks.
541
+ constexpr size_t kTrustedPointerTableReservationSize = 64 * MB;
542
+
543
+ // The trusted pointer handles are stores shifted to the left by this amount
544
+ // to guarantee that they are smaller than the maximum table size.
545
+ constexpr uint32_t kTrustedPointerHandleShift = 9;
546
+
547
+ // A null handle always references an entry that contains nullptr.
548
+ constexpr TrustedPointerHandle kNullTrustedPointerHandle =
549
+ kNullIndirectPointerHandle;
550
+
551
+ // The maximum number of entries in an trusted pointer table.
552
+ constexpr int kTrustedPointerTableEntrySize = 8;
553
+ constexpr int kTrustedPointerTableEntrySizeLog2 = 3;
554
+ constexpr size_t kMaxTrustedPointers =
555
+ kTrustedPointerTableReservationSize / kTrustedPointerTableEntrySize;
556
+ static_assert((1 << (32 - kTrustedPointerHandleShift)) == kMaxTrustedPointers,
557
+ "kTrustedPointerTableReservationSize and "
558
+ "kTrustedPointerHandleShift don't match");
516
559
 
517
560
  //
518
561
  // Code Pointers.
519
562
  //
520
- // When the sandbox is enabled, Code objects are referenced from inside the
521
- // sandbox through indirect pointers that reference entries in the code pointer
522
- // table (CPT). Each entry in the CPT contains both a pointer to a Code object
523
- // as well as a pointer to the Code's entrypoint. This allows calling/jumping
524
- // into Code with one fewer memory access (compared to the case where the
525
- // entrypoint pointer needs to be loaded from the Code object).
526
- // As such, a CodePointerHandle can be used both to obtain the referenced Code
527
- // object and to directly load its entrypoint pointer.
563
+ // A pointer to a Code object.
564
+ // Essentially a specialized version of a trusted pointer that (when the
565
+ // sandbox is enabled) uses the code pointer table (CPT) instead of the TPT.
566
+ // Each entry in the CPT contains both a pointer to a Code object as well as a
567
+ // pointer to the Code's entrypoint. This allows calling/jumping into Code with
568
+ // one fewer memory access (compared to the case where the entrypoint pointer
569
+ // first needs to be loaded from the Code object). As such, a CodePointerHandle
570
+ // can be used both to obtain the referenced Code object and to directly load
571
+ // its entrypoint.
572
+ //
573
+ // When the sandbox is disabled, these are regular tagged pointers.
528
574
  using CodePointerHandle = IndirectPointerHandle;
529
- constexpr uint32_t kCodePointerHandleShift = kIndirectPointerHandleShift;
530
- constexpr CodePointerHandle kNullCodePointerHandle = 0;
531
575
 
532
- // The size of the virtual memory reservation for code pointer table.
533
- // This determines the maximum number of entries in a table. Using a maximum
534
- // size allows omitting bounds checks on table accesses if the indices are
535
- // guaranteed (e.g. through shifting) to be below the maximum index. This
536
- // value must be a power of two.
537
- constexpr size_t kCodePointerTableReservationSize = 1 * GB;
576
+ // The size of the virtual memory reservation for the code pointer table.
577
+ // As with the other tables, a maximum table size in combination with shifted
578
+ // indices allows omitting bounds checks.
579
+ constexpr size_t kCodePointerTableReservationSize = 16 * MB;
538
580
 
539
- // The maximum number of entries in an external pointer table.
581
+ // Code pointer handles are shifted by a different amount than indirect pointer
582
+ // handles as the tables have a different maximum size.
583
+ constexpr uint32_t kCodePointerHandleShift = 12;
584
+
585
+ // A null handle always references an entry that contains nullptr.
586
+ constexpr CodePointerHandle kNullCodePointerHandle = kNullIndirectPointerHandle;
587
+
588
+ // It can sometimes be necessary to distinguish a code pointer handle from a
589
+ // trusted pointer handle. A typical example would be a union trusted pointer
590
+ // field that can refer to both Code objects and other trusted objects. To
591
+ // support these use-cases, we use a simple marking scheme where some of the
592
+ // low bits of a code pointer handle are set, while they will be unset on a
593
+ // trusted pointer handle. This way, the correct table to resolve the handle
594
+ // can be determined even in the absence of a type tag.
595
+ constexpr uint32_t kCodePointerHandleMarker = 0x1;
596
+ static_assert(kCodePointerHandleShift > 0);
597
+ static_assert(kTrustedPointerHandleShift > 0);
598
+
599
+ // The maximum number of entries in a code pointer table.
540
600
  constexpr int kCodePointerTableEntrySize = 16;
541
601
  constexpr int kCodePointerTableEntrySizeLog2 = 4;
542
602
  constexpr size_t kMaxCodePointers =
543
603
  kCodePointerTableReservationSize / kCodePointerTableEntrySize;
544
604
  static_assert(
545
- (1 << (32 - kIndirectPointerHandleShift)) == kMaxCodePointers,
605
+ (1 << (32 - kCodePointerHandleShift)) == kMaxCodePointers,
546
606
  "kCodePointerTableReservationSize and kCodePointerHandleShift don't match");
547
607
 
548
608
  constexpr int kCodePointerTableEntryEntrypointOffset = 0;
549
609
  constexpr int kCodePointerTableEntryCodeObjectOffset = 8;
550
610
 
611
+ // Constants that can be used to mark places that should be modified once
612
+ // certain types of objects are moved out of the sandbox and into trusted space.
613
+ constexpr bool kRuntimeGeneratedCodeObjectsLiveInTrustedSpace = true;
614
+ constexpr bool kBuiltinCodeObjectsLiveInTrustedSpace = false;
615
+ constexpr bool kAllCodeObjectsLiveInTrustedSpace =
616
+ kRuntimeGeneratedCodeObjectsLiveInTrustedSpace &&
617
+ kBuiltinCodeObjectsLiveInTrustedSpace;
618
+
551
619
  // {obj} must be the raw tagged pointer representation of a HeapObject
552
620
  // that's guaranteed to never be in ReadOnlySpace.
553
621
  V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
@@ -595,6 +663,9 @@ class Internals {
595
663
 
596
664
  static const uint32_t kNumIsolateDataSlots = 4;
597
665
  static const int kStackGuardSize = 8 * kApiSystemPointerSize;
666
+ static const int kNumberOfBooleanFlags = 6;
667
+ static const int kErrorMessageParamSize = 1;
668
+ static const int kTablesAlignmentPaddingSize = 1;
598
669
  static const int kBuiltinTier0EntryTableSize = 7 * kApiSystemPointerSize;
599
670
  static const int kBuiltinTier0TableSize = 7 * kApiSystemPointerSize;
600
671
  static const int kLinearAllocationAreaSize = 3 * kApiSystemPointerSize;
@@ -602,9 +673,11 @@ class Internals {
602
673
  static const int kHandleScopeDataSize =
603
674
  2 * kApiSystemPointerSize + 2 * kApiInt32Size;
604
675
 
605
- // ExternalPointerTable layout guarantees.
676
+ // ExternalPointerTable and TrustedPointerTable layout guarantees.
606
677
  static const int kExternalPointerTableBasePointerOffset = 0;
607
678
  static const int kExternalPointerTableSize = 2 * kApiSystemPointerSize;
679
+ static const int kTrustedPointerTableSize = 2 * kApiSystemPointerSize;
680
+ static const int kTrustedPointerTableBasePointerOffset = 0;
608
681
 
609
682
  // IsolateData layout guarantees.
610
683
  static const int kIsolateCageBaseOffset = 0;
@@ -612,16 +685,23 @@ class Internals {
612
685
  kIsolateCageBaseOffset + kApiSystemPointerSize;
613
686
  static const int kVariousBooleanFlagsOffset =
614
687
  kIsolateStackGuardOffset + kStackGuardSize;
615
- static const int kBuiltinTier0EntryTableOffset =
616
- kVariousBooleanFlagsOffset + 8;
688
+ static const int kErrorMessageParamOffset =
689
+ kVariousBooleanFlagsOffset + kNumberOfBooleanFlags;
690
+ static const int kBuiltinTier0EntryTableOffset = kErrorMessageParamOffset +
691
+ kErrorMessageParamSize +
692
+ kTablesAlignmentPaddingSize;
617
693
  static const int kBuiltinTier0TableOffset =
618
694
  kBuiltinTier0EntryTableOffset + kBuiltinTier0EntryTableSize;
619
695
  static const int kNewAllocationInfoOffset =
620
696
  kBuiltinTier0TableOffset + kBuiltinTier0TableSize;
621
697
  static const int kOldAllocationInfoOffset =
622
698
  kNewAllocationInfoOffset + kLinearAllocationAreaSize;
699
+
700
+ static const int kFastCCallAlignmentPaddingSize =
701
+ kApiSystemPointerSize == 8 ? 0 : kApiSystemPointerSize;
623
702
  static const int kIsolateFastCCallCallerFpOffset =
624
- kOldAllocationInfoOffset + kLinearAllocationAreaSize;
703
+ kOldAllocationInfoOffset + kLinearAllocationAreaSize +
704
+ kFastCCallAlignmentPaddingSize;
625
705
  static const int kIsolateFastCCallCallerPcOffset =
626
706
  kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
627
707
  static const int kIsolateFastApiCallTargetOffset =
@@ -639,34 +719,55 @@ class Internals {
639
719
  kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
640
720
  static const int kIsolateSharedExternalPointerTableAddressOffset =
641
721
  kIsolateExternalPointerTableOffset + kExternalPointerTableSize;
722
+ #ifdef V8_ENABLE_SANDBOX
723
+ static const int kIsolateTrustedCageBaseOffset =
724
+ kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
725
+ static const int kIsolateTrustedPointerTableOffset =
726
+ kIsolateTrustedCageBaseOffset + kApiSystemPointerSize;
727
+ static const int kIsolateApiCallbackThunkArgumentOffset =
728
+ kIsolateTrustedPointerTableOffset + kTrustedPointerTableSize;
729
+ #else
642
730
  static const int kIsolateApiCallbackThunkArgumentOffset =
643
731
  kIsolateSharedExternalPointerTableAddressOffset + kApiSystemPointerSize;
732
+ #endif // V8_ENABLE_SANDBOX
644
733
  #else
645
734
  static const int kIsolateApiCallbackThunkArgumentOffset =
646
735
  kIsolateEmbedderDataOffset + kNumIsolateDataSlots * kApiSystemPointerSize;
647
- #endif
648
- static const int kIsolateRootsOffset =
736
+ #endif // V8_COMPRESS_POINTERS
737
+ static const int kContinuationPreservedEmbedderDataOffset =
649
738
  kIsolateApiCallbackThunkArgumentOffset + kApiSystemPointerSize;
650
739
 
740
+ static const int kWasm64OOBOffsetAlignmentPaddingSize = 0;
741
+ static const int kWasm64OOBOffsetOffset =
742
+ kContinuationPreservedEmbedderDataOffset + kApiSystemPointerSize +
743
+ kWasm64OOBOffsetAlignmentPaddingSize;
744
+ static const int kIsolateRootsOffset =
745
+ kWasm64OOBOffsetOffset + sizeof(int64_t);
746
+
651
747
  #if V8_STATIC_ROOTS_BOOL
652
748
 
653
- // These constants need to be initialized in api.cc.
749
+ // These constants are copied from static-roots.h and guarded by static asserts.
654
750
  #define EXPORTED_STATIC_ROOTS_PTR_LIST(V) \
655
- V(UndefinedValue) \
656
- V(NullValue) \
657
- V(TrueValue) \
658
- V(FalseValue) \
659
- V(EmptyString) \
660
- V(TheHoleValue)
751
+ V(UndefinedValue, 0x69) \
752
+ V(NullValue, 0x85) \
753
+ V(TrueValue, 0xc9) \
754
+ V(FalseValue, 0xad) \
755
+ V(EmptyString, 0xa1) \
756
+ V(TheHoleValue, 0x719)
661
757
 
662
758
  using Tagged_t = uint32_t;
663
759
  struct StaticReadOnlyRoot {
664
- #define DEF_ROOT(name) V8_EXPORT static const Tagged_t k##name;
760
+ #define DEF_ROOT(name, value) static constexpr Tagged_t k##name = value;
665
761
  EXPORTED_STATIC_ROOTS_PTR_LIST(DEF_ROOT)
666
762
  #undef DEF_ROOT
667
763
 
668
- V8_EXPORT static const Tagged_t kFirstStringMap;
669
- V8_EXPORT static const Tagged_t kLastStringMap;
764
+ static constexpr Tagged_t kFirstStringMap = 0xe5;
765
+ static constexpr Tagged_t kLastStringMap = 0x47d;
766
+
767
+ #define PLUSONE(...) +1
768
+ static constexpr size_t kNumberOfExportedStaticRoots =
769
+ 2 + EXPORTED_STATIC_ROOTS_PTR_LIST(PLUSONE);
770
+ #undef PLUSONE
670
771
  };
671
772
 
672
773
  #endif // V8_STATIC_ROOTS_BOOL
@@ -683,8 +784,6 @@ class Internals {
683
784
  static const int kNodeStateMask = 0x3;
684
785
  static const int kNodeStateIsWeakValue = 2;
685
786
 
686
- static const int kTracedNodeClassIdOffset = kApiSystemPointerSize;
687
-
688
787
  static const int kFirstNonstringType = 0x80;
689
788
  static const int kOddballType = 0x83;
690
789
  static const int kForeignType = 0xcc;
@@ -692,8 +791,13 @@ class Internals {
692
791
  static const int kJSObjectType = 0x421;
693
792
  static const int kFirstJSApiObjectType = 0x422;
694
793
  static const int kLastJSApiObjectType = 0x80A;
794
+ // Defines a range [kFirstEmbedderJSApiObjectType, kJSApiObjectTypesCount]
795
+ // of JSApiObject instance type values that an embedder can use.
796
+ static const int kFirstEmbedderJSApiObjectType = 0;
797
+ static const int kLastEmbedderJSApiObjectType =
798
+ kLastJSApiObjectType - kFirstJSApiObjectType;
695
799
 
696
- static const int kUndefinedOddballKind = 5;
800
+ static const int kUndefinedOddballKind = 4;
697
801
  static const int kNullOddballKind = 3;
698
802
 
699
803
  // Constants used by PropertyCallbackInfo to check if we should throw when an
@@ -763,6 +867,15 @@ class Internals {
763
867
  return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
764
868
  }
765
869
 
870
+ V8_INLINE static Address LoadMap(Address obj) {
871
+ if (!HasHeapObjectTag(obj)) return kNullAddress;
872
+ Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
873
+ #ifdef V8_MAP_PACKING
874
+ map = UnpackMapWord(map);
875
+ #endif
876
+ return map;
877
+ }
878
+
766
879
  V8_INLINE static int GetOddballKind(Address obj) {
767
880
  return SmiValue(ReadTaggedSignedField(obj, kOddballKindOffset));
768
881
  }
@@ -836,15 +949,15 @@ class Internals {
836
949
  Address base = *reinterpret_cast<Address*>(
837
950
  reinterpret_cast<uintptr_t>(isolate) + kIsolateCageBaseOffset);
838
951
  switch (index) {
839
- #define DECOMPRESS_ROOT(name) \
840
- case k##name##RootIndex: \
952
+ #define DECOMPRESS_ROOT(name, ...) \
953
+ case k##name##RootIndex: \
841
954
  return base + StaticReadOnlyRoot::k##name;
842
955
  EXPORTED_STATIC_ROOTS_PTR_LIST(DECOMPRESS_ROOT)
843
956
  #undef DECOMPRESS_ROOT
957
+ #undef EXPORTED_STATIC_ROOTS_PTR_LIST
844
958
  default:
845
959
  break;
846
960
  }
847
- #undef EXPORTED_STATIC_ROOTS_PTR_LIST
848
961
  #endif // V8_STATIC_ROOTS_BOOL
849
962
  return *GetRootSlot(isolate, index);
850
963
  }
@@ -943,6 +1056,10 @@ class Internals {
943
1056
  return addr & -static_cast<intptr_t>(kPtrComprCageBaseAlignment);
944
1057
  }
945
1058
 
1059
+ V8_INLINE static uint32_t CompressTagged(Address value) {
1060
+ return static_cast<uint32_t>(value);
1061
+ }
1062
+
946
1063
  V8_INLINE static Address DecompressTaggedField(Address heap_object_ptr,
947
1064
  uint32_t value) {
948
1065
  Address base = GetPtrComprCageBaseFromOnHeapAddress(heap_object_ptr);
@@ -984,6 +1101,296 @@ class BackingStoreBase {};
984
1101
  // This is needed for histograms sampling garbage collection reasons.
985
1102
  constexpr int kGarbageCollectionReasonMaxValue = 27;
986
1103
 
1104
+ // Base class for the address block allocator compatible with standard
1105
+ // containers, which registers its allocated range as strong roots.
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
+ // Allocate/deallocate a range of n elements of type internal::Address.
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
+ // The general version of this template behaves just as std::allocator, with
1130
+ // the exception that the constructor takes the isolate as parameter. Only
1131
+ // specialized versions, e.g., internal::StrongRootAllocator<internal::Address>
1132
+ // and internal::StrongRootAllocator<v8::Local<T>> register the allocated range
1133
+ // as strong roots.
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
+ // A class of iterators that wrap some different iterator type.
1152
+ // If specified, ElementType is the type of element accessed by the wrapper
1153
+ // iterator; in this case, the actual reference and pointer types of Iterator
1154
+ // must be convertible to ElementType& and ElementType*, respectively.
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
+ // Helper functions about values contained in handles.
1310
+ // A value is either an indirect pointer or a direct pointer, depending on
1311
+ // whether direct local support is enabled.
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 // V8_ENABLE_DIRECT_LOCAL
1320
+
1321
+ template <typename T>
1322
+ V8_INLINE static bool IsEmpty(T* value) {
1323
+ return reinterpret_cast<Address>(value) == kEmpty;
1324
+ }
1325
+
1326
+ // Returns a handle's "value" for all kinds of abstract handles. For Local,
1327
+ // it is equivalent to `*handle`. The variadic parameters support handle
1328
+ // types with extra type parameters, like `Persistent<T, M>`.
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 // !V8_ENABLE_DIRECT_LOCAL
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 // V8_ENABLE_DIRECT_LOCAL
1363
+ };
1364
+
1365
+ /**
1366
+ * Helper functions about handles.
1367
+ */
1368
+ class HandleHelper final {
1369
+ public:
1370
+ /**
1371
+ * Checks whether two handles are equal.
1372
+ * They are equal iff they are both empty or they are both non-empty and the
1373
+ * objects to which they refer are physically equal.
1374
+ *
1375
+ * If both handles refer to JS objects, this is the same as strict equality.
1376
+ * For primitives, such as numbers or strings, a `false` return value does not
1377
+ * indicate that the values aren't equal in the JavaScript sense.
1378
+ * Use `Value::StrictEquals()` to check primitives for equality.
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
+
987
1394
  } // namespace internal
988
1395
  } // namespace v8
989
1396