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>>
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_
Definition: member.h:77
Definition: persistent.h:54
BasicPersistent(T &raw, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:82
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
T PointeeType
Definition: persistent.h:57
BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > To() const
Definition: persistent.h:222
BasicPersistent(const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:60
BasicPersistent & operator=(BasicPersistent &&other) noexcept
Definition: persistent.h:144
T * Release()
Definition: persistent.h:211
~BasicPersistent()
Definition: persistent.h:127
void Clear()
Definition: persistent.h:201
T * operator->() const
Definition: persistent.h:188
BasicPersistent & operator=(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other)
Definition: persistent.h:137
BasicPersistent & operator=(const BasicPersistent &other)
Definition: persistent.h:130
BasicPersistent(SentinelPointer s, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:68
T & operator*() const
Definition: persistent.h:189
BasicPersistent & operator=(const internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy, MemberStorageType > &member)
Definition: persistent.h:162
BasicPersistent(BasicPersistent &&other, const SourceLocation &loc=SourceLocation::Current()) noexcept
Definition: persistent.h:104
BasicPersistent(const internal::BasicMember< U, MemberBarrierPolicy, MemberWeaknessTag, MemberCheckingPolicy, MemberStorageType > &member, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:121
BasicPersistent(std::nullptr_t, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:64
T * Get() const
Definition: persistent.h:194
BasicPersistent & operator=(T *other)
Definition: persistent.h:169
BasicPersistent(const BasicPersistent< U, OtherWeaknessPolicy, OtherLocationPolicy, OtherCheckingPolicy > &other, const SourceLocation &loc=SourceLocation::Current())
Definition: persistent.h:96
BasicPersistent & operator=(std::nullptr_t)
Definition: persistent.h:174
BasicPersistent & operator=(SentinelPointer s)
Definition: persistent.h:179
Definition: persistent.h:23
void ClearFromGC() const
Definition: persistent.h:36
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
const void * raw_
Definition: persistent.h:42
PersistentNode * node_
Definition: persistent.h:43
void SetNode(PersistentNode *node)
Definition: persistent.h:32
Definition: persistent-node.h:27
void UpdateOwner(void *owner)
Definition: persistent-node.h:45
Definition: persistent-node.h:78
Definition: visitor.h:441
void Trace(const AnyStrongPersistentType &p)
Definition: visitor.h:450
Definition: v8-source-location.h:31
static constexpr SourceLocation Current()
Definition: v8-source-location.h:44
bool operator!=(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1, StorageType > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2, StorageType > &member2)
Definition: member.h:368
bool operator==(const BasicMember< T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1, StorageType > &member1, const BasicMember< T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2, StorageType > &member2)
Definition: member.h:348
Definition: allocation.h:38
constexpr internal::SentinelPointer kSentinelPointer
Definition: sentinel-pointer.h:35
Definition: type-traits.h:30
Definition: sentinel-pointer.h:17
Definition: pointer-policies.h:245
#define V8_CLANG_NO_SANITIZE(what)
defined(V8_TRIVIAL_ABI)
Definition: v8config.h:754