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