File indexing completed on 2025-04-02 08:54:42
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 const SourceLocation& loc = SourceLocation::Current())
0062 : LocationPolicy(loc) {}
0063
0064 BasicPersistent(std::nullptr_t,
0065 const SourceLocation& loc = SourceLocation::Current())
0066 : LocationPolicy(loc) {}
0067
0068 BasicPersistent(
0069 SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
0070 : PersistentBase(s), LocationPolicy(loc) {}
0071
0072
0073 BasicPersistent(T* raw,
0074 const 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 const SourceLocation& loc = SourceLocation::Current())
0084 : BasicPersistent(&raw, loc) {}
0085
0086
0087 BasicPersistent(const BasicPersistent& other,
0088 const 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<T, U>::value>>
0095
0096 BasicPersistent(
0097 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0098 OtherCheckingPolicy>& other,
0099 const SourceLocation& loc = SourceLocation::Current())
0100 : BasicPersistent(other.Get(), loc) {}
0101
0102
0103
0104 BasicPersistent(
0105 BasicPersistent&& other,
0106 const SourceLocation& loc = SourceLocation::Current()) noexcept
0107 : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
0108 if (!IsValid()) return;
0109 GetNode()->UpdateOwner(this);
0110 other.SetValue(nullptr);
0111 other.SetNode(nullptr);
0112 this->CheckPointer(Get());
0113 }
0114
0115
0116 template <typename U, typename MemberBarrierPolicy,
0117 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0118 typename MemberStorageType,
0119 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
0120
0121 BasicPersistent(const internal::BasicMember<
0122 U, MemberBarrierPolicy, MemberWeaknessTag,
0123 MemberCheckingPolicy, MemberStorageType>& member,
0124 const SourceLocation& loc = SourceLocation::Current())
0125 : BasicPersistent(member.Get(), loc) {}
0126
0127 ~BasicPersistent() { Clear(); }
0128
0129
0130 BasicPersistent& operator=(const BasicPersistent& other) {
0131 return operator=(other.Get());
0132 }
0133
0134 template <typename U, typename OtherWeaknessPolicy,
0135 typename OtherLocationPolicy, typename OtherCheckingPolicy,
0136 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
0137 BasicPersistent& operator=(
0138 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0139 OtherCheckingPolicy>& other) {
0140 return operator=(other.Get());
0141 }
0142
0143
0144 BasicPersistent& operator=(BasicPersistent&& other) noexcept {
0145 if (this == &other) return *this;
0146 Clear();
0147 PersistentBase::operator=(std::move(other));
0148 LocationPolicy::operator=(std::move(other));
0149 if (!IsValid()) return *this;
0150 GetNode()->UpdateOwner(this);
0151 other.SetValue(nullptr);
0152 other.SetNode(nullptr);
0153 this->CheckPointer(Get());
0154 return *this;
0155 }
0156
0157
0158 template <typename U, typename MemberBarrierPolicy,
0159 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0160 typename MemberStorageType,
0161 typename = std::enable_if_t<std::is_base_of<T, U>::value>>
0162 BasicPersistent& operator=(
0163 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
0164 MemberCheckingPolicy, MemberStorageType>&
0165 member) {
0166 return operator=(member.Get());
0167 }
0168
0169 BasicPersistent& operator=(T* other) {
0170 Assign(other);
0171 return *this;
0172 }
0173
0174 BasicPersistent& operator=(std::nullptr_t) {
0175 Clear();
0176 return *this;
0177 }
0178
0179 BasicPersistent& operator=(SentinelPointer s) {
0180 Assign(s);
0181 return *this;
0182 }
0183
0184 explicit operator bool() const { return Get(); }
0185
0186
0187 operator T*() const { return Get(); }
0188 T* operator->() const { return Get(); }
0189 T& operator*() const { return *Get(); }
0190
0191
0192
0193
0194 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
0195
0196
0197
0198 return static_cast<T*>(const_cast<void*>(GetValue()));
0199 }
0200
0201 void Clear() {
0202
0203
0204 if (IsValid()) {
0205 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0206 SetNode(nullptr);
0207 }
0208 SetValue(nullptr);
0209 }
0210
0211 T* Release() {
0212 T* result = Get();
0213 Clear();
0214 return result;
0215 }
0216
0217 template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
0218 typename OtherLocationPolicy = LocationPolicy,
0219 typename OtherCheckingPolicy = CheckingPolicy>
0220 BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0221 OtherCheckingPolicy>
0222 To() const {
0223 return BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
0224 OtherCheckingPolicy>(static_cast<U*>(Get()));
0225 }
0226
0227 private:
0228 static void TraceAsRoot(RootVisitor& root_visitor, const void* ptr) {
0229 root_visitor.Trace(*static_cast<const BasicPersistent*>(ptr));
0230 }
0231
0232 bool IsValid() const {
0233
0234
0235
0236 return GetValue() != nullptr && GetValue() != kSentinelPointer;
0237 }
0238
0239 void Assign(T* ptr) {
0240 if (IsValid()) {
0241 if (ptr && ptr != kSentinelPointer) {
0242
0243 SetValue(ptr);
0244 this->CheckPointer(ptr);
0245 return;
0246 }
0247 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0248 SetNode(nullptr);
0249 }
0250 SetValue(ptr);
0251 if (!IsValid()) return;
0252 SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
0253 .AllocateNode(this, &TraceAsRoot));
0254 this->CheckPointer(Get());
0255 }
0256
0257 void ClearFromGC() const {
0258 if (IsValid()) {
0259 WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
0260 PersistentBase::ClearFromGC();
0261 }
0262 }
0263
0264
0265 V8_CLANG_NO_SANITIZE("cfi-unrelated-cast")
0266 T* GetFromGC() const {
0267 return static_cast<T*>(const_cast<void*>(GetValue()));
0268 }
0269
0270 friend class internal::RootVisitor;
0271 };
0272
0273 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
0274 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
0275 typename LocationPolicy2, typename CheckingPolicy2>
0276 bool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
0277 CheckingPolicy1>& p1,
0278 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
0279 CheckingPolicy2>& p2) {
0280 return p1.Get() == p2.Get();
0281 }
0282
0283 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
0284 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
0285 typename LocationPolicy2, typename CheckingPolicy2>
0286 bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
0287 CheckingPolicy1>& p1,
0288 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
0289 CheckingPolicy2>& p2) {
0290 return !(p1 == p2);
0291 }
0292
0293 template <typename T1, typename PersistentWeaknessPolicy,
0294 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
0295 typename T2, typename MemberWriteBarrierPolicy,
0296 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0297 typename MemberStorageType>
0298 bool operator==(
0299 const BasicPersistent<T1, PersistentWeaknessPolicy,
0300 PersistentLocationPolicy, PersistentCheckingPolicy>&
0301 p,
0302 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0303 MemberCheckingPolicy, MemberStorageType>& m) {
0304 return p.Get() == m.Get();
0305 }
0306
0307 template <typename T1, typename PersistentWeaknessPolicy,
0308 typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
0309 typename T2, typename MemberWriteBarrierPolicy,
0310 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0311 typename MemberStorageType>
0312 bool operator!=(
0313 const BasicPersistent<T1, PersistentWeaknessPolicy,
0314 PersistentLocationPolicy, PersistentCheckingPolicy>&
0315 p,
0316 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0317 MemberCheckingPolicy, MemberStorageType>& m) {
0318 return !(p == m);
0319 }
0320
0321 template <typename T1, typename MemberWriteBarrierPolicy,
0322 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0323 typename MemberStorageType, typename T2,
0324 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
0325 typename PersistentCheckingPolicy>
0326 bool operator==(
0327 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0328 MemberCheckingPolicy, MemberStorageType>& m,
0329 const BasicPersistent<T1, PersistentWeaknessPolicy,
0330 PersistentLocationPolicy, PersistentCheckingPolicy>&
0331 p) {
0332 return m.Get() == p.Get();
0333 }
0334
0335 template <typename T1, typename MemberWriteBarrierPolicy,
0336 typename MemberWeaknessTag, typename MemberCheckingPolicy,
0337 typename MemberStorageType, typename T2,
0338 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
0339 typename PersistentCheckingPolicy>
0340 bool operator!=(
0341 const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
0342 MemberCheckingPolicy, MemberStorageType>& m,
0343 const BasicPersistent<T1, PersistentWeaknessPolicy,
0344 PersistentLocationPolicy, PersistentCheckingPolicy>&
0345 p) {
0346 return !(m == p);
0347 }
0348
0349 template <typename T, typename LocationPolicy, typename CheckingPolicy>
0350 struct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy,
0351 CheckingPolicy>> : std::true_type {};
0352 }
0353
0354
0355
0356
0357
0358
0359
0360
0361 template <typename T>
0362 using Persistent =
0363 internal::BasicPersistent<T, internal::StrongPersistentPolicy>;
0364
0365
0366
0367
0368
0369
0370
0371 template <typename T>
0372 using WeakPersistent =
0373 internal::BasicPersistent<T, internal::WeakPersistentPolicy>;
0374
0375 }
0376
0377 #endif