v8  9.4.146 (node 16.13.0)
V8 is Google's open source JavaScript engine
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
member.h
Go to the documentation of this file.
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_MEMBER_H_
6 #define INCLUDE_CPPGC_MEMBER_H_
7 
8 #include <atomic>
9 #include <cstddef>
10 #include <type_traits>
11 
12 #include "cppgc/internal/pointer-policies.h"
13 #include "cppgc/sentinel-pointer.h"
14 #include "cppgc/type-traits.h"
15 #include "v8config.h" // NOLINT(build/include_directory)
16 
17 namespace cppgc {
18 
19 class Visitor;
20 
21 namespace internal {
22 
23 // MemberBase always refers to the object as const object and defers to
24 // BasicMember on casting to the right type as needed.
25 class MemberBase {
26  protected:
28 
29  MemberBase() = default;
30  explicit MemberBase(const void* value) : raw_(value) {}
31  MemberBase(const void* value, AtomicInitializerTag) { SetRawAtomic(value); }
32 
33  const void** GetRawSlot() const { return &raw_; }
34  const void* GetRaw() const { return raw_; }
35  void SetRaw(void* value) { raw_ = value; }
36 
37  const void* GetRawAtomic() const {
38  return reinterpret_cast<const std::atomic<const void*>*>(&raw_)->load(
39  std::memory_order_relaxed);
40  }
41  void SetRawAtomic(const void* value) {
42  reinterpret_cast<std::atomic<const void*>*>(&raw_)->store(
43  value, std::memory_order_relaxed);
44  }
45 
46  void ClearFromGC() const { raw_ = nullptr; }
47 
48  private:
49  mutable const void* raw_ = nullptr;
50 };
51 
52 // The basic class from which all Member classes are 'generated'.
53 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
54  typename CheckingPolicy>
55 class BasicMember final : private MemberBase, private CheckingPolicy {
56  public:
57  using PointeeType = T;
58 
59  constexpr BasicMember() = default;
60  constexpr BasicMember(std::nullptr_t) {} // NOLINT
61  BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT
62  BasicMember(T* raw) : MemberBase(raw) { // NOLINT
63  InitializingWriteBarrier();
64  this->CheckPointer(Get());
65  }
66  BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
67  // Atomic ctor. Using the AtomicInitializerTag forces BasicMember to
68  // initialize using atomic assignments. This is required for preventing
69  // data races with concurrent marking.
70  using AtomicInitializerTag = MemberBase::AtomicInitializerTag;
71  BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
72  : MemberBase(nullptr, atomic) {}
73  BasicMember(SentinelPointer s, AtomicInitializerTag atomic)
74  : MemberBase(s, atomic) {}
75  BasicMember(T* raw, AtomicInitializerTag atomic) : MemberBase(raw, atomic) {
76  InitializingWriteBarrier();
77  this->CheckPointer(Get());
78  }
79  BasicMember(T& raw, AtomicInitializerTag atomic)
80  : BasicMember(&raw, atomic) {}
81  // Copy ctor.
82  BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
83  // Allow heterogeneous construction.
84  template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
85  typename OtherCheckingPolicy,
86  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
87  BasicMember( // NOLINT
88  const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
89  OtherCheckingPolicy>& other)
90  : BasicMember(other.Get()) {}
91  // Move ctor.
92  BasicMember(BasicMember&& other) noexcept : BasicMember(other.Get()) {
93  other.Clear();
94  }
95  // Allow heterogeneous move construction.
96  template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
97  typename OtherCheckingPolicy,
98  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
99  BasicMember(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
100  OtherCheckingPolicy>&& other) noexcept
101  : BasicMember(other.Get()) {
102  other.Clear();
103  }
104  // Construction from Persistent.
105  template <typename U, typename PersistentWeaknessPolicy,
106  typename PersistentLocationPolicy,
107  typename PersistentCheckingPolicy,
108  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
109  BasicMember(const BasicPersistent<U, PersistentWeaknessPolicy,
110  PersistentLocationPolicy,
111  PersistentCheckingPolicy>& p)
112  : BasicMember(p.Get()) {}
113 
114  // Copy assignment.
115  BasicMember& operator=(const BasicMember& other) {
116  return operator=(other.Get());
117  }
118  // Allow heterogeneous copy assignment.
119  template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
120  typename OtherCheckingPolicy,
121  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
122  BasicMember& operator=(
123  const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
124  OtherCheckingPolicy>& other) {
125  return operator=(other.Get());
126  }
127  // Move assignment.
128  BasicMember& operator=(BasicMember&& other) noexcept {
129  operator=(other.Get());
130  other.Clear();
131  return *this;
132  }
133  // Heterogeneous move assignment.
134  template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
135  typename OtherCheckingPolicy,
136  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
137  BasicMember& operator=(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
138  OtherCheckingPolicy>&& other) noexcept {
139  operator=(other.Get());
140  other.Clear();
141  return *this;
142  }
143  // Assignment from Persistent.
144  template <typename U, typename PersistentWeaknessPolicy,
145  typename PersistentLocationPolicy,
146  typename PersistentCheckingPolicy,
147  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
148  BasicMember& operator=(
149  const BasicPersistent<U, PersistentWeaknessPolicy,
150  PersistentLocationPolicy, PersistentCheckingPolicy>&
151  other) {
152  return operator=(other.Get());
153  }
154  BasicMember& operator=(T* other) {
155  SetRawAtomic(other);
156  AssigningWriteBarrier();
157  this->CheckPointer(Get());
158  return *this;
159  }
160  BasicMember& operator=(std::nullptr_t) {
161  Clear();
162  return *this;
163  }
164  BasicMember& operator=(SentinelPointer s) {
166  return *this;
167  }
168 
169  template <typename OtherWeaknessTag, typename OtherBarrierPolicy,
170  typename OtherCheckingPolicy>
171  void Swap(BasicMember<T, OtherWeaknessTag, OtherBarrierPolicy,
172  OtherCheckingPolicy>& other) {
173  T* tmp = Get();
174  *this = other;
175  other = tmp;
176  }
177 
178  explicit operator bool() const { return Get(); }
179  operator T*() const { return Get(); }
180  T* operator->() const { return Get(); }
181  T& operator*() const { return *Get(); }
182 
183  // CFI cast exemption to allow passing SentinelPointer through T* and support
184  // heterogeneous assignments between different Member and Persistent handles
185  // based on their actual types.
186  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
187  // Executed by the mutator, hence non atomic load.
188  //
189  // The const_cast below removes the constness from MemberBase storage. The
190  // following static_cast re-adds any constness if specified through the
191  // user-visible template parameter T.
192  return static_cast<T*>(const_cast<void*>(MemberBase::GetRaw()));
193  }
194 
195  void Clear() { SetRawAtomic(nullptr); }
196 
197  T* Release() {
198  T* result = Get();
199  Clear();
200  return result;
201  }
202 
203  const T** GetSlotForTesting() const {
204  return reinterpret_cast<const T**>(GetRawSlot());
205  }
206 
207  private:
208  const T* GetRawAtomic() const {
209  return static_cast<const T*>(MemberBase::GetRawAtomic());
210  }
211 
212  void InitializingWriteBarrier() const {
213  WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw());
214  }
215  void AssigningWriteBarrier() const {
216  WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw());
217  }
218 
219  void ClearFromGC() const { MemberBase::ClearFromGC(); }
220 
221  T* GetFromGC() const { return Get(); }
222 
223  friend class cppgc::Visitor;
224  template <typename U>
225  friend struct cppgc::TraceTrait;
226 };
227 
228 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
229  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
230  typename WriteBarrierPolicy2, typename CheckingPolicy2>
231 bool operator==(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
232  CheckingPolicy1>& member1,
233  const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
234  CheckingPolicy2>& member2) {
235  return member1.Get() == member2.Get();
236 }
237 
238 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
239  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
240  typename WriteBarrierPolicy2, typename CheckingPolicy2>
241 bool operator!=(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
242  CheckingPolicy1>& member1,
243  const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
244  CheckingPolicy2>& member2) {
245  return !(member1 == member2);
246 }
247 
248 template <typename T, typename WriteBarrierPolicy, typename CheckingPolicy>
249 struct IsWeak<
250  internal::BasicMember<T, WeakMemberTag, WriteBarrierPolicy, CheckingPolicy>>
251  : std::true_type {};
252 
253 } // namespace internal
254 
255 /**
256  * Members are used in classes to contain strong pointers to other garbage
257  * collected objects. All Member fields of a class must be traced in the class'
258  * trace method.
259  */
260 template <typename T>
261 using Member = internal::BasicMember<T, internal::StrongMemberTag,
263 
264 /**
265  * WeakMember is similar to Member in that it is used to point to other garbage
266  * collected objects. However instead of creating a strong pointer to the
267  * object, the WeakMember creates a weak pointer, which does not keep the
268  * pointee alive. Hence if all pointers to to a heap allocated object are weak
269  * the object will be garbage collected. At the time of GC the weak pointers
270  * will automatically be set to null.
271  */
272 template <typename T>
273 using WeakMember = internal::BasicMember<T, internal::WeakMemberTag,
275 
276 /**
277  * UntracedMember is a pointer to an on-heap object that is not traced for some
278  * reason. Do not use this unless you know what you are doing. Keeping raw
279  * pointers to on-heap objects is prohibited unless used from stack. Pointee
280  * must be kept alive through other means.
281  */
282 template <typename T>
283 using UntracedMember = internal::BasicMember<T, internal::UntracedMemberTag,
285 
286 } // namespace cppgc
287 
288 #endif // INCLUDE_CPPGC_MEMBER_H_