libv8-node 15.14.0.1-x86_64-linux → 16.10.0.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libv8-node/location.rb +1 -1
  3. data/ext/libv8-node/paths.rb +1 -1
  4. data/lib/libv8/node/version.rb +3 -3
  5. data/vendor/v8/include/cppgc/allocation.h +104 -45
  6. data/vendor/v8/include/cppgc/common.h +9 -6
  7. data/vendor/v8/include/cppgc/cross-thread-persistent.h +384 -0
  8. data/vendor/v8/include/cppgc/custom-space.h +37 -2
  9. data/vendor/v8/include/cppgc/default-platform.h +47 -48
  10. data/vendor/v8/include/cppgc/ephemeron-pair.h +30 -0
  11. data/vendor/v8/include/cppgc/explicit-management.h +82 -0
  12. data/vendor/v8/include/cppgc/garbage-collected.h +4 -3
  13. data/vendor/v8/include/cppgc/heap-consistency.h +236 -0
  14. data/vendor/v8/include/cppgc/heap-state.h +70 -0
  15. data/vendor/v8/include/cppgc/heap-statistics.h +120 -0
  16. data/vendor/v8/include/cppgc/heap.h +68 -6
  17. data/vendor/v8/include/cppgc/internal/api-constants.h +3 -3
  18. data/vendor/v8/include/cppgc/internal/caged-heap-local-data.h +2 -1
  19. data/vendor/v8/include/cppgc/internal/compiler-specific.h +2 -2
  20. data/vendor/v8/include/cppgc/internal/gc-info.h +44 -13
  21. data/vendor/v8/include/cppgc/internal/name-trait.h +111 -0
  22. data/vendor/v8/include/cppgc/internal/persistent-node.h +57 -1
  23. data/vendor/v8/include/cppgc/internal/pointer-policies.h +69 -28
  24. data/vendor/v8/include/cppgc/internal/prefinalizer-handler.h +1 -1
  25. data/vendor/v8/include/cppgc/internal/write-barrier.h +353 -35
  26. data/vendor/v8/include/cppgc/liveness-broker.h +7 -1
  27. data/vendor/v8/include/cppgc/macros.h +2 -0
  28. data/vendor/v8/include/cppgc/member.h +85 -25
  29. data/vendor/v8/include/cppgc/name-provider.h +65 -0
  30. data/vendor/v8/include/cppgc/object-size-trait.h +58 -0
  31. data/vendor/v8/include/cppgc/persistent.h +33 -9
  32. data/vendor/v8/include/cppgc/platform.h +48 -25
  33. data/vendor/v8/include/cppgc/prefinalizer.h +1 -1
  34. data/vendor/v8/include/cppgc/process-heap-statistics.h +36 -0
  35. data/vendor/v8/include/cppgc/sentinel-pointer.h +32 -0
  36. data/vendor/v8/include/cppgc/source-location.h +2 -1
  37. data/vendor/v8/include/cppgc/testing.h +99 -0
  38. data/vendor/v8/include/cppgc/trace-trait.h +8 -3
  39. data/vendor/v8/include/cppgc/type-traits.h +157 -19
  40. data/vendor/v8/include/cppgc/visitor.h +187 -23
  41. data/vendor/v8/include/libplatform/libplatform.h +11 -0
  42. data/vendor/v8/include/libplatform/v8-tracing.h +2 -0
  43. data/vendor/v8/include/v8-cppgc.h +258 -159
  44. data/vendor/v8/include/v8-fast-api-calls.h +562 -159
  45. data/vendor/v8/include/v8-inspector.h +23 -2
  46. data/vendor/v8/include/v8-internal.h +99 -27
  47. data/vendor/v8/include/v8-metrics.h +77 -8
  48. data/vendor/v8/include/v8-platform.h +47 -22
  49. data/vendor/v8/include/v8-profiler.h +75 -11
  50. data/vendor/v8/include/v8-unwinder-state.h +30 -0
  51. data/vendor/v8/include/v8-util.h +1 -1
  52. data/vendor/v8/include/v8-version.h +4 -4
  53. data/vendor/v8/include/v8.h +1192 -642
  54. data/vendor/v8/include/v8config.h +40 -9
  55. data/vendor/v8/{out.gn → x86_64-linux}/libv8/obj/libv8_monolith.a +0 -0
  56. metadata +17 -5
  57. data/vendor/v8/include/cppgc/internal/process-heap.h +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2391e6a843640810095f689167f58f79b20f7c15b7c9fd37e325c7b392dd8ee
4
- data.tar.gz: c2d520d8be63dd5135ebabf332204ff8557842528e154ec57f6644c4886af692
3
+ metadata.gz: 10d9bc2ea31b8588bfdebaa45157ce3de39308f7e12e137bea5f461b2e1f0d40
4
+ data.tar.gz: 8b11e8fac1a8c301136f575e2d6335df3f73e2c4d79b8ca1d9832934f631d8fe
5
5
  SHA512:
6
- metadata.gz: a8c33c4a3f8e2051a3591f17c8aed836cdc86104df073c873a51c193dd87b20b27a22b97ae6dc054637d9623970834ac484fa3d739d6f734d9fbaa6b8874f3f7
7
- data.tar.gz: aa6cd213a304c97fb71c0eea8f58951082d18e1844a018a5fde2543c2b4ccca6f51259ea45f4ac24c1a0ef3f934d445c511acf4e92e676578004321676f3f9d1
6
+ metadata.gz: 30fb9c6db7c0045eabba05f03fe0b4db9ae5b3c3081b847be13e3d09a6a9fe151bfa04af6d608ce0a3c79a670b82db23cd89071232c95eb10d9b4938c9eb3f4f
7
+ data.tar.gz: feffdf7bcf57566b981ea5a767762ef0c8a3c5d81df0467a3602fd45aa9d06309fb5d163490b6654320a0c1f68a26408428f7a21c3828a1103054fd75eb39aa8
@@ -18,7 +18,7 @@ module Libv8::Node
18
18
 
19
19
  def self.load!
20
20
  File.open(Pathname(__FILE__).dirname.join('.location.yml')) do |f|
21
- YAML.load(f) # rubocop:disable Security/YAMLLoad
21
+ YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(f) : YAML.load(f) # rubocop:disable Security/YAMLLoad
22
22
  end
23
23
  end
24
24
 
@@ -13,7 +13,7 @@ module Libv8::Node
13
13
 
14
14
  def object_paths
15
15
  [Shellwords.escape(File.join(vendored_source_path,
16
- 'out.gn',
16
+ Gem::Platform.local.to_s,
17
17
  'libv8',
18
18
  'obj',
19
19
  "libv8_monolith.#{config['LIBEXT']}"))]
@@ -1,7 +1,7 @@
1
1
  module Libv8; end
2
2
 
3
3
  module Libv8::Node
4
- VERSION = '15.14.0.1'.freeze
5
- NODE_VERSION = '15.14.0'.freeze
6
- LIBV8_VERSION = '8.6.395.17'.freeze # from v8/include/v8-version.h
4
+ VERSION = '16.10.0.0'.freeze
5
+ NODE_VERSION = '16.10.0'.freeze
6
+ LIBV8_VERSION = '9.3.345.19'.freeze # from v8/include/v8-version.h
7
7
  end
@@ -5,24 +5,20 @@
5
5
  #ifndef INCLUDE_CPPGC_ALLOCATION_H_
6
6
  #define INCLUDE_CPPGC_ALLOCATION_H_
7
7
 
8
- #include <stdint.h>
9
-
10
8
  #include <atomic>
9
+ #include <cstddef>
10
+ #include <cstdint>
11
+ #include <new>
12
+ #include <type_traits>
11
13
 
12
14
  #include "cppgc/custom-space.h"
13
- #include "cppgc/garbage-collected.h"
14
15
  #include "cppgc/internal/api-constants.h"
15
16
  #include "cppgc/internal/gc-info.h"
17
+ #include "cppgc/type-traits.h"
18
+ #include "v8config.h" // NOLINT(build/include_directory)
16
19
 
17
20
  namespace cppgc {
18
21
 
19
- template <typename T>
20
- class MakeGarbageCollectedTraitBase;
21
-
22
- namespace internal {
23
- class ObjectAllocator;
24
- } // namespace internal
25
-
26
22
  /**
27
23
  * AllocationHandle is used to allocate garbage-collected objects.
28
24
  */
@@ -39,11 +35,32 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal {
39
35
  const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
40
36
  reinterpret_cast<const uint8_t*>(payload) -
41
37
  api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
42
- uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
43
- value = value | api_constants::kFullyConstructedBitMask;
44
- atomic_mutable_bitfield->store(value, std::memory_order_release);
38
+ atomic_mutable_bitfield->fetch_or(api_constants::kFullyConstructedBitMask,
39
+ std::memory_order_release);
45
40
  }
46
41
 
42
+ template <typename U, typename CustomSpace>
43
+ struct SpacePolicy {
44
+ static void* Allocate(AllocationHandle& handle, size_t size) {
45
+ // Custom space.
46
+ static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
47
+ "Custom space must inherit from CustomSpaceBase.");
48
+ return MakeGarbageCollectedTraitInternal::Allocate(
49
+ handle, size, internal::GCInfoTrait<U>::Index(),
50
+ CustomSpace::kSpaceIndex);
51
+ }
52
+ };
53
+
54
+ template <typename U>
55
+ struct SpacePolicy<U, void> {
56
+ static void* Allocate(AllocationHandle& handle, size_t size) {
57
+ // Default space.
58
+ return MakeGarbageCollectedTraitInternal::Allocate(
59
+ handle, size, internal::GCInfoTrait<U>::Index());
60
+ }
61
+ };
62
+
63
+ private:
47
64
  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
48
65
  GCInfoIndex index);
49
66
  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
@@ -65,26 +82,12 @@ template <typename T>
65
82
  class MakeGarbageCollectedTraitBase
66
83
  : private internal::MakeGarbageCollectedTraitInternal {
67
84
  private:
68
- template <typename U, typename CustomSpace>
69
- struct SpacePolicy {
70
- static void* Allocate(AllocationHandle& handle, size_t size) {
71
- // Custom space.
72
- static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
73
- "Custom space must inherit from CustomSpaceBase.");
74
- return internal::MakeGarbageCollectedTraitInternal::Allocate(
75
- handle, size, internal::GCInfoTrait<T>::Index(),
76
- CustomSpace::kSpaceIndex);
77
- }
78
- };
79
-
80
- template <typename U>
81
- struct SpacePolicy<U, void> {
82
- static void* Allocate(AllocationHandle& handle, size_t size) {
83
- // Default space.
84
- return internal::MakeGarbageCollectedTraitInternal::Allocate(
85
- handle, size, internal::GCInfoTrait<T>::Index());
86
- }
87
- };
85
+ static_assert(internal::IsGarbageCollectedType<T>::value,
86
+ "T needs to be a garbage collected object");
87
+ static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
88
+ sizeof(T) <=
89
+ internal::api_constants::kLargeObjectSizeThreshold,
90
+ "GarbageCollectedMixin may not be a large object");
88
91
 
89
92
  protected:
90
93
  /**
@@ -95,9 +98,15 @@ class MakeGarbageCollectedTraitBase
95
98
  * \param size The size that should be reserved for the object.
96
99
  * \returns the memory to construct an object of type T on.
97
100
  */
98
- static void* Allocate(AllocationHandle& handle, size_t size) {
99
- return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(handle,
100
- size);
101
+ V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
102
+ static_assert(
103
+ std::is_base_of<typename T::ParentMostGarbageCollectedType, T>::value,
104
+ "U of GarbageCollected<U> must be a base of T. Check "
105
+ "GarbageCollected<T> base class inheritance.");
106
+ return SpacePolicy<
107
+ typename internal::GCInfoFolding<
108
+ T, typename T::ParentMostGarbageCollectedType>::ResultType,
109
+ typename SpaceTrait<T>::Space>::Allocate(handle, size);
101
110
  }
102
111
 
103
112
  /**
@@ -106,39 +115,70 @@ class MakeGarbageCollectedTraitBase
106
115
  *
107
116
  * \param payload The base pointer the object is allocated at.
108
117
  */
109
- static void MarkObjectAsFullyConstructed(const void* payload) {
118
+ V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
110
119
  internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
111
120
  payload);
112
121
  }
113
122
  };
114
123
 
124
+ /**
125
+ * Passed to MakeGarbageCollected to specify how many bytes should be appended
126
+ * to the allocated object.
127
+ *
128
+ * Example:
129
+ * \code
130
+ * class InlinedArray final : public GarbageCollected<InlinedArray> {
131
+ * public:
132
+ * explicit InlinedArray(size_t bytes) : size(bytes), byte_array(this + 1) {}
133
+ * void Trace(Visitor*) const {}
134
+
135
+ * size_t size;
136
+ * char* byte_array;
137
+ * };
138
+ *
139
+ * auto* inlined_array = MakeGarbageCollected<InlinedArray(
140
+ * GetAllocationHandle(), AdditionalBytes(4), 4);
141
+ * for (size_t i = 0; i < 4; i++) {
142
+ * Process(inlined_array->byte_array[i]);
143
+ * }
144
+ * \endcode
145
+ */
146
+ struct AdditionalBytes {
147
+ constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
148
+ const size_t value;
149
+ };
150
+
115
151
  /**
116
152
  * Default trait class that specifies how to construct an object of type T.
117
153
  * Advanced users may override how an object is constructed using the utilities
118
154
  * that are provided through MakeGarbageCollectedTraitBase.
119
155
  *
120
156
  * Any trait overriding construction must
121
- * - allocate through MakeGarbageCollectedTraitBase<T>::Allocate;
157
+ * - allocate through `MakeGarbageCollectedTraitBase<T>::Allocate`;
122
158
  * - mark the object as fully constructed using
123
- * MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed;
159
+ * `MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed`;
124
160
  */
125
161
  template <typename T>
126
162
  class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
127
163
  public:
128
164
  template <typename... Args>
129
165
  static T* Call(AllocationHandle& handle, Args&&... args) {
130
- static_assert(internal::IsGarbageCollectedType<T>::value,
131
- "T needs to be a garbage collected object");
132
- static_assert(
133
- !internal::IsGarbageCollectedMixinType<T>::value ||
134
- sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold,
135
- "GarbageCollectedMixin may not be a large object");
136
166
  void* memory =
137
167
  MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
138
168
  T* object = ::new (memory) T(std::forward<Args>(args)...);
139
169
  MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
140
170
  return object;
141
171
  }
172
+
173
+ template <typename... Args>
174
+ static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
175
+ Args&&... args) {
176
+ void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(
177
+ handle, sizeof(T) + additional_bytes.value);
178
+ T* object = ::new (memory) T(std::forward<Args>(args)...);
179
+ MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
180
+ return object;
181
+ }
142
182
  };
143
183
 
144
184
  /**
@@ -168,6 +208,25 @@ T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
168
208
  return object;
169
209
  }
170
210
 
211
+ /**
212
+ * Constructs a managed object of type T where T transitively inherits from
213
+ * GarbageCollected. Created objects will have additional bytes appended to
214
+ * it. Allocated memory would suffice for `sizeof(T) + additional_bytes`.
215
+ *
216
+ * \param additional_bytes Denotes how many bytes to append to T.
217
+ * \param args List of arguments with which an instance of T will be
218
+ * constructed.
219
+ * \returns an instance of type T.
220
+ */
221
+ template <typename T, typename... Args>
222
+ T* MakeGarbageCollected(AllocationHandle& handle,
223
+ AdditionalBytes additional_bytes, Args&&... args) {
224
+ T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
225
+ std::forward<Args>(args)...);
226
+ PostConstructionCallbackTrait<T>::Call(object);
227
+ return object;
228
+ }
229
+
171
230
  } // namespace cppgc
172
231
 
173
232
  #endif // INCLUDE_CPPGC_ALLOCATION_H_
@@ -10,15 +10,18 @@
10
10
 
11
11
  namespace cppgc {
12
12
 
13
- // Indicator for the stack state of the embedder.
13
+ /**
14
+ * Indicator for the stack state of the embedder.
15
+ */
14
16
  enum class EmbedderStackState {
17
+ /**
18
+ * Stack may contain interesting heap pointers.
19
+ */
15
20
  kMayContainHeapPointers,
21
+ /**
22
+ * Stack does not contain any interesting heap pointers.
23
+ */
16
24
  kNoHeapPointers,
17
- kUnknown V8_ENUM_DEPRECATE_SOON("Use kMayContainHeapPointers") =
18
- kMayContainHeapPointers,
19
- kNonEmpty V8_ENUM_DEPRECATE_SOON("Use kMayContainHeapPointers") =
20
- kMayContainHeapPointers,
21
- kEmpty V8_ENUM_DEPRECATE_SOON("Use kNoHeapPointers") = kNoHeapPointers,
22
25
  };
23
26
 
24
27
  } // namespace cppgc
@@ -0,0 +1,384 @@
1
+ // Copyright 2020 the V8 project authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ #ifndef INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
6
+ #define INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_
7
+
8
+ #include <atomic>
9
+
10
+ #include "cppgc/internal/persistent-node.h"
11
+ #include "cppgc/internal/pointer-policies.h"
12
+ #include "cppgc/persistent.h"
13
+ #include "cppgc/visitor.h"
14
+
15
+ namespace cppgc {
16
+
17
+ namespace internal {
18
+
19
+ template <typename T, typename WeaknessPolicy, typename LocationPolicy,
20
+ typename CheckingPolicy>
21
+ class BasicCrossThreadPersistent final : public PersistentBase,
22
+ public LocationPolicy,
23
+ private WeaknessPolicy,
24
+ private CheckingPolicy {
25
+ public:
26
+ using typename WeaknessPolicy::IsStrongPersistent;
27
+ using PointeeType = T;
28
+
29
+ ~BasicCrossThreadPersistent() { Clear(); }
30
+
31
+ BasicCrossThreadPersistent(
32
+ const SourceLocation& loc = SourceLocation::Current())
33
+ : LocationPolicy(loc) {}
34
+
35
+ BasicCrossThreadPersistent(
36
+ std::nullptr_t, const SourceLocation& loc = SourceLocation::Current())
37
+ : LocationPolicy(loc) {}
38
+
39
+ BasicCrossThreadPersistent(
40
+ SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
41
+ : PersistentBase(s), LocationPolicy(loc) {}
42
+
43
+ BasicCrossThreadPersistent(
44
+ T* raw, const SourceLocation& loc = SourceLocation::Current())
45
+ : PersistentBase(raw), LocationPolicy(loc) {
46
+ if (!IsValid(raw)) return;
47
+ PersistentRegionLock guard;
48
+ CrossThreadPersistentRegion& region = this->GetPersistentRegion(raw);
49
+ SetNode(region.AllocateNode(this, &Trace));
50
+ this->CheckPointer(raw);
51
+ }
52
+
53
+ class UnsafeCtorTag {
54
+ private:
55
+ UnsafeCtorTag() = default;
56
+ template <typename U, typename OtherWeaknessPolicy,
57
+ typename OtherLocationPolicy, typename OtherCheckingPolicy>
58
+ friend class BasicCrossThreadPersistent;
59
+ };
60
+
61
+ BasicCrossThreadPersistent(
62
+ UnsafeCtorTag, T* raw,
63
+ const SourceLocation& loc = SourceLocation::Current())
64
+ : PersistentBase(raw), LocationPolicy(loc) {
65
+ if (!IsValid(raw)) return;
66
+ CrossThreadPersistentRegion& region = this->GetPersistentRegion(raw);
67
+ SetNode(region.AllocateNode(this, &Trace));
68
+ this->CheckPointer(raw);
69
+ }
70
+
71
+ BasicCrossThreadPersistent(
72
+ T& raw, const SourceLocation& loc = SourceLocation::Current())
73
+ : BasicCrossThreadPersistent(&raw, loc) {}
74
+
75
+ template <typename U, typename MemberBarrierPolicy,
76
+ typename MemberWeaknessTag, typename MemberCheckingPolicy,
77
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
78
+ BasicCrossThreadPersistent(
79
+ internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
80
+ MemberCheckingPolicy>
81
+ member,
82
+ const SourceLocation& loc = SourceLocation::Current())
83
+ : BasicCrossThreadPersistent(member.Get(), loc) {}
84
+
85
+ BasicCrossThreadPersistent(
86
+ const BasicCrossThreadPersistent& other,
87
+ const SourceLocation& loc = SourceLocation::Current())
88
+ : BasicCrossThreadPersistent(loc) {
89
+ // Invoke operator=.
90
+ *this = other;
91
+ }
92
+
93
+ // Heterogeneous ctor.
94
+ template <typename U, typename OtherWeaknessPolicy,
95
+ typename OtherLocationPolicy, typename OtherCheckingPolicy,
96
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
97
+ BasicCrossThreadPersistent(
98
+ const BasicCrossThreadPersistent<U, OtherWeaknessPolicy,
99
+ OtherLocationPolicy,
100
+ OtherCheckingPolicy>& other,
101
+ const SourceLocation& loc = SourceLocation::Current())
102
+ : BasicCrossThreadPersistent(loc) {
103
+ *this = other;
104
+ }
105
+
106
+ BasicCrossThreadPersistent(
107
+ BasicCrossThreadPersistent&& other,
108
+ const SourceLocation& loc = SourceLocation::Current()) noexcept {
109
+ // Invoke operator=.
110
+ *this = std::move(other);
111
+ }
112
+
113
+ BasicCrossThreadPersistent& operator=(
114
+ const BasicCrossThreadPersistent& other) {
115
+ PersistentRegionLock guard;
116
+ AssignUnsafe(other.Get());
117
+ return *this;
118
+ }
119
+
120
+ template <typename U, typename OtherWeaknessPolicy,
121
+ typename OtherLocationPolicy, typename OtherCheckingPolicy,
122
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
123
+ BasicCrossThreadPersistent& operator=(
124
+ const BasicCrossThreadPersistent<U, OtherWeaknessPolicy,
125
+ OtherLocationPolicy,
126
+ OtherCheckingPolicy>& other) {
127
+ PersistentRegionLock guard;
128
+ AssignUnsafe(other.Get());
129
+ return *this;
130
+ }
131
+
132
+ BasicCrossThreadPersistent& operator=(BasicCrossThreadPersistent&& other) {
133
+ if (this == &other) return *this;
134
+ Clear();
135
+ PersistentRegionLock guard;
136
+ PersistentBase::operator=(std::move(other));
137
+ LocationPolicy::operator=(std::move(other));
138
+ if (!IsValid(GetValue())) return *this;
139
+ GetNode()->UpdateOwner(this);
140
+ other.SetValue(nullptr);
141
+ other.SetNode(nullptr);
142
+ this->CheckPointer(Get());
143
+ return *this;
144
+ }
145
+
146
+ BasicCrossThreadPersistent& operator=(T* other) {
147
+ Assign(other);
148
+ return *this;
149
+ }
150
+
151
+ // Assignment from member.
152
+ template <typename U, typename MemberBarrierPolicy,
153
+ typename MemberWeaknessTag, typename MemberCheckingPolicy,
154
+ typename = std::enable_if_t<std::is_base_of<T, U>::value>>
155
+ BasicCrossThreadPersistent& operator=(
156
+ internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
157
+ MemberCheckingPolicy>
158
+ member) {
159
+ return operator=(member.Get());
160
+ }
161
+
162
+ BasicCrossThreadPersistent& operator=(std::nullptr_t) {
163
+ Clear();
164
+ return *this;
165
+ }
166
+
167
+ BasicCrossThreadPersistent& operator=(SentinelPointer s) {
168
+ Assign(s);
169
+ return *this;
170
+ }
171
+
172
+ /**
173
+ * Returns a pointer to the stored object.
174
+ *
175
+ * Note: **Not thread-safe.**
176
+ *
177
+ * \returns a pointer to the stored object.
178
+ */
179
+ // CFI cast exemption to allow passing SentinelPointer through T* and support
180
+ // heterogeneous assignments between different Member and Persistent handles
181
+ // based on their actual types.
182
+ V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
183
+ return static_cast<T*>(const_cast<void*>(GetValue()));
184
+ }
185
+
186
+ /**
187
+ * Clears the stored object.
188
+ */
189
+ void Clear() {
190
+ // Simplified version of `Assign()` to allow calling without a complete type
191
+ // `T`.
192
+ const void* old_value = GetValue();
193
+ if (IsValid(old_value)) {
194
+ PersistentRegionLock guard;
195
+ old_value = GetValue();
196
+ // The fast path check (IsValid()) does not acquire the lock. Reload
197
+ // the value to ensure the reference has not been cleared.
198
+ if (IsValid(old_value)) {
199
+ CrossThreadPersistentRegion& region =
200
+ this->GetPersistentRegion(old_value);
201
+ region.FreeNode(GetNode());
202
+ SetNode(nullptr);
203
+ } else {
204
+ CPPGC_DCHECK(!GetNode());
205
+ }
206
+ }
207
+ SetValue(nullptr);
208
+ }
209
+
210
+ /**
211
+ * Returns a pointer to the stored object and releases it.
212
+ *
213
+ * Note: **Not thread-safe.**
214
+ *
215
+ * \returns a pointer to the stored object.
216
+ */
217
+ T* Release() {
218
+ T* result = Get();
219
+ Clear();
220
+ return result;
221
+ }
222
+
223
+ /**
224
+ * Conversio to boolean.
225
+ *
226
+ * Note: **Not thread-safe.**
227
+ *
228
+ * \returns true if an actual object has been stored and false otherwise.
229
+ */
230
+ explicit operator bool() const { return Get(); }
231
+
232
+ /**
233
+ * Conversion to object of type T.
234
+ *
235
+ * Note: **Not thread-safe.**
236
+ *
237
+ * \returns the object.
238
+ */
239
+ operator T*() const { return Get(); }
240
+
241
+ /**
242
+ * Dereferences the stored object.
243
+ *
244
+ * Note: **Not thread-safe.**
245
+ */
246
+ T* operator->() const { return Get(); }
247
+ T& operator*() const { return *Get(); }
248
+
249
+ template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
250
+ typename OtherLocationPolicy = LocationPolicy,
251
+ typename OtherCheckingPolicy = CheckingPolicy>
252
+ BasicCrossThreadPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
253
+ OtherCheckingPolicy>
254
+ To() const {
255
+ using OtherBasicCrossThreadPersistent =
256
+ BasicCrossThreadPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
257
+ OtherCheckingPolicy>;
258
+ PersistentRegionLock guard;
259
+ return OtherBasicCrossThreadPersistent(
260
+ typename OtherBasicCrossThreadPersistent::UnsafeCtorTag(),
261
+ static_cast<U*>(Get()));
262
+ }
263
+
264
+ template <typename U = T,
265
+ typename = typename std::enable_if<!BasicCrossThreadPersistent<
266
+ U, WeaknessPolicy>::IsStrongPersistent::value>::type>
267
+ BasicCrossThreadPersistent<U, internal::StrongCrossThreadPersistentPolicy>
268
+ Lock() const {
269
+ return BasicCrossThreadPersistent<
270
+ U, internal::StrongCrossThreadPersistentPolicy>(*this);
271
+ }
272
+
273
+ private:
274
+ static bool IsValid(const void* ptr) {
275
+ return ptr && ptr != kSentinelPointer;
276
+ }
277
+
278
+ static void Trace(Visitor* v, const void* ptr) {
279
+ const auto* handle = static_cast<const BasicCrossThreadPersistent*>(ptr);
280
+ v->TraceRoot(*handle, handle->Location());
281
+ }
282
+
283
+ void Assign(T* ptr) {
284
+ const void* old_value = GetValue();
285
+ if (IsValid(old_value)) {
286
+ PersistentRegionLock guard;
287
+ old_value = GetValue();
288
+ // The fast path check (IsValid()) does not acquire the lock. Reload
289
+ // the value to ensure the reference has not been cleared.
290
+ if (IsValid(old_value)) {
291
+ CrossThreadPersistentRegion& region =
292
+ this->GetPersistentRegion(old_value);
293
+ if (IsValid(ptr) && (&region == &this->GetPersistentRegion(ptr))) {
294
+ SetValue(ptr);
295
+ this->CheckPointer(ptr);
296
+ return;
297
+ }
298
+ region.FreeNode(GetNode());
299
+ SetNode(nullptr);
300
+ } else {
301
+ CPPGC_DCHECK(!GetNode());
302
+ }
303
+ }
304
+ SetValue(ptr);
305
+ if (!IsValid(ptr)) return;
306
+ PersistentRegionLock guard;
307
+ SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
308
+ this->CheckPointer(ptr);
309
+ }
310
+
311
+ void AssignUnsafe(T* ptr) {
312
+ PersistentRegionLock::AssertLocked();
313
+ const void* old_value = GetValue();
314
+ if (IsValid(old_value)) {
315
+ CrossThreadPersistentRegion& region =
316
+ this->GetPersistentRegion(old_value);
317
+ if (IsValid(ptr) && (&region == &this->GetPersistentRegion(ptr))) {
318
+ SetValue(ptr);
319
+ this->CheckPointer(ptr);
320
+ return;
321
+ }
322
+ region.FreeNode(GetNode());
323
+ SetNode(nullptr);
324
+ }
325
+ SetValue(ptr);
326
+ if (!IsValid(ptr)) return;
327
+ SetNode(this->GetPersistentRegion(ptr).AllocateNode(this, &Trace));
328
+ this->CheckPointer(ptr);
329
+ }
330
+
331
+ void ClearFromGC() const {
332
+ if (IsValid(GetValue())) {
333
+ WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
334
+ PersistentBase::ClearFromGC();
335
+ }
336
+ }
337
+
338
+ friend class cppgc::Visitor;
339
+ };
340
+
341
+ template <typename T, typename LocationPolicy, typename CheckingPolicy>
342
+ struct IsWeak<
343
+ BasicCrossThreadPersistent<T, internal::WeakCrossThreadPersistentPolicy,
344
+ LocationPolicy, CheckingPolicy>>
345
+ : std::true_type {};
346
+
347
+ } // namespace internal
348
+
349
+ namespace subtle {
350
+
351
+ /**
352
+ * **DO NOT USE: Has known caveats, see below.**
353
+ *
354
+ * CrossThreadPersistent allows retaining objects from threads other than the
355
+ * thread the owning heap is operating on.
356
+ *
357
+ * Known caveats:
358
+ * - Does not protect the heap owning an object from terminating.
359
+ * - Reaching transitively through the graph is unsupported as objects may be
360
+ * moved concurrently on the thread owning the object.
361
+ */
362
+ template <typename T>
363
+ using CrossThreadPersistent = internal::BasicCrossThreadPersistent<
364
+ T, internal::StrongCrossThreadPersistentPolicy>;
365
+
366
+ /**
367
+ * **DO NOT USE: Has known caveats, see below.**
368
+ *
369
+ * CrossThreadPersistent allows weakly retaining objects from threads other than
370
+ * the thread the owning heap is operating on.
371
+ *
372
+ * Known caveats:
373
+ * - Does not protect the heap owning an object from terminating.
374
+ * - Reaching transitively through the graph is unsupported as objects may be
375
+ * moved concurrently on the thread owning the object.
376
+ */
377
+ template <typename T>
378
+ using WeakCrossThreadPersistent = internal::BasicCrossThreadPersistent<
379
+ T, internal::WeakCrossThreadPersistentPolicy>;
380
+
381
+ } // namespace subtle
382
+ } // namespace cppgc
383
+
384
+ #endif // INCLUDE_CPPGC_CROSS_THREAD_PERSISTENT_H_