v8 10.2.154 (node 18.16.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 {
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