diff options
Diffstat (limited to 'chromium/v8/include/cppgc/persistent.h')
-rw-r--r-- | chromium/v8/include/cppgc/persistent.h | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/chromium/v8/include/cppgc/persistent.h b/chromium/v8/include/cppgc/persistent.h index fc6b0b9d92e..c2d8a7a5a64 100644 --- a/chromium/v8/include/cppgc/persistent.h +++ b/chromium/v8/include/cppgc/persistent.h @@ -15,14 +15,43 @@ #include "v8config.h" // NOLINT(build/include_directory) namespace cppgc { + +class Visitor; + namespace internal { +class PersistentBase { + protected: + PersistentBase() = default; + explicit PersistentBase(void* raw) : raw_(raw) {} + + void* GetValue() const { return raw_; } + void SetValue(void* value) { raw_ = value; } + + PersistentNode* GetNode() const { return node_; } + void SetNode(PersistentNode* node) { node_ = node; } + + // Performs a shallow clear which assumes that internal persistent nodes are + // destroyed elsewhere. + void ClearFromGC() const { + raw_ = nullptr; + node_ = nullptr; + } + + private: + mutable void* raw_ = nullptr; + mutable PersistentNode* node_ = nullptr; + + friend class PersistentRegion; +}; + // The basic class from which all Persistent classes are generated. template <typename T, typename WeaknessPolicy, typename LocationPolicy, typename CheckingPolicy> -class BasicPersistent : public LocationPolicy, - private WeaknessPolicy, - private CheckingPolicy { +class BasicPersistent final : public PersistentBase, + public LocationPolicy, + private WeaknessPolicy, + private CheckingPolicy { public: using typename WeaknessPolicy::IsStrongPersistent; using PointeeType = T; @@ -38,15 +67,15 @@ class BasicPersistent : public LocationPolicy, BasicPersistent( // NOLINT SentinelPointer s, const SourceLocation& loc = SourceLocation::Current()) - : LocationPolicy(loc), raw_(s) {} + : PersistentBase(s), LocationPolicy(loc) {} - // Raw value contstructors. + // Raw value constructors. BasicPersistent(T* raw, // NOLINT const SourceLocation& loc = SourceLocation::Current()) - : LocationPolicy(loc), raw_(raw) { + : PersistentBase(raw), LocationPolicy(loc) { if (!IsValid()) return; - node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode( - this, &BasicPersistent::Trace); + SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) + .AllocateNode(this, &BasicPersistent::Trace)); this->CheckPointer(Get()); } @@ -74,13 +103,11 @@ class BasicPersistent : public LocationPolicy, BasicPersistent( BasicPersistent&& other, const SourceLocation& loc = SourceLocation::Current()) noexcept - : LocationPolicy(std::move(other)), - raw_(std::move(other.raw_)), - node_(std::move(other.node_)) { + : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) { if (!IsValid()) return; - node_->UpdateOwner(this); - other.raw_ = nullptr; - other.node_ = nullptr; + GetNode()->UpdateOwner(this); + other.SetValue(nullptr); + other.SetNode(nullptr); this->CheckPointer(Get()); } @@ -114,13 +141,12 @@ class BasicPersistent : public LocationPolicy, BasicPersistent& operator=(BasicPersistent&& other) { if (this == &other) return *this; Clear(); + PersistentBase::operator=(std::move(other)); LocationPolicy::operator=(std::move(other)); - raw_ = std::move(other.raw_); - node_ = std::move(other.node_); if (!IsValid()) return *this; - node_->UpdateOwner(this); - other.raw_ = nullptr; - other.node_ = nullptr; + GetNode()->UpdateOwner(this); + other.SetValue(nullptr); + other.SetNode(nullptr); this->CheckPointer(Get()); return *this; } @@ -156,7 +182,12 @@ class BasicPersistent : public LocationPolicy, T* operator->() const { return Get(); } T& operator*() const { return *Get(); } - T* Get() const { return raw_; } + // CFI cast exemption to allow passing SentinelPointer through T* and support + // heterogeneous assignments between different Member and Persistent handles + // based on their actual types. + V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const { + return static_cast<T*>(GetValue()); + } void Clear() { Assign(nullptr); } @@ -176,29 +207,35 @@ class BasicPersistent : public LocationPolicy, // Ideally, handling kSentinelPointer would be done by the embedder. On the // other hand, having Persistent aware of it is beneficial since no node // gets wasted. - return raw_ != nullptr && raw_ != kSentinelPointer; + return GetValue() != nullptr && GetValue() != kSentinelPointer; } void Assign(T* ptr) { if (IsValid()) { if (ptr && ptr != kSentinelPointer) { // Simply assign the pointer reusing the existing node. - raw_ = ptr; + SetValue(ptr); this->CheckPointer(ptr); return; } - WeaknessPolicy::GetPersistentRegion(raw_).FreeNode(node_); - node_ = nullptr; + WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode()); + SetNode(nullptr); } - raw_ = ptr; + SetValue(ptr); if (!IsValid()) return; - node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode( - this, &BasicPersistent::Trace); + SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) + .AllocateNode(this, &BasicPersistent::Trace)); this->CheckPointer(Get()); } - T* raw_ = nullptr; - PersistentNode* node_ = nullptr; + void ClearFromGC() const { + if (IsValid()) { + WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode()); + PersistentBase::ClearFromGC(); + } + } + + friend class cppgc::Visitor; }; template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1, |