v8 10.2.154 (node 18.16.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 {
19
20class Visitor;
21
22namespace 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 protected:
45 mutable const void* raw_ = nullptr;
46 mutable PersistentNode* node_ = nullptr;
47
49};
50
51// The basic class from which all Persistent classes are generated.
52template <typename T, typename WeaknessPolicy, typename LocationPolicy,
53 typename CheckingPolicy>
54class 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
65 : LocationPolicy(loc) {}
66
67 BasicPersistent(std::nullptr_t, // NOLINT
69 : LocationPolicy(loc) {}
70
71 BasicPersistent( // NOLINT
73 : PersistentBase(s), LocationPolicy(loc) {}
74
75 // Raw value constructors.
76 BasicPersistent(T* raw, // NOLINT
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
87 : BasicPersistent(&raw, loc) {}
88
89 // Copy ctor.
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>>
99 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
100 OtherCheckingPolicy>& other,
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>>
122 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
123 MemberCheckingPolicy>& 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 = std::enable_if_t<std::is_base_of<T, U>::value>>
162 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
163 MemberCheckingPolicy>& 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 Trace(Visitor* v, const void* ptr) {
225 const auto* persistent = static_cast<const BasicPersistent*>(ptr);
226 v->TraceRoot(*persistent, persistent->Location());
227 }
228
229 bool IsValid() const {
230 // Ideally, handling kSentinelPointer would be done by the embedder. On the
231 // other hand, having Persistent aware of it is beneficial since no node
232 // gets wasted.
233 return GetValue() != nullptr && GetValue() != kSentinelPointer;
234 }
235
236 void Assign(T* ptr) {
237 if (IsValid()) {
238 if (ptr && ptr != kSentinelPointer) {
239 // Simply assign the pointer reusing the existing node.
240 SetValue(ptr);
241 this->CheckPointer(ptr);
242 return;
243 }
244 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
245 SetNode(nullptr);
246 }
247 SetValue(ptr);
248 if (!IsValid()) return;
249 SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
250 .AllocateNode(this, &BasicPersistent::Trace));
251 this->CheckPointer(Get());
252 }
253
254 void ClearFromGC() const {
255 if (IsValid()) {
256 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
258 }
259 }
260
261 // Set Get() for details.
262 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast")
263 T* GetFromGC() const {
264 return static_cast<T*>(const_cast<void*>(GetValue()));
265 }
266
267 friend class cppgc::Visitor;
268};
269
270template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
271 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
272 typename LocationPolicy2, typename CheckingPolicy2>
273bool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
274 CheckingPolicy1>& p1,
275 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
276 CheckingPolicy2>& p2) {
277 return p1.Get() == p2.Get();
278}
279
280template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
281 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
282 typename LocationPolicy2, typename CheckingPolicy2>
283bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
284 CheckingPolicy1>& p1,
285 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
286 CheckingPolicy2>& p2) {
287 return !(p1 == p2);
288}
289
290template <typename T1, typename PersistentWeaknessPolicy,
291 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
292 typename T2, typename MemberWriteBarrierPolicy,
293 typename MemberWeaknessTag, typename MemberCheckingPolicy>
295 const BasicPersistent<T1, PersistentWeaknessPolicy,
296 PersistentLocationPolicy, PersistentCheckingPolicy>&
297 p,
298 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
299 MemberCheckingPolicy>& 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>
308 const BasicPersistent<T1, PersistentWeaknessPolicy,
309 PersistentLocationPolicy, PersistentCheckingPolicy>&
310 p,
311 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
312 MemberCheckingPolicy>& m) {
313 return !(p == m);
314}
315
316template <typename T1, typename MemberWriteBarrierPolicy,
317 typename MemberWeaknessTag, typename MemberCheckingPolicy,
318 typename T2, typename PersistentWeaknessPolicy,
319 typename PersistentLocationPolicy, typename PersistentCheckingPolicy>
321 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
322 MemberCheckingPolicy>& m,
323 const BasicPersistent<T1, PersistentWeaknessPolicy,
324 PersistentLocationPolicy, PersistentCheckingPolicy>&
325 p) {
326 return m.Get() == p.Get();
327}
328
329template <typename T1, typename MemberWriteBarrierPolicy,
330 typename MemberWeaknessTag, typename MemberCheckingPolicy,
331 typename T2, typename PersistentWeaknessPolicy,
332 typename PersistentLocationPolicy, typename PersistentCheckingPolicy>
334 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
335 MemberCheckingPolicy>& m,
336 const BasicPersistent<T1, PersistentWeaknessPolicy,
337 PersistentLocationPolicy, PersistentCheckingPolicy>&
338 p) {
339 return !(m == p);
340}
341
342template <typename T, typename LocationPolicy, typename CheckingPolicy>
343struct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy,
344 CheckingPolicy>> : std::true_type {};
345} // namespace internal
346
354template <typename T>
357
364template <typename T>
367
368} // namespace cppgc
369
370#endif // INCLUDE_CPPGC_PERSISTENT_H_
static constexpr SourceLocation Current()
BasicPersistent & operator=(BasicPersistent &&other) noexcept
Definition persistent.h:144
BasicPersistent(BasicPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
Definition persistent.h:106
BasicPersistent(T *raw, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:76
BasicPersistent(const BasicPersistent &other, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:90
BasicPersistent(std::nullptr_t, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:67
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=(const internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > &member)
Definition persistent.h:161
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:98
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:63
BasicPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:85
BasicPersistent(const internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy > &member, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:121
BasicPersistent(SentinelPointer s, const SourceLocation &loc=SourceLocation::Current())
Definition persistent.h:71
const void * GetValue() const
Definition persistent.h:31
PersistentBase(const void *raw)
Definition persistent.h:29
void SetValue(const void *value)
Definition persistent.h:32
PersistentNode * GetNode() const
Definition persistent.h:34
void SetNode(PersistentNode *node)
Definition persistent.h:35
bool operator!=(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1 > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2 > &member2)
Definition member.h:244
bool operator==(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1 > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2 > &member2)
Definition member.h:234
constexpr internal::SentinelPointer kSentinelPointer
#define V8_CLANG_NO_SANITIZE(what)
Definition v8config.h:544