v8  8.6.395 (node 15.0.1)
V8 is Google's open source JavaScript engine
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/type-traits.h"
14 #include "v8config.h" // NOLINT(build/include_directory)
15 
16 namespace cppgc {
17 
18 class Visitor;
19 
20 namespace internal {
21 
22 class MemberBase {
23  protected:
24  MemberBase() = default;
25  explicit MemberBase(void* value) : raw_(value) {}
26 
27  void* const* GetRawSlot() const { return &raw_; }
28  void* GetRaw() const { return raw_; }
29  void SetRaw(void* value) { raw_ = value; }
30 
31  void* GetRawAtomic() const {
32  return reinterpret_cast<const std::atomic<void*>*>(&raw_)->load(
33  std::memory_order_relaxed);
34  }
35  void SetRawAtomic(void* value) {
36  reinterpret_cast<std::atomic<void*>*>(&raw_)->store(
37  value, std::memory_order_relaxed);
38  }
39 
40  void ClearFromGC() const { raw_ = nullptr; }
41 
42  private:
43  mutable void* raw_ = nullptr;
44 };
45 
46 // The basic class from which all Member classes are 'generated'.
47 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
48  typename CheckingPolicy>
49 class BasicMember final : private MemberBase, private CheckingPolicy {
50  public:
51  using PointeeType = T;
52 
53  constexpr BasicMember() = default;
54  constexpr BasicMember(std::nullptr_t) {} // NOLINT
55  BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT
56  BasicMember(T* raw) : MemberBase(raw) { // NOLINT
57  InitializingWriteBarrier();
58  this->CheckPointer(Get());
59  }
60  BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
61  BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
62  // Allow heterogeneous construction.
63  template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
64  typename OtherCheckingPolicy,
65  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
66  BasicMember( // NOLINT
67  const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
68  OtherCheckingPolicy>& other)
69  : BasicMember(other.Get()) {}
70  // Construction from Persistent.
71  template <typename U, typename PersistentWeaknessPolicy,
72  typename PersistentLocationPolicy,
73  typename PersistentCheckingPolicy,
74  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
75  BasicMember( // NOLINT
76  const BasicPersistent<U, PersistentWeaknessPolicy,
77  PersistentLocationPolicy, PersistentCheckingPolicy>&
78  p)
79  : BasicMember(p.Get()) {}
80 
81  BasicMember& operator=(const BasicMember& other) {
82  return operator=(other.Get());
83  }
84  // Allow heterogeneous assignment.
85  template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
86  typename OtherCheckingPolicy,
87  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
88  BasicMember& operator=(
89  const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
90  OtherCheckingPolicy>& other) {
91  return operator=(other.Get());
92  }
93  // Assignment from Persistent.
94  template <typename U, typename PersistentWeaknessPolicy,
95  typename PersistentLocationPolicy,
96  typename PersistentCheckingPolicy,
97  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
98  BasicMember& operator=(
99  const BasicPersistent<U, PersistentWeaknessPolicy,
100  PersistentLocationPolicy, PersistentCheckingPolicy>&
101  other) {
102  return operator=(other.Get());
103  }
104  BasicMember& operator=(T* other) {
105  SetRawAtomic(other);
106  AssigningWriteBarrier();
107  this->CheckPointer(Get());
108  return *this;
109  }
110  BasicMember& operator=(std::nullptr_t) {
111  Clear();
112  return *this;
113  }
114  BasicMember& operator=(SentinelPointer s) {
116  return *this;
117  }
118 
119  template <typename OtherWeaknessTag, typename OtherBarrierPolicy,
120  typename OtherCheckingPolicy>
121  void Swap(BasicMember<T, OtherWeaknessTag, OtherBarrierPolicy,
122  OtherCheckingPolicy>& other) {
123  T* tmp = Get();
124  *this = other;
125  other = tmp;
126  }
127 
128  explicit operator bool() const { return Get(); }
129  operator T*() const { return Get(); } // NOLINT
130  T* operator->() const { return Get(); }
131  T& operator*() const { return *Get(); }
132 
133  // CFI cast exemption to allow passing SentinelPointer through T* and support
134  // heterogeneous assignments between different Member and Persistent handles
135  // based on their actual types.
136  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
137  // Executed by the mutator, hence non atomic load.
138  return static_cast<T*>(MemberBase::GetRaw());
139  }
140 
141  void Clear() { SetRawAtomic(nullptr); }
142 
143  T* Release() {
144  T* result = Get();
145  Clear();
146  return result;
147  }
148 
149  private:
150  T* GetRawAtomic() const {
151  return static_cast<T*>(MemberBase::GetRawAtomic());
152  }
153 
154  void InitializingWriteBarrier() const {
155  WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw());
156  }
157  void AssigningWriteBarrier() const {
158  WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw());
159  }
160 
161  void ClearFromGC() const { MemberBase::ClearFromGC(); }
162 
163  friend class cppgc::Visitor;
164 };
165 
166 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
167  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
168  typename WriteBarrierPolicy2, typename CheckingPolicy2>
169 bool operator==(
170  BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1> member1,
171  BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2>
172  member2) {
173  return member1.Get() == member2.Get();
174 }
175 
176 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
177  typename CheckingPolicy1, typename T2, typename WeaknessTag2,
178  typename WriteBarrierPolicy2, typename CheckingPolicy2>
179 bool operator!=(
180  BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1> member1,
181  BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2>
182  member2) {
183  return !(member1 == member2);
184 }
185 
186 template <typename T, typename WriteBarrierPolicy, typename CheckingPolicy>
187 struct IsWeak<
188  internal::BasicMember<T, WeakMemberTag, WriteBarrierPolicy, CheckingPolicy>>
189  : std::true_type {};
190 
191 } // namespace internal
192 
193 /**
194  * Members are used in classes to contain strong pointers to other garbage
195  * collected objects. All Member fields of a class must be traced in the class'
196  * trace method.
197  */
198 template <typename T>
199 using Member = internal::BasicMember<T, internal::StrongMemberTag,
201 
202 /**
203  * WeakMember is similar to Member in that it is used to point to other garbage
204  * collected objects. However instead of creating a strong pointer to the
205  * object, the WeakMember creates a weak pointer, which does not keep the
206  * pointee alive. Hence if all pointers to to a heap allocated object are weak
207  * the object will be garbage collected. At the time of GC the weak pointers
208  * will automatically be set to null.
209  */
210 template <typename T>
211 using WeakMember = internal::BasicMember<T, internal::WeakMemberTag,
213 
214 /**
215  * UntracedMember is a pointer to an on-heap object that is not traced for some
216  * reason. Do not use this unless you know what you are doing. Keeping raw
217  * pointers to on-heap objects is prohibited unless used from stack. Pointee
218  * must be kept alive through other means.
219  */
220 template <typename T>
221 using UntracedMember = internal::BasicMember<T, internal::UntracedMemberTag,
223 
224 } // namespace cppgc
225 
226 #endif // INCLUDE_CPPGC_MEMBER_H_