libv8-node 21.7.2.0-x86_64-linux → 22.5.1.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
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-linux/libv8/obj/libv8_monolith.a +0 -0
  37. metadata +2 -2
@@ -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