11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_PERSISTENT_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_PERSISTENT_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <type_traits>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "cppgc/internal/persistent-node.h"
111cb0ef41Sopenharmony_ci#include "cppgc/internal/pointer-policies.h"
121cb0ef41Sopenharmony_ci#include "cppgc/sentinel-pointer.h"
131cb0ef41Sopenharmony_ci#include "cppgc/source-location.h"
141cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h"
151cb0ef41Sopenharmony_ci#include "cppgc/visitor.h"
161cb0ef41Sopenharmony_ci#include "v8config.h"  // NOLINT(build/include_directory)
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace cppgc {
191cb0ef41Sopenharmony_cinamespace internal {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci// PersistentBase always refers to the object as const object and defers to
221cb0ef41Sopenharmony_ci// BasicPersistent on casting to the right type as needed.
231cb0ef41Sopenharmony_ciclass PersistentBase {
241cb0ef41Sopenharmony_ci protected:
251cb0ef41Sopenharmony_ci  PersistentBase() = default;
261cb0ef41Sopenharmony_ci  explicit PersistentBase(const void* raw) : raw_(raw) {}
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  const void* GetValue() const { return raw_; }
291cb0ef41Sopenharmony_ci  void SetValue(const void* value) { raw_ = value; }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  PersistentNode* GetNode() const { return node_; }
321cb0ef41Sopenharmony_ci  void SetNode(PersistentNode* node) { node_ = node; }
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  // Performs a shallow clear which assumes that internal persistent nodes are
351cb0ef41Sopenharmony_ci  // destroyed elsewhere.
361cb0ef41Sopenharmony_ci  void ClearFromGC() const {
371cb0ef41Sopenharmony_ci    raw_ = nullptr;
381cb0ef41Sopenharmony_ci    node_ = nullptr;
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci protected:
421cb0ef41Sopenharmony_ci  mutable const void* raw_ = nullptr;
431cb0ef41Sopenharmony_ci  mutable PersistentNode* node_ = nullptr;
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  friend class PersistentRegionBase;
461cb0ef41Sopenharmony_ci};
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci// The basic class from which all Persistent classes are generated.
491cb0ef41Sopenharmony_citemplate <typename T, typename WeaknessPolicy, typename LocationPolicy,
501cb0ef41Sopenharmony_ci          typename CheckingPolicy>
511cb0ef41Sopenharmony_ciclass BasicPersistent final : public PersistentBase,
521cb0ef41Sopenharmony_ci                              public LocationPolicy,
531cb0ef41Sopenharmony_ci                              private WeaknessPolicy,
541cb0ef41Sopenharmony_ci                              private CheckingPolicy {
551cb0ef41Sopenharmony_ci public:
561cb0ef41Sopenharmony_ci  using typename WeaknessPolicy::IsStrongPersistent;
571cb0ef41Sopenharmony_ci  using PointeeType = T;
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  // Null-state/sentinel constructors.
601cb0ef41Sopenharmony_ci  BasicPersistent(  // NOLINT
611cb0ef41Sopenharmony_ci      const SourceLocation& loc = SourceLocation::Current())
621cb0ef41Sopenharmony_ci      : LocationPolicy(loc) {}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  BasicPersistent(std::nullptr_t,  // NOLINT
651cb0ef41Sopenharmony_ci                  const SourceLocation& loc = SourceLocation::Current())
661cb0ef41Sopenharmony_ci      : LocationPolicy(loc) {}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  BasicPersistent(  // NOLINT
691cb0ef41Sopenharmony_ci      SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
701cb0ef41Sopenharmony_ci      : PersistentBase(s), LocationPolicy(loc) {}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  // Raw value constructors.
731cb0ef41Sopenharmony_ci  BasicPersistent(T* raw,  // NOLINT
741cb0ef41Sopenharmony_ci                  const SourceLocation& loc = SourceLocation::Current())
751cb0ef41Sopenharmony_ci      : PersistentBase(raw), LocationPolicy(loc) {
761cb0ef41Sopenharmony_ci    if (!IsValid()) return;
771cb0ef41Sopenharmony_ci    SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
781cb0ef41Sopenharmony_ci                .AllocateNode(this, &TraceAsRoot));
791cb0ef41Sopenharmony_ci    this->CheckPointer(Get());
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  BasicPersistent(T& raw,  // NOLINT
831cb0ef41Sopenharmony_ci                  const SourceLocation& loc = SourceLocation::Current())
841cb0ef41Sopenharmony_ci      : BasicPersistent(&raw, loc) {}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  // Copy ctor.
871cb0ef41Sopenharmony_ci  BasicPersistent(const BasicPersistent& other,
881cb0ef41Sopenharmony_ci                  const SourceLocation& loc = SourceLocation::Current())
891cb0ef41Sopenharmony_ci      : BasicPersistent(other.Get(), loc) {}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  // Heterogeneous ctor.
921cb0ef41Sopenharmony_ci  template <typename U, typename OtherWeaknessPolicy,
931cb0ef41Sopenharmony_ci            typename OtherLocationPolicy, typename OtherCheckingPolicy,
941cb0ef41Sopenharmony_ci            typename = std::enable_if_t<std::is_base_of<T, U>::value>>
951cb0ef41Sopenharmony_ci  BasicPersistent(
961cb0ef41Sopenharmony_ci      const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
971cb0ef41Sopenharmony_ci                            OtherCheckingPolicy>& other,
981cb0ef41Sopenharmony_ci      const SourceLocation& loc = SourceLocation::Current())
991cb0ef41Sopenharmony_ci      : BasicPersistent(other.Get(), loc) {}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  // Move ctor. The heterogeneous move ctor is not supported since e.g.
1021cb0ef41Sopenharmony_ci  // persistent can't reuse persistent node from weak persistent.
1031cb0ef41Sopenharmony_ci  BasicPersistent(
1041cb0ef41Sopenharmony_ci      BasicPersistent&& other,
1051cb0ef41Sopenharmony_ci      const SourceLocation& loc = SourceLocation::Current()) noexcept
1061cb0ef41Sopenharmony_ci      : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
1071cb0ef41Sopenharmony_ci    if (!IsValid()) return;
1081cb0ef41Sopenharmony_ci    GetNode()->UpdateOwner(this);
1091cb0ef41Sopenharmony_ci    other.SetValue(nullptr);
1101cb0ef41Sopenharmony_ci    other.SetNode(nullptr);
1111cb0ef41Sopenharmony_ci    this->CheckPointer(Get());
1121cb0ef41Sopenharmony_ci  }
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  // Constructor from member.
1151cb0ef41Sopenharmony_ci  template <typename U, typename MemberBarrierPolicy,
1161cb0ef41Sopenharmony_ci            typename MemberWeaknessTag, typename MemberCheckingPolicy,
1171cb0ef41Sopenharmony_ci            typename MemberStorageType,
1181cb0ef41Sopenharmony_ci            typename = std::enable_if_t<std::is_base_of<T, U>::value>>
1191cb0ef41Sopenharmony_ci  BasicPersistent(const internal::BasicMember<
1201cb0ef41Sopenharmony_ci                      U, MemberBarrierPolicy, MemberWeaknessTag,
1211cb0ef41Sopenharmony_ci                      MemberCheckingPolicy, MemberStorageType>& member,
1221cb0ef41Sopenharmony_ci                  const SourceLocation& loc = SourceLocation::Current())
1231cb0ef41Sopenharmony_ci      : BasicPersistent(member.Get(), loc) {}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  ~BasicPersistent() { Clear(); }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  // Copy assignment.
1281cb0ef41Sopenharmony_ci  BasicPersistent& operator=(const BasicPersistent& other) {
1291cb0ef41Sopenharmony_ci    return operator=(other.Get());
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  template <typename U, typename OtherWeaknessPolicy,
1331cb0ef41Sopenharmony_ci            typename OtherLocationPolicy, typename OtherCheckingPolicy,
1341cb0ef41Sopenharmony_ci            typename = std::enable_if_t<std::is_base_of<T, U>::value>>
1351cb0ef41Sopenharmony_ci  BasicPersistent& operator=(
1361cb0ef41Sopenharmony_ci      const BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
1371cb0ef41Sopenharmony_ci                            OtherCheckingPolicy>& other) {
1381cb0ef41Sopenharmony_ci    return operator=(other.Get());
1391cb0ef41Sopenharmony_ci  }
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  // Move assignment.
1421cb0ef41Sopenharmony_ci  BasicPersistent& operator=(BasicPersistent&& other) noexcept {
1431cb0ef41Sopenharmony_ci    if (this == &other) return *this;
1441cb0ef41Sopenharmony_ci    Clear();
1451cb0ef41Sopenharmony_ci    PersistentBase::operator=(std::move(other));
1461cb0ef41Sopenharmony_ci    LocationPolicy::operator=(std::move(other));
1471cb0ef41Sopenharmony_ci    if (!IsValid()) return *this;
1481cb0ef41Sopenharmony_ci    GetNode()->UpdateOwner(this);
1491cb0ef41Sopenharmony_ci    other.SetValue(nullptr);
1501cb0ef41Sopenharmony_ci    other.SetNode(nullptr);
1511cb0ef41Sopenharmony_ci    this->CheckPointer(Get());
1521cb0ef41Sopenharmony_ci    return *this;
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  // Assignment from member.
1561cb0ef41Sopenharmony_ci  template <typename U, typename MemberBarrierPolicy,
1571cb0ef41Sopenharmony_ci            typename MemberWeaknessTag, typename MemberCheckingPolicy,
1581cb0ef41Sopenharmony_ci            typename MemberStorageType,
1591cb0ef41Sopenharmony_ci            typename = std::enable_if_t<std::is_base_of<T, U>::value>>
1601cb0ef41Sopenharmony_ci  BasicPersistent& operator=(
1611cb0ef41Sopenharmony_ci      const internal::BasicMember<U, MemberBarrierPolicy, MemberWeaknessTag,
1621cb0ef41Sopenharmony_ci                                  MemberCheckingPolicy, MemberStorageType>&
1631cb0ef41Sopenharmony_ci          member) {
1641cb0ef41Sopenharmony_ci    return operator=(member.Get());
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  BasicPersistent& operator=(T* other) {
1681cb0ef41Sopenharmony_ci    Assign(other);
1691cb0ef41Sopenharmony_ci    return *this;
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  BasicPersistent& operator=(std::nullptr_t) {
1731cb0ef41Sopenharmony_ci    Clear();
1741cb0ef41Sopenharmony_ci    return *this;
1751cb0ef41Sopenharmony_ci  }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  BasicPersistent& operator=(SentinelPointer s) {
1781cb0ef41Sopenharmony_ci    Assign(s);
1791cb0ef41Sopenharmony_ci    return *this;
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  explicit operator bool() const { return Get(); }
1831cb0ef41Sopenharmony_ci  operator T*() const { return Get(); }
1841cb0ef41Sopenharmony_ci  T* operator->() const { return Get(); }
1851cb0ef41Sopenharmony_ci  T& operator*() const { return *Get(); }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  // CFI cast exemption to allow passing SentinelPointer through T* and support
1881cb0ef41Sopenharmony_ci  // heterogeneous assignments between different Member and Persistent handles
1891cb0ef41Sopenharmony_ci  // based on their actual types.
1901cb0ef41Sopenharmony_ci  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
1911cb0ef41Sopenharmony_ci    // The const_cast below removes the constness from PersistentBase storage.
1921cb0ef41Sopenharmony_ci    // The following static_cast re-adds any constness if specified through the
1931cb0ef41Sopenharmony_ci    // user-visible template parameter T.
1941cb0ef41Sopenharmony_ci    return static_cast<T*>(const_cast<void*>(GetValue()));
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  void Clear() {
1981cb0ef41Sopenharmony_ci    // Simplified version of `Assign()` to allow calling without a complete type
1991cb0ef41Sopenharmony_ci    // `T`.
2001cb0ef41Sopenharmony_ci    if (IsValid()) {
2011cb0ef41Sopenharmony_ci      WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
2021cb0ef41Sopenharmony_ci      SetNode(nullptr);
2031cb0ef41Sopenharmony_ci    }
2041cb0ef41Sopenharmony_ci    SetValue(nullptr);
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  T* Release() {
2081cb0ef41Sopenharmony_ci    T* result = Get();
2091cb0ef41Sopenharmony_ci    Clear();
2101cb0ef41Sopenharmony_ci    return result;
2111cb0ef41Sopenharmony_ci  }
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  template <typename U, typename OtherWeaknessPolicy = WeaknessPolicy,
2141cb0ef41Sopenharmony_ci            typename OtherLocationPolicy = LocationPolicy,
2151cb0ef41Sopenharmony_ci            typename OtherCheckingPolicy = CheckingPolicy>
2161cb0ef41Sopenharmony_ci  BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
2171cb0ef41Sopenharmony_ci                  OtherCheckingPolicy>
2181cb0ef41Sopenharmony_ci  To() const {
2191cb0ef41Sopenharmony_ci    return BasicPersistent<U, OtherWeaknessPolicy, OtherLocationPolicy,
2201cb0ef41Sopenharmony_ci                           OtherCheckingPolicy>(static_cast<U*>(Get()));
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci private:
2241cb0ef41Sopenharmony_ci  static void TraceAsRoot(RootVisitor& root_visitor, const void* ptr) {
2251cb0ef41Sopenharmony_ci    root_visitor.Trace(*static_cast<const BasicPersistent*>(ptr));
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  bool IsValid() const {
2291cb0ef41Sopenharmony_ci    // Ideally, handling kSentinelPointer would be done by the embedder. On the
2301cb0ef41Sopenharmony_ci    // other hand, having Persistent aware of it is beneficial since no node
2311cb0ef41Sopenharmony_ci    // gets wasted.
2321cb0ef41Sopenharmony_ci    return GetValue() != nullptr && GetValue() != kSentinelPointer;
2331cb0ef41Sopenharmony_ci  }
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  void Assign(T* ptr) {
2361cb0ef41Sopenharmony_ci    if (IsValid()) {
2371cb0ef41Sopenharmony_ci      if (ptr && ptr != kSentinelPointer) {
2381cb0ef41Sopenharmony_ci        // Simply assign the pointer reusing the existing node.
2391cb0ef41Sopenharmony_ci        SetValue(ptr);
2401cb0ef41Sopenharmony_ci        this->CheckPointer(ptr);
2411cb0ef41Sopenharmony_ci        return;
2421cb0ef41Sopenharmony_ci      }
2431cb0ef41Sopenharmony_ci      WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
2441cb0ef41Sopenharmony_ci      SetNode(nullptr);
2451cb0ef41Sopenharmony_ci    }
2461cb0ef41Sopenharmony_ci    SetValue(ptr);
2471cb0ef41Sopenharmony_ci    if (!IsValid()) return;
2481cb0ef41Sopenharmony_ci    SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
2491cb0ef41Sopenharmony_ci                .AllocateNode(this, &TraceAsRoot));
2501cb0ef41Sopenharmony_ci    this->CheckPointer(Get());
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  void ClearFromGC() const {
2541cb0ef41Sopenharmony_ci    if (IsValid()) {
2551cb0ef41Sopenharmony_ci      WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
2561cb0ef41Sopenharmony_ci      PersistentBase::ClearFromGC();
2571cb0ef41Sopenharmony_ci    }
2581cb0ef41Sopenharmony_ci  }
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  // Set Get() for details.
2611cb0ef41Sopenharmony_ci  V8_CLANG_NO_SANITIZE("cfi-unrelated-cast")
2621cb0ef41Sopenharmony_ci  T* GetFromGC() const {
2631cb0ef41Sopenharmony_ci    return static_cast<T*>(const_cast<void*>(GetValue()));
2641cb0ef41Sopenharmony_ci  }
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci  friend class internal::RootVisitor;
2671cb0ef41Sopenharmony_ci};
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_citemplate <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
2701cb0ef41Sopenharmony_ci          typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
2711cb0ef41Sopenharmony_ci          typename LocationPolicy2, typename CheckingPolicy2>
2721cb0ef41Sopenharmony_cibool operator==(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
2731cb0ef41Sopenharmony_ci                                      CheckingPolicy1>& p1,
2741cb0ef41Sopenharmony_ci                const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
2751cb0ef41Sopenharmony_ci                                      CheckingPolicy2>& p2) {
2761cb0ef41Sopenharmony_ci  return p1.Get() == p2.Get();
2771cb0ef41Sopenharmony_ci}
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_citemplate <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
2801cb0ef41Sopenharmony_ci          typename CheckingPolicy1, typename T2, typename WeaknessPolicy2,
2811cb0ef41Sopenharmony_ci          typename LocationPolicy2, typename CheckingPolicy2>
2821cb0ef41Sopenharmony_cibool operator!=(const BasicPersistent<T1, WeaknessPolicy1, LocationPolicy1,
2831cb0ef41Sopenharmony_ci                                      CheckingPolicy1>& p1,
2841cb0ef41Sopenharmony_ci                const BasicPersistent<T2, WeaknessPolicy2, LocationPolicy2,
2851cb0ef41Sopenharmony_ci                                      CheckingPolicy2>& p2) {
2861cb0ef41Sopenharmony_ci  return !(p1 == p2);
2871cb0ef41Sopenharmony_ci}
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_citemplate <typename T1, typename PersistentWeaknessPolicy,
2901cb0ef41Sopenharmony_ci          typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
2911cb0ef41Sopenharmony_ci          typename T2, typename MemberWriteBarrierPolicy,
2921cb0ef41Sopenharmony_ci          typename MemberWeaknessTag, typename MemberCheckingPolicy,
2931cb0ef41Sopenharmony_ci          typename MemberStorageType>
2941cb0ef41Sopenharmony_cibool operator==(
2951cb0ef41Sopenharmony_ci    const BasicPersistent<T1, PersistentWeaknessPolicy,
2961cb0ef41Sopenharmony_ci                          PersistentLocationPolicy, PersistentCheckingPolicy>&
2971cb0ef41Sopenharmony_ci        p,
2981cb0ef41Sopenharmony_ci    const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
2991cb0ef41Sopenharmony_ci                      MemberCheckingPolicy, MemberStorageType>& m) {
3001cb0ef41Sopenharmony_ci  return p.Get() == m.Get();
3011cb0ef41Sopenharmony_ci}
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_citemplate <typename T1, typename PersistentWeaknessPolicy,
3041cb0ef41Sopenharmony_ci          typename PersistentLocationPolicy, typename PersistentCheckingPolicy,
3051cb0ef41Sopenharmony_ci          typename T2, typename MemberWriteBarrierPolicy,
3061cb0ef41Sopenharmony_ci          typename MemberWeaknessTag, typename MemberCheckingPolicy,
3071cb0ef41Sopenharmony_ci          typename MemberStorageType>
3081cb0ef41Sopenharmony_cibool operator!=(
3091cb0ef41Sopenharmony_ci    const BasicPersistent<T1, PersistentWeaknessPolicy,
3101cb0ef41Sopenharmony_ci                          PersistentLocationPolicy, PersistentCheckingPolicy>&
3111cb0ef41Sopenharmony_ci        p,
3121cb0ef41Sopenharmony_ci    const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
3131cb0ef41Sopenharmony_ci                      MemberCheckingPolicy, MemberStorageType>& m) {
3141cb0ef41Sopenharmony_ci  return !(p == m);
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_citemplate <typename T1, typename MemberWriteBarrierPolicy,
3181cb0ef41Sopenharmony_ci          typename MemberWeaknessTag, typename MemberCheckingPolicy,
3191cb0ef41Sopenharmony_ci          typename MemberStorageType, typename T2,
3201cb0ef41Sopenharmony_ci          typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
3211cb0ef41Sopenharmony_ci          typename PersistentCheckingPolicy>
3221cb0ef41Sopenharmony_cibool operator==(
3231cb0ef41Sopenharmony_ci    const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
3241cb0ef41Sopenharmony_ci                      MemberCheckingPolicy, MemberStorageType>& m,
3251cb0ef41Sopenharmony_ci    const BasicPersistent<T1, PersistentWeaknessPolicy,
3261cb0ef41Sopenharmony_ci                          PersistentLocationPolicy, PersistentCheckingPolicy>&
3271cb0ef41Sopenharmony_ci        p) {
3281cb0ef41Sopenharmony_ci  return m.Get() == p.Get();
3291cb0ef41Sopenharmony_ci}
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_citemplate <typename T1, typename MemberWriteBarrierPolicy,
3321cb0ef41Sopenharmony_ci          typename MemberWeaknessTag, typename MemberCheckingPolicy,
3331cb0ef41Sopenharmony_ci          typename MemberStorageType, typename T2,
3341cb0ef41Sopenharmony_ci          typename PersistentWeaknessPolicy, typename PersistentLocationPolicy,
3351cb0ef41Sopenharmony_ci          typename PersistentCheckingPolicy>
3361cb0ef41Sopenharmony_cibool operator!=(
3371cb0ef41Sopenharmony_ci    const BasicMember<T2, MemberWeaknessTag, MemberWriteBarrierPolicy,
3381cb0ef41Sopenharmony_ci                      MemberCheckingPolicy, MemberStorageType>& m,
3391cb0ef41Sopenharmony_ci    const BasicPersistent<T1, PersistentWeaknessPolicy,
3401cb0ef41Sopenharmony_ci                          PersistentLocationPolicy, PersistentCheckingPolicy>&
3411cb0ef41Sopenharmony_ci        p) {
3421cb0ef41Sopenharmony_ci  return !(m == p);
3431cb0ef41Sopenharmony_ci}
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_citemplate <typename T, typename LocationPolicy, typename CheckingPolicy>
3461cb0ef41Sopenharmony_cistruct IsWeak<BasicPersistent<T, internal::WeakPersistentPolicy, LocationPolicy,
3471cb0ef41Sopenharmony_ci                              CheckingPolicy>> : std::true_type {};
3481cb0ef41Sopenharmony_ci}  // namespace internal
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci/**
3511cb0ef41Sopenharmony_ci * Persistent is a way to create a strong pointer from an off-heap object to
3521cb0ef41Sopenharmony_ci * another on-heap object. As long as the Persistent handle is alive the GC will
3531cb0ef41Sopenharmony_ci * keep the object pointed to alive. The Persistent handle is always a GC root
3541cb0ef41Sopenharmony_ci * from the point of view of the GC. Persistent must be constructed and
3551cb0ef41Sopenharmony_ci * destructed in the same thread.
3561cb0ef41Sopenharmony_ci */
3571cb0ef41Sopenharmony_citemplate <typename T>
3581cb0ef41Sopenharmony_ciusing Persistent =
3591cb0ef41Sopenharmony_ci    internal::BasicPersistent<T, internal::StrongPersistentPolicy>;
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci/**
3621cb0ef41Sopenharmony_ci * WeakPersistent is a way to create a weak pointer from an off-heap object to
3631cb0ef41Sopenharmony_ci * an on-heap object. The pointer is automatically cleared when the pointee gets
3641cb0ef41Sopenharmony_ci * collected. WeakPersistent must be constructed and destructed in the same
3651cb0ef41Sopenharmony_ci * thread.
3661cb0ef41Sopenharmony_ci */
3671cb0ef41Sopenharmony_citemplate <typename T>
3681cb0ef41Sopenharmony_ciusing WeakPersistent =
3691cb0ef41Sopenharmony_ci    internal::BasicPersistent<T, internal::WeakPersistentPolicy>;
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci}  // namespace cppgc
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_PERSISTENT_H_
374