Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/deps/v8/include/cppgc/persistent.h
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 10 #include "cppgc/internal/persistent-node.h" 11 #include "cppgc/internal/pointer-policies.h" 12 #include "cppgc/sentinel-pointer.h" 13 #include "cppgc/source-location.h" 14 #include "cppgc/type-traits.h" 15 #include "cppgc/visitor.h" 16 #include "v8config.h" // NOLINT(build/include_directory) 17 18 namespace cppgc { 19 namespace 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. 23 class PersistentBase { 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 45 friend class PersistentRegionBase; 46 }; 47 48 // The basic class from which all Persistent classes are generated. 49 template <typename T, typename WeaknessPolicy, typename LocationPolicy, 50 typename CheckingPolicy> 51 class 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 61 const SourceLocation& loc = SourceLocation::Current()) 62 : LocationPolicy(loc) {} 63 64 BasicPersistent(std::nullptr_t, // NOLINT 65 const SourceLocation& loc = SourceLocation::Current()) 66 : LocationPolicy(loc) {} 67 68 BasicPersistent( // NOLINT 69 SentinelPointer s, const SourceLocation& loc = SourceLocation::Current()) 70 : PersistentBase(s), LocationPolicy(loc) {} 71 72 // Raw value constructors. 73 BasicPersistent(T* raw, // NOLINT 74 const SourceLocation& loc = SourceLocation::Current()) 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 83 const SourceLocation& loc = SourceLocation::Current()) 84 : BasicPersistent(&raw, loc) {} 85 86 // Copy ctor. 87 BasicPersistent(const BasicPersistent& other, 88 const SourceLocation& loc = SourceLocation::Current()) 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 96 BasicPersistent( 97 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy, 98 OtherCheckingPolicy>& other, 99 const SourceLocation& loc = SourceLocation::Current()) 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. 104 BasicPersistent( 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 121 BasicPersistent(const internal::BasicMember< 122 U, MemberBarrierPolicy, MemberWeaknessTag, 123 MemberCheckingPolicy, MemberStorageType>& member, 124 const SourceLocation& loc = SourceLocation::Current()) 125 : BasicPersistent(member.Get(), loc) {} 126 127 ~BasicPersistent() { Clear(); } 128 129 // Copy assignment. 130 BasicPersistent& operator=(const BasicPersistent& other) { 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>> 137 BasicPersistent& operator=( 138 const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy, 139 OtherCheckingPolicy>& other) { 140 return operator=(other.Get()); 141 } 142 143 // Move assignment. 144 BasicPersistent& operator=(BasicPersistent&& other) noexcept { 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>> 162 BasicPersistent& operator=( 163 const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag, 164 MemberCheckingPolicy, MemberStorageType>& 165 member) { 166 return operator=(member.Get()); 167 } 168 169 BasicPersistent& operator=(T* other) { 170 Assign(other); 171 return *this; 172 } 173 174 BasicPersistent& operator=(std::nullptr_t) { 175 Clear(); 176 return *this; 177 } 178 179 BasicPersistent& operator=(SentinelPointer s) { 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()); 260 PersistentBase::ClearFromGC(); 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 270 friend class internal::RootVisitor; 271 }; 272 273 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1, 274 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2, 275 typename LocationPolicy2, typename CheckingPolicy2> 276 bool 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 283 template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1, 284 typename CheckingPolicy1, typename T2, typename WeaknessPolicy2, 285 typename LocationPolicy2, typename CheckingPolicy2> 286 bool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1, 287 CheckingPolicy1>& p1, 288 const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2, 289 CheckingPolicy2>& p2) { 290 return !(p1 == p2); 291 } 292 293 template <typename T1, typename PersistentWeaknessPolicy, 294 typename PersistentLocationPolicy, typename PersistentCheckingPolicy, 295 typename T2, typename MemberWriteBarrierPolicy, 296 typename MemberWeaknessTag, typename MemberCheckingPolicy, 297 typename MemberStorageType> 298 bool operator==( 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 307 template <typename T1, typename PersistentWeaknessPolicy, 308 typename PersistentLocationPolicy, typename PersistentCheckingPolicy, 309 typename T2, typename MemberWriteBarrierPolicy, 310 typename MemberWeaknessTag, typename MemberCheckingPolicy, 311 typename MemberStorageType> 312 bool operator!=( 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 321 template <typename T1, typename MemberWriteBarrierPolicy, 322 typename MemberWeaknessTag, typename MemberCheckingPolicy, 323 typename MemberStorageType, typename T2, 324 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy, 325 typename PersistentCheckingPolicy> 326 bool operator==( 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 335 template <typename T1, typename MemberWriteBarrierPolicy, 336 typename MemberWeaknessTag, typename MemberCheckingPolicy, 337 typename MemberStorageType, typename T2, 338 typename PersistentWeaknessPolicy, typename PersistentLocationPolicy, 339 typename PersistentCheckingPolicy> 340 bool operator!=( 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 349 template <typename T, typename LocationPolicy, typename CheckingPolicy> 350 struct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy, 351 CheckingPolicy>> : std::true_type {}; 352 } // namespace internal 353 354 /** 355 * Persistent is a way to create a strong pointer from an off-heap object to 356 * another on-heap object. As long as the Persistent handle is alive the GC will 357 * keep the object pointed to alive. The Persistent handle is always a GC root 358 * from the point of view of the GC. Persistent must be constructed and 359 * destructed in the same thread. 360 */ 361 template <typename T> 362 using Persistent = 363 internal::BasicPersistent<T, internal::StrongPersistentPolicy>; 364 365 /** 366 * WeakPersistent is a way to create a weak pointer from an off-heap object to 367 * an on-heap object. The pointer is automatically cleared when the pointee gets 368 * collected. WeakPersistent must be constructed and destructed in the same 369 * thread. 370 */ 371 template <typename T> 372 using WeakPersistent = 373 internal::BasicPersistent<T, internal::WeakPersistentPolicy>; 374 375 } // namespace cppgc 376 377 #endif // INCLUDE_CPPGC_PERSISTENT_H_