v8  8.6.395 (node 15.0.1)
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/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_