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