File indexing completed on 2026-08-30 08:57:00
0001
0002
0003
0004
0005 #ifndef INCLUDE_CPPGC_PERSISTENT_H_
0006 #define INCLUDE_CPPGC_PERSISTENT_H_
0007
0008 #include <type_traits>
0009
0010 #include "cppgc/internal/persistent-node.h"
0011 #include "cppgc/internal/pointer-policies.h"
0012 #include "cppgc/sentinel-pointer.h"
0013 #include "cppgc/source-location.h"
0014 #include "cppgc/type-traits.h"
0015 #include "cppgc/visitor.h"
0016 #include "v8config.h" // NOLINT(build/include_directory)
0017
0018 namespace cppgc {
0019 namespace internal {
0020
0021
0022
0023 class PersistentBase {
0024 protected:
0025 PersistentBase() = default;
0026 explicit PersistentBase(const void* raw) : raw_(raw) {}
0027
0028 const void* GetValue() const { return raw_; }
0029 void SetValue(const void* value) { raw_ = value; }
0030
0031 PersistentNode* GetNode() const { return node_; }
0032 void SetNode(PersistentNode* node) { node_ = node; }
0033
0034
0035
0036 void ClearFromGC() const {
0037 raw_ = nullptr;
0038 node_ = nullptr;
0039 }
0040
0041 protected:
0042 mutable const void* raw_ = nullptr;
0043 mutable PersistentNode* node_ = nullptr;
0044
0045 friend class PersistentRegionBase;
0046 };
0047
0048
0049 template <typename T, typename WeaknessPolicy, typename LocationPolicy,
0050 typename CheckingPolicy>
0051 class BasicPersistent final : public PersistentBase,
0052 public LocationPolicy,
0053 private WeaknessPolicy,
0054 private CheckingPolicy {
0055 public:
0056 using typename WeaknessPolicy::IsStrongPersistent;
0057 using PointeeType = T;
0058
0059
0060 BasicPersistent(
0061 SourceLocation loc = SourceLocation::Current())
0062 : LocationPolicy(loc) {}
0063
0064 BasicPersistent(std::nullptr_t,
0065 SourceLocation loc = SourceLocation::Current())
0066 : LocationPolicy(loc) {}
0067
0068 BasicPersistent(
0069 SentinelPointer s, SourceLocation loc = SourceLocation::Current())
0070 : PersistentBase(s), LocationPolicy(loc) {}
0071
0072
0073 BasicPersistent(T* raw,
0074 SourceLocation loc = SourceLocation::Current())
0075 : PersistentBase(raw), LocationPolicy(loc) {
0076 if (!IsValid()) return;
0077 SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
0078 .AllocateNode(this, &TraceAsRoot));
0079 this->CheckPointer(Get());
0080 }
0081
0082 BasicPersistent(T& raw,
0083 SourceLocation loc = SourceLocation::Current())
0084 : BasicPersistent(&raw, loc) {}
0085
0086
0087 BasicPersistent(const BasicPersistent& other,
0088 SourceLocation loc = SourceLocation::Current())
0089 : BasicPersistent(other.Get(), loc) {}
0090
0091
0092 template <typename U, typename OtherWeaknessPolicy,
0093 typename OtherLocationPolicy, typename OtherCheckingPolicy,
0094 typename = std::enable_if_t<std::is_base_of_v<T, U>>>
0095
0096 BasicPersistent(
0097 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0098 OtherCheckingPolicy>& other,
0099 SourceLocation loc = SourceLocation::Current())
0100 : BasicPersistent(other.Get(), loc) {}
0101
0102
0103
0104 BasicPersistent(BasicPersistent&& other,
0105 SourceLocation loc = SourceLocation::Current()) noexcept
0106 : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
0107 if (!IsValid()) return;
0108 GetNode()->UpdateOwner(this);
0109 other.SetValue(nullptr);
0110 other.SetNode(nullptr);
0111 this->CheckPointer(Get());
0112 }
0113
0114
0115 template <typename U, typename MemberBarrierPolicy,
0116 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0117 typename MemberStorageType,
0118 typename = std::enable_if_t<std::is_base_of_v<T, U>>>
0119
0120 BasicPersistent(const internal::BasicMember<
0121 U, MemberBarrierPolicy, MemberWeaknessTag,
0122 MemberCheckingPolicy, MemberStorageType>& member,
0123 SourceLocation loc = SourceLocation::Current())
0124 : BasicPersistent(member.Get(), loc) {}
0125
0126 ~BasicPersistent() { Clear(); }
0127
0128
0129 BasicPersistent& operator=(const BasicPersistent& other) {
0130 return operator=(other.Get());
0131 }
0132
0133 template <typename U, typename OtherWeaknessPolicy,
0134 typename OtherLocationPolicy, typename OtherCheckingPolicy,
0135 typename = std::enable_if_t<std::is_base_of_v<T, U>>>
0136 BasicPersistent& operator=(
0137 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0138 OtherCheckingPolicy>& other) {
0139 return operator=(other.Get());
0140 }
0141
0142
0143 BasicPersistent& operator=(BasicPersistent&& other) noexcept {
0144 if (this == &other) return *this;
0145 Clear();
0146 PersistentBase::operator=(std::move(other));
0147 LocationPolicy::operator=(std::move(other));
0148 if (!IsValid()) return *this;
0149 GetNode()->UpdateOwner(this);
0150 other.SetValue(nullptr);
0151 other.SetNode(nullptr);
0152 this->CheckPointer(Get());
0153 return *this;
0154 }
0155
0156
0157 template <typename U, typename MemberBarrierPolicy,
0158 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0159 typename MemberStorageType,
0160 typename = std::enable_if_t<std::is_base_of_v<T, U>>>
0161 BasicPersistent& operator=(
0162 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
0163 MemberCheckingPolicy, MemberStorageType>&
0164 member) {
0165 return operator=(member.Get());
0166 }
0167
0168 BasicPersistent& operator=(T* other) {
0169 Assign(other);
0170 return *this;
0171 }
0172
0173 BasicPersistent& operator=(std::nullptr_t) {
0174 Clear();
0175 return *this;
0176 }
0177
0178 BasicPersistent& operator=(SentinelPointer s) {
0179 Assign(s);
0180 return *this;
0181 }
0182
0183 explicit operator bool() const { return Get(); }
0184
0185
0186 operator T*() const { return Get(); }
0187 T* operator->() const { return Get(); }
0188 T& operator*() const { return *Get(); }
0189
0190
0191
0192
0193 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
0194
0195
0196
0197 return static_cast<T*>(const_cast<void*>(GetValue()));
0198 }
0199
0200 void Clear() {
0201
0202
0203 if (IsValid()) {
0204 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0205 SetNode(nullptr);
0206 }
0207 SetValue(nullptr);
0208 }
0209
0210 T* Release() {
0211 T* result = Get();
0212 Clear();
0213 return result;
0214 }
0215
0216 template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
0217 typename OtherLocationPolicy = LocationPolicy,
0218 typename OtherCheckingPolicy = CheckingPolicy>
0219 BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0220 OtherCheckingPolicy>
0221 To() const {
0222 return BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0223 OtherCheckingPolicy>(static_cast<U*>(Get()));
0224 }
0225
0226 private:
0227 static void TraceAsRoot(RootVisitor& root_visitor, const void* ptr) {
0228 root_visitor.Trace(*static_cast<const BasicPersistent*>(ptr));
0229 }
0230
0231 bool IsValid() const {
0232
0233
0234
0235 return GetValue() != nullptr && GetValue() != kSentinelPointer;
0236 }
0237
0238 void Assign(T* ptr) {
0239 if (IsValid()) {
0240 if (ptr && ptr != kSentinelPointer) {
0241
0242 SetValue(ptr);
0243 this->CheckPointer(ptr);
0244 return;
0245 }
0246 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0247 SetNode(nullptr);
0248 }
0249 SetValue(ptr);
0250 if (!IsValid()) return;
0251 SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
0252 .AllocateNode(this, &TraceAsRoot));
0253 this->CheckPointer(Get());
0254 }
0255
0256 void ClearFromGC() const {
0257 if (IsValid()) {
0258 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0259 PersistentBase::ClearFromGC();
0260 }
0261 }
0262
0263
0264 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast")
0265 T* GetFromGC() const {
0266 return static_cast<T*>(const_cast<void*>(GetValue()));
0267 }
0268
0269 friend class internal::RootVisitor;
0270 };
0271
0272 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
0273 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
0274 typename LocationPolicy2, typename CheckingPolicy2>
0275 bool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
0276 CheckingPolicy1>& p1,
0277 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
0278 CheckingPolicy2>& p2) {
0279 return p1.Get() == p2.Get();
0280 }
0281
0282 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
0283 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
0284 typename LocationPolicy2, typename CheckingPolicy2>
0285 bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
0286 CheckingPolicy1>& p1,
0287 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
0288 CheckingPolicy2>& p2) {
0289 return !(p1 == p2);
0290 }
0291
0292 template <typename T1, typename PersistentWeaknessPolicy,
0293 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
0294 typename T2, typename MemberWriteBarrierPolicy,
0295 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0296 typename MemberStorageType>
0297 bool operator==(
0298 const BasicPersistent<T1, PersistentWeaknessPolicy,
0299 PersistentLocationPolicy, PersistentCheckingPolicy>&
0300 p,
0301 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0302 MemberCheckingPolicy, MemberStorageType>& m) {
0303 return p.Get() == m.Get();
0304 }
0305
0306 template <typename T1, typename PersistentWeaknessPolicy,
0307 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
0308 typename T2, typename MemberWriteBarrierPolicy,
0309 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0310 typename MemberStorageType>
0311 bool operator!=(
0312 const BasicPersistent<T1, PersistentWeaknessPolicy,
0313 PersistentLocationPolicy, PersistentCheckingPolicy>&
0314 p,
0315 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0316 MemberCheckingPolicy, MemberStorageType>& m) {
0317 return !(p == m);
0318 }
0319
0320 template <typename T1, typename MemberWriteBarrierPolicy,
0321 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0322 typename MemberStorageType, typename T2,
0323 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
0324 typename PersistentCheckingPolicy>
0325 bool operator==(
0326 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0327 MemberCheckingPolicy, MemberStorageType>& m,
0328 const BasicPersistent<T1, PersistentWeaknessPolicy,
0329 PersistentLocationPolicy, PersistentCheckingPolicy>&
0330 p) {
0331 return m.Get() == p.Get();
0332 }
0333
0334 template <typename T1, typename MemberWriteBarrierPolicy,
0335 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0336 typename MemberStorageType, typename T2,
0337 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
0338 typename PersistentCheckingPolicy>
0339 bool operator!=(
0340 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0341 MemberCheckingPolicy, MemberStorageType>& m,
0342 const BasicPersistent<T1, PersistentWeaknessPolicy,
0343 PersistentLocationPolicy, PersistentCheckingPolicy>&
0344 p) {
0345 return !(m == p);
0346 }
0347
0348 template <typename T, typename LocationPolicy, typename CheckingPolicy>
0349 struct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy,
0350 CheckingPolicy>> : std::true_type {};
0351 }
0352
0353
0354
0355
0356
0357
0358
0359
0360 template <typename T>
0361 using Persistent =
0362 internal::BasicPersistent<T, internal::StrongPersistentPolicy>;
0363
0364
0365
0366
0367
0368
0369
0370 template <typename T>
0371 using WeakPersistent =
0372 internal::BasicPersistent<T, internal::WeakPersistentPolicy>;
0373
0374 }
0375
0376 #endif