v8 11.3.244 (node 20.3.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
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