v8 12.4.254 (node 22.4.1)
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>>
95 // NOLINTNEXTLINE
97 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
98 OtherCheckingPolicy>& other,
100 : BasicPersistent(other.Get(), loc) {}
101
102 // Move ctor. The heterogeneous move ctor is not supported since e.g.
103 // persistent can't reuse persistent node from weak persistent.
105 BasicPersistent&& other,
106 const SourceLocation& loc = SourceLocation::Current()) noexcept
107 : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
108 if (!IsValid()) return;
109 GetNode()->UpdateOwner(this);
110 other.SetValue(nullptr);
111 other.SetNode(nullptr);
112 this->CheckPointer(Get());
113 }
114
115 // Constructor from member.
116 template <typename U, typename MemberBarrierPolicy,
117 typename MemberWeaknessTag, typename MemberCheckingPolicy,
118 typename MemberStorageType,
119 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
120 // NOLINTNEXTLINE
122 U, MemberBarrierPolicy, MemberWeaknessTag,
123 MemberCheckingPolicy, MemberStorageType>& member,
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 MemberStorageType,
161 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
163 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
164 MemberCheckingPolicy, MemberStorageType>&
165 member) {
166 return operator=(member.Get());
167 }
168
170 Assign(other);
171 return *this;
172 }
173
174 BasicPersistent& operator=(std::nullptr_t) {
175 Clear();
176 return *this;
177 }
178
180 Assign(s);
181 return *this;
182 }
183
184 explicit operator bool() const { return Get(); }
185 // Historically we allow implicit conversions to T*.
186 // NOLINTNEXTLINE
187 operator T*() const { return Get(); }
188 T* operator->() const { return Get(); }
189 T& operator*() const { return *Get(); }
190
191 // CFI cast exemption to allow passing SentinelPointer through T* and support
192 // heterogeneous assignments between different Member and Persistent handles
193 // based on their actual types.
194 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
195 // The const_cast below removes the constness from PersistentBase storage.
196 // The following static_cast re-adds any constness if specified through the
197 // user-visible template parameter T.
198 return static_cast<T*>(const_cast<void*>(GetValue()));
199 }
200
201 void Clear() {
202 // Simplified version of `Assign()` to allow calling without a complete type
203 // `T`.
204 if (IsValid()) {
205 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
206 SetNode(nullptr);
207 }
208 SetValue(nullptr);
209 }
210
211 T* Release() {
212 T* result = Get();
213 Clear();
214 return result;
215 }
216
217 template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
218 typename OtherLocationPolicy = LocationPolicy,
219 typename OtherCheckingPolicy = CheckingPolicy>
220 BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
221 OtherCheckingPolicy>
222 To() const {
223 return BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
224 OtherCheckingPolicy>(static_cast<U*>(Get()));
225 }
226
227 private:
228 static void TraceAsRoot(RootVisitor& root_visitor, const void* ptr) {
229 root_visitor.Trace(*static_cast<const BasicPersistent*>(ptr));
230 }
231
232 bool IsValid() const {
233 // Ideally, handling kSentinelPointer would be done by the embedder. On the
234 // other hand, having Persistent aware of it is beneficial since no node
235 // gets wasted.
236 return GetValue() != nullptr && GetValue() != kSentinelPointer;
237 }
238
239 void Assign(T* ptr) {
240 if (IsValid()) {
241 if (ptr && ptr != kSentinelPointer) {
242 // Simply assign the pointer reusing the existing node.
243 SetValue(ptr);
244 this->CheckPointer(ptr);
245 return;
246 }
247 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
248 SetNode(nullptr);
249 }
250 SetValue(ptr);
251 if (!IsValid()) return;
252 SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
253 .AllocateNode(this, &TraceAsRoot));
254 this->CheckPointer(Get());
255 }
256
257 void ClearFromGC() const {
258 if (IsValid()) {
259 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
261 }
262 }
263
264 // Set Get() for details.
265 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast")
266 T* GetFromGC() const {
267 return static_cast<T*>(const_cast<void*>(GetValue()));
268 }
269
271};
272
273template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
274 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
275 typename LocationPolicy2, typename CheckingPolicy2>
276bool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
277 CheckingPolicy1>& p1,
278 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
279 CheckingPolicy2>& p2) {
280 return p1.Get() == p2.Get();
281}
282
283template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
284 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
285 typename LocationPolicy2, typename CheckingPolicy2>
286bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
287 CheckingPolicy1>& p1,
288 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
289 CheckingPolicy2>& p2) {
290 return !(p1 == p2);
291}
292
293template <typename T1, typename PersistentWeaknessPolicy,
294 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
295 typename T2, typename MemberWriteBarrierPolicy,
296 typename MemberWeaknessTag, typename MemberCheckingPolicy,
297 typename MemberStorageType>
299 const BasicPersistent<T1, PersistentWeaknessPolicy,
300 PersistentLocationPolicy, PersistentCheckingPolicy>&
301 p,
302 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
303 MemberCheckingPolicy, MemberStorageType>& m) {
304 return p.Get() == m.Get();
305}
306
307template <typename T1, typename PersistentWeaknessPolicy,
308 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
309 typename T2, typename MemberWriteBarrierPolicy,
310 typename MemberWeaknessTag, typename MemberCheckingPolicy,
311 typename MemberStorageType>
313 const BasicPersistent<T1, PersistentWeaknessPolicy,
314 PersistentLocationPolicy, PersistentCheckingPolicy>&
315 p,
316 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
317 MemberCheckingPolicy, MemberStorageType>& m) {
318 return !(p == m);
319}
320
321template <typename T1, typename MemberWriteBarrierPolicy,
322 typename MemberWeaknessTag, typename MemberCheckingPolicy,
323 typename MemberStorageType, typename T2,
324 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
325 typename PersistentCheckingPolicy>
327 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
328 MemberCheckingPolicy, MemberStorageType>& m,
329 const BasicPersistent<T1, PersistentWeaknessPolicy,
330 PersistentLocationPolicy, PersistentCheckingPolicy>&
331 p) {
332 return m.Get() == p.Get();
333}
334
335template <typename T1, typename MemberWriteBarrierPolicy,
336 typename MemberWeaknessTag, typename MemberCheckingPolicy,
337 typename MemberStorageType, typename T2,
338 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
339 typename PersistentCheckingPolicy>
341 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
342 MemberCheckingPolicy, MemberStorageType>& m,
343 const BasicPersistent<T1, PersistentWeaknessPolicy,
344 PersistentLocationPolicy, PersistentCheckingPolicy>&
345 p) {
346 return !(m == p);
347}
348
349template <typename T, typename LocationPolicy, typename CheckingPolicy>
350struct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy,
351 CheckingPolicy>> : std::true_type {};
352} // namespace internal
353
361template <typename T>
364
371template <typename T>
374
375} // namespace cppgc
376
377#endif // INCLUDE_CPPGC_PERSISTENT_H_
BasicPersistent & operator=(BasicPersistent &&other) noexcept
Definition persistent.h:144
BasicPersistent(BasicPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
Definition persistent.h:104
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:169
V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T *Get() const
Definition persistent.h:194
BasicPersistent & operator=(std::nullptr_t)
Definition persistent.h:174
BasicPersistent & operator=(SentinelPointer s)
Definition persistent.h:179
BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > To() const
Definition persistent.h:222
BasicPersistent(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:96
BasicPersistent & operator=(const BasicPersistent &other)
Definition persistent.h:130
BasicPersistent & operator=(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
Definition persistent.h:137
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:162
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:121
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:450
static constexpr SourceLocation Current()
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:714