v8  9.0.257(node16.0.0)
V8 is Google's open source JavaScript engine
persistent.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_PERSISTENT_H_
6 #define INCLUDE_CPPGC_PERSISTENT_H_
7 
8 #include <type_traits>
9 
10 #include "cppgc/internal/persistent-node.h"
11 #include "cppgc/internal/pointer-policies.h"
12 #include "cppgc/sentinel-pointer.h"
13 #include "cppgc/source-location.h"
14 #include "cppgc/type-traits.h"
15 #include "cppgc/visitor.h"
16 #include "v8config.h" // NOLINT(build/include_directory)
17 
18 namespace cppgc {
19 
20 class Visitor;
21 
22 namespace internal {
23 
24 // PersistentBase always refers to the object as const object and defers to
25 // BasicPersistent on casting to the right type as needed.
27  protected:
28  PersistentBase() = default;
29  explicit PersistentBase(const void* raw) : raw_(raw) {}
30 
31  const void* GetValue() const { return raw_; }
32  void SetValue(const void* value) { raw_ = value; }
33 
34  PersistentNode* GetNode() const { return node_; }
35  void SetNode(PersistentNode* node) { node_ = node; }
36 
37  // Performs a shallow clear which assumes that internal persistent nodes are
38  // destroyed elsewhere.
39  void ClearFromGC() const {
40  raw_ = nullptr;
41  node_ = nullptr;
42  }
43 
44  private:
45  mutable const void* raw_ = nullptr;
46  mutable PersistentNode* node_ = nullptr;
47 
48  friend class PersistentRegion;
49 };
50 
51 // The basic class from which all Persistent classes are generated.
52 template <typename T, typename WeaknessPolicy, typename LocationPolicy,
53  typename CheckingPolicy>
54 class BasicPersistent final : public PersistentBase,
55  public LocationPolicy,
56  private WeaknessPolicy,
57  private CheckingPolicy {
58  public:
59  using typename WeaknessPolicy::IsStrongPersistent;
60  using PointeeType = T;
61 
62  // Null-state/sentinel constructors.
63  BasicPersistent( // NOLINT
64  const SourceLocation& loc = SourceLocation::Current())
65  : LocationPolicy(loc) {}
66 
67  BasicPersistent(std::nullptr_t, // NOLINT
68  const SourceLocation& loc = SourceLocation::Current())
69  : LocationPolicy(loc) {}
70 
71  BasicPersistent( // NOLINT
72  SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
73  : PersistentBase(s), LocationPolicy(loc) {}
74 
75  // Raw value constructors.
76  BasicPersistent(T* raw, // NOLINT
77  const SourceLocation& loc = SourceLocation::Current())
78  : PersistentBase(raw), LocationPolicy(loc) {
79  if (!IsValid()) return;
80  SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
81  .AllocateNode(this, &BasicPersistent::Trace));
82  this->CheckPointer(Get());
83  }
84 
85  BasicPersistent(T& raw, // NOLINT
86  const SourceLocation& loc = SourceLocation::Current())
87  : BasicPersistent(&raw, loc) {}
88 
89  // Copy ctor.
91  const SourceLocation& loc = SourceLocation::Current())
92  : BasicPersistent(other.Get(), loc) {}
93 
94  // Heterogeneous ctor.
95  template <typename U, typename OtherWeaknessPolicy,
96  typename OtherLocationPolicy, typename OtherCheckingPolicy,
97  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
98  BasicPersistent( // NOLINT
99  const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
100  OtherCheckingPolicy>& other,
101  const SourceLocation& loc = SourceLocation::Current())
102  : BasicPersistent(other.Get(), loc) {}
103 
104  // Move ctor. The heterogeneous move ctor is not supported since e.g.
105  // persistent can't reuse persistent node from weak persistent.
107  BasicPersistent&& other,
108  const SourceLocation& loc = SourceLocation::Current()) noexcept
109  : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
110  if (!IsValid()) return;
111  GetNode()->UpdateOwner(this);
112  other.SetValue(nullptr);
113  other.SetNode(nullptr);
114  this->CheckPointer(Get());
115  }
116 
117  // Constructor from member.
118  template <typename U, typename MemberBarrierPolicy,
119  typename MemberWeaknessTag, typename MemberCheckingPolicy,
120  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
121  BasicPersistent(internal::BasicMember<U, MemberBarrierPolicy, // NOLINT
122  MemberWeaknessTag, MemberCheckingPolicy>
123  member,
124  const SourceLocation& loc = SourceLocation::Current())
125  : BasicPersistent(member.Get(), loc) {}
126 
128 
129  // Copy assignment.
131  return operator=(other.Get());
132  }
133 
134  template <typename U, typename OtherWeaknessPolicy,
135  typename OtherLocationPolicy, typename OtherCheckingPolicy,
136  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
138  const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
139  OtherCheckingPolicy>& other) {
140  return operator=(other.Get());
141  }
142 
143  // Move assignment.
145  if (this == &other) return *this;
146  Clear();
147  PersistentBase::operator=(std::move(other));
148  LocationPolicy::operator=(std::move(other));
149  if (!IsValid()) return *this;
150  GetNode()->UpdateOwner(this);
151  other.SetValue(nullptr);
152  other.SetNode(nullptr);
153  this->CheckPointer(Get());
154  return *this;
155  }
156 
157  // Assignment from member.
158  template <typename U, typename MemberBarrierPolicy,
159  typename MemberWeaknessTag, typename MemberCheckingPolicy,
160  typename = std::enable_if_t<std::is_base_of<T, U>::value>>
162  internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
163  MemberCheckingPolicy>
164  member) {
165  return operator=(member.Get());
166  }
167 
168  BasicPersistent& operator=(T* other) {
169  Assign(other);
170  return *this;
171  }
172 
173  BasicPersistent& operator=(std::nullptr_t) {
174  Clear();
175  return *this;
176  }
177 
179  Assign(s);
180  return *this;
181  }
182 
183  explicit operator bool() const { return Get(); }
184  operator T*() const { return Get(); } // NOLINT
185  T* operator->() const { return Get(); }
186  T& operator*() const { return *Get(); }
187 
188  // CFI cast exemption to allow passing SentinelPointer through T* and support
189  // heterogeneous assignments between different Member and Persistent handles
190  // based on their actual types.
191  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
192  // The const_cast below removes the constness from PersistentBase storage.
193  // The following static_cast re-adds any constness if specified through the
194  // user-visible template parameter T.
195  return static_cast<T*>(const_cast<void*>(GetValue()));
196  }
197 
198  void Clear() {
199  // Simplified version of `Assign()` to allow calling without a complete type
200  // `T`.
201  if (IsValid()) {
202  WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
203  SetNode(nullptr);
204  }
205  SetValue(nullptr);
206  }
207 
208  T* Release() {
209  T* result = Get();
210  Clear();
211  return result;
212  }
213 
214  template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
215  typename OtherLocationPolicy = LocationPolicy,
216  typename OtherCheckingPolicy = CheckingPolicy>
217  BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
218  OtherCheckingPolicy>
219  To() const {
220  return BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
221  OtherCheckingPolicy>(static_cast<U*>(Get()));
222  }
223 
224  private:
225  static void Trace(Visitor* v, const void* ptr) {
226  const auto* persistent = static_cast<const BasicPersistent*>(ptr);
227  v->TraceRoot(*persistent, persistent->Location());
228  }
229 
230  bool IsValid() const {
231  // Ideally, handling kSentinelPointer would be done by the embedder. On the
232  // other hand, having Persistent aware of it is beneficial since no node
233  // gets wasted.
234  return GetValue() != nullptr && GetValue() != kSentinelPointer;
235  }
236 
237  void Assign(T* ptr) {
238  if (IsValid()) {
239  if (ptr && ptr != kSentinelPointer) {
240  // Simply assign the pointer reusing the existing node.
241  SetValue(ptr);
242  this->CheckPointer(ptr);
243  return;
244  }
245  WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
246  SetNode(nullptr);
247  }
248  SetValue(ptr);
249  if (!IsValid()) return;
250  SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
251  .AllocateNode(this, &BasicPersistent::Trace));
252  this->CheckPointer(Get());
253  }
254 
255  void ClearFromGC() const {
256  if (IsValid()) {
257  WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
259  }
260  }
261 
262  friend class cppgc::Visitor;
263 };
264 
265 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
266  typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
267  typename LocationPolicy2, typename CheckingPolicy2>
268 bool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
269  CheckingPolicy1>& p1,
270  const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
271  CheckingPolicy2>& p2) {
272  return p1.Get() == p2.Get();
273 }
274 
275 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
276  typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
277  typename LocationPolicy2, typename CheckingPolicy2>
278 bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
279  CheckingPolicy1>& p1,
280  const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
281  CheckingPolicy2>& p2) {
282  return !(p1 == p2);
283 }
284 
285 template <typename T1, typename PersistentWeaknessPolicy,
286  typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
287  typename T2, typename MemberWriteBarrierPolicy,
288  typename MemberWeaknessTag, typename MemberCheckingPolicy>
289 bool operator==(const BasicPersistent<T1, PersistentWeaknessPolicy,
290  PersistentLocationPolicy,
291  PersistentCheckingPolicy>& p,
292  BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
293  MemberCheckingPolicy>
294  m) {
295  return p.Get() == m.Get();
296 }
297 
298 template <typename T1, typename PersistentWeaknessPolicy,
299  typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
300  typename T2, typename MemberWriteBarrierPolicy,
301  typename MemberWeaknessTag, typename MemberCheckingPolicy>
302 bool operator!=(const BasicPersistent<T1, PersistentWeaknessPolicy,
303  PersistentLocationPolicy,
304  PersistentCheckingPolicy>& p,
305  BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
306  MemberCheckingPolicy>
307  m) {
308  return !(p == m);
309 }
310 
311 template <typename T1, typename MemberWriteBarrierPolicy,
312  typename MemberWeaknessTag, typename MemberCheckingPolicy,
313  typename T2, typename PersistentWeaknessPolicy,
314  typename PersistentLocationPolicy, typename PersistentCheckingPolicy>
315 bool operator==(BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
316  MemberCheckingPolicy>
317  m,
318  const BasicPersistent<T1, PersistentWeaknessPolicy,
319  PersistentLocationPolicy,
320  PersistentCheckingPolicy>& p) {
321  return m.Get() == p.Get();
322 }
323 
324 template <typename T1, typename MemberWriteBarrierPolicy,
325  typename MemberWeaknessTag, typename MemberCheckingPolicy,
326  typename T2, typename PersistentWeaknessPolicy,
327  typename PersistentLocationPolicy, typename PersistentCheckingPolicy>
328 bool operator!=(BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
329  MemberCheckingPolicy>
330  m,
331  const BasicPersistent<T1, PersistentWeaknessPolicy,
332  PersistentLocationPolicy,
333  PersistentCheckingPolicy>& p) {
334  return !(m == p);
335 }
336 
337 template <typename T, typename LocationPolicy, typename CheckingPolicy>
339  CheckingPolicy>> : std::true_type {};
340 } // namespace internal
341 
342 /**
343  * Persistent is a way to create a strong pointer from an off-heap object to
344  * another on-heap object. As long as the Persistent handle is alive the GC will
345  * keep the object pointed to alive. The Persistent handle is always a GC root
346  * from the point of view of the GC. Persistent must be constructed and
347  * destructed in the same thread.
348  */
349 template <typename T>
350 using Persistent =
352 
353 /**
354  * WeakPersistent is a way to create a weak pointer from an off-heap object to
355  * an on-heap object. The pointer is automatically cleared when the pointee gets
356  * collected. WeakPersistent must be constructed and destructed in the same
357  * thread.
358  */
359 template <typename T>
360 using WeakPersistent =
362 
363 } // namespace cppgc
364 
365 #endif // INCLUDE_CPPGC_PERSISTENT_H_
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(SentinelPointer s, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:71
cppgc::internal::PersistentBase::PersistentBase
PersistentBase()=default
cppgc::Visitor::BasicPersistent
friend class internal::BasicPersistent
Definition: visitor.h:325
cppgc::internal::IsWeak
Definition: type-traits.h:36
cppgc::internal::operator==
bool operator==(BasicMember< T2, MemberWeaknessTag, MemberWriteBarrierPolicy, MemberCheckingPolicy > m, const BasicPersistent< T1, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &p)
Definition: persistent.h:315
cppgc::internal::operator!=
bool operator!=(BasicMember< T2, MemberWeaknessTag, MemberWriteBarrierPolicy, MemberCheckingPolicy > m, const BasicPersistent< T1, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &p)
Definition: persistent.h:328
cppgc::internal::BasicPersistent::operator*
T & operator*() const
Definition: persistent.h:186
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member)
Definition: persistent.h:161
cppgc::internal::operator==
bool operator==(const BasicPersistent< T1, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &p, BasicMember< T2, MemberWeaknessTag, MemberWriteBarrierPolicy, MemberCheckingPolicy > m)
Definition: persistent.h:289
cppgc::internal::BasicPersistent::Release
T * Release()
Definition: persistent.h:208
cppgc::internal::WeakPersistentPolicy
Definition: pointer-policies.h:111
cppgc::internal::SentinelPointer
Definition: sentinel-pointer.h:15
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(T *other)
Definition: persistent.h:168
cppgc::internal::PersistentBase::SetValue
void SetValue(const void *value)
Definition: persistent.h:32
cppgc::internal::PersistentBase::ClearFromGC
void ClearFromGC() const
Definition: persistent.h:39
cppgc::internal::BasicPersistent::Clear
void Clear()
Definition: persistent.h:198
cppgc::internal::PersistentBase::GetValue
const void * GetValue() const
Definition: persistent.h:31
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:85
cppgc
Definition: allocation.h:17
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > member, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:121
cppgc::internal::operator==
bool operator==(const BasicPersistent< T1, WeaknessPolicy1, LocationPolicy1, CheckingPolicy1 > &p1, const BasicPersistent< T2, WeaknessPolicy2, LocationPolicy2, CheckingPolicy2 > &p2)
Definition: persistent.h:268
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(SentinelPointer s)
Definition: persistent.h:178
cppgc::internal::PersistentBase
Definition: persistent.h:26
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:63
cppgc::internal::PersistentBase::GetNode
PersistentNode * GetNode() const
Definition: persistent.h:34
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(T *raw, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:76
cppgc::internal::operator!=
bool operator!=(const BasicPersistent< T1, PersistentWeaknessPolicy, PersistentLocationPolicy, PersistentCheckingPolicy > &p, BasicMember< T2, MemberWeaknessTag, MemberWriteBarrierPolicy, MemberCheckingPolicy > m)
Definition: persistent.h:302
cppgc::SourceLocation::Current
static constexpr SourceLocation Current()
Definition: source-location.h:43
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(std::nullptr_t, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:67
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(std::nullptr_t)
Definition: persistent.h:173
cppgc::internal::BasicPersistent::To
BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > To() const
Definition: persistent.h:219
cppgc::internal::operator!=
bool operator!=(const BasicPersistent< T1, WeaknessPolicy1, LocationPolicy1, CheckingPolicy1 > &p1, const BasicPersistent< T2, WeaknessPolicy2, LocationPolicy2, CheckingPolicy2 > &p2)
Definition: persistent.h:278
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:98
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(BasicPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
Definition: persistent.h:106
cppgc::Visitor
Definition: visitor.h:52
cppgc::internal::BasicPersistent::operator bool
operator bool() const
Definition: persistent.h:183
cppgc::internal::PersistentBase::SetNode
void SetNode(PersistentNode *node)
Definition: persistent.h:35
cppgc::internal::PersistentBase::PersistentBase
PersistentBase(const void *raw)
Definition: persistent.h:29
cppgc::internal::BasicPersistent::operator->
T * operator->() const
Definition: persistent.h:185
cppgc::kSentinelPointer
constexpr internal::SentinelPointer kSentinelPointer
Definition: sentinel-pointer.h:28
cppgc::internal::BasicPersistent::BasicPersistent
BasicPersistent(const BasicPersistent &other, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:90
cppgc::internal::BasicPersistent::~BasicPersistent
~BasicPersistent()
Definition: persistent.h:127
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
Definition: persistent.h:137
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(BasicPersistent &&other)
Definition: persistent.h:144
cppgc::internal
Definition: allocation.h:22
cppgc::internal::BasicPersistent::operator T*
operator T*() const
Definition: persistent.h:184
cppgc::internal::StrongPersistentPolicy
Definition: pointer-policies.h:106
cppgc::internal::BasicPersistent::operator=
BasicPersistent & operator=(const BasicPersistent &other)
Definition: persistent.h:130
V8_CLANG_NO_SANITIZE
#define V8_CLANG_NO_SANITIZE(what)
Definition: v8config.h:478