Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:42:26

0001 // Copyright 2020 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef INCLUDE_CPPGC_MEMBER_H_
0006 #define INCLUDE_CPPGC_MEMBER_H_
0007 
0008 #include <atomic>
0009 #include <cstddef>
0010 #include <type_traits>
0011 
0012 #include "cppgc/internal/api-constants.h"
0013 #include "cppgc/internal/member-storage.h"
0014 #include "cppgc/internal/pointer-policies.h"
0015 #include "cppgc/sentinel-pointer.h"
0016 #include "cppgc/type-traits.h"
0017 #include "v8config.h"  // NOLINT(build/include_directory)
0018 
0019 namespace cppgc {
0020 
0021 namespace subtle {
0022 class HeapConsistency;
0023 }  // namespace subtle
0024 
0025 class Visitor;
0026 
0027 namespace internal {
0028 
0029 // MemberBase always refers to the object as const object and defers to
0030 // BasicMember on casting to the right type as needed.
0031 template <typename StorageType>
0032 class V8_TRIVIAL_ABI MemberBase {
0033  public:
0034   using RawStorage = StorageType;
0035 
0036  protected:
0037   struct AtomicInitializerTag {};
0038 
0039   V8_INLINE MemberBase() = default;
0040   V8_INLINE explicit MemberBase(const void* value) : raw_(value) {}
0041   V8_INLINE MemberBase(const void* value, AtomicInitializerTag) {
0042     SetRawAtomic(value);
0043   }
0044 
0045   V8_INLINE explicit MemberBase(RawStorage raw) : raw_(raw) {}
0046   V8_INLINE explicit MemberBase(std::nullptr_t) : raw_(nullptr) {}
0047   V8_INLINE explicit MemberBase(SentinelPointer s) : raw_(s) {}
0048 
0049   V8_INLINE const void** GetRawSlot() const {
0050     return reinterpret_cast<const void**>(const_cast<MemberBase*>(this));
0051   }
0052   V8_INLINE const void* GetRaw() const { return raw_.Load(); }
0053   V8_INLINE void SetRaw(void* value) { raw_.Store(value); }
0054 
0055   V8_INLINE const void* GetRawAtomic() const { return raw_.LoadAtomic(); }
0056   V8_INLINE void SetRawAtomic(const void* value) { raw_.StoreAtomic(value); }
0057 
0058   V8_INLINE RawStorage GetRawStorage() const { return raw_; }
0059   V8_INLINE void SetRawStorageAtomic(RawStorage other) {
0060     reinterpret_cast<std::atomic<RawStorage>&>(raw_).store(
0061         other, std::memory_order_relaxed);
0062   }
0063 
0064   V8_INLINE bool IsCleared() const { return raw_.IsCleared(); }
0065 
0066   V8_INLINE void ClearFromGC() const { raw_.Clear(); }
0067 
0068  private:
0069   friend class MemberDebugHelper;
0070 
0071   mutable RawStorage raw_;
0072 };
0073 
0074 // The basic class from which all Member classes are 'generated'.
0075 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0076           typename CheckingPolicy, typename StorageType>
0077 class V8_TRIVIAL_ABI BasicMember final : private MemberBase<StorageType>,
0078                                          private CheckingPolicy {
0079   using Base = MemberBase<StorageType>;
0080 
0081  public:
0082   using PointeeType = T;
0083   using RawStorage = typename Base::RawStorage;
0084 
0085   V8_INLINE constexpr BasicMember() = default;
0086   V8_INLINE constexpr BasicMember(std::nullptr_t) {}     // NOLINT
0087   V8_INLINE BasicMember(SentinelPointer s) : Base(s) {}  // NOLINT
0088   V8_INLINE BasicMember(T* raw) : Base(raw) {            // NOLINT
0089     InitializingWriteBarrier(raw);
0090     this->CheckPointer(Get());
0091   }
0092   V8_INLINE BasicMember(T& raw)  // NOLINT
0093       : BasicMember(&raw) {}
0094 
0095   // Atomic ctor. Using the AtomicInitializerTag forces BasicMember to
0096   // initialize using atomic assignments. This is required for preventing
0097   // data races with concurrent marking.
0098   using AtomicInitializerTag = typename Base::AtomicInitializerTag;
0099   V8_INLINE BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
0100       : Base(nullptr, atomic) {}
0101   V8_INLINE BasicMember(SentinelPointer s, AtomicInitializerTag atomic)
0102       : Base(s, atomic) {}
0103   V8_INLINE BasicMember(T* raw, AtomicInitializerTag atomic)
0104       : Base(raw, atomic) {
0105     InitializingWriteBarrier(raw);
0106     this->CheckPointer(Get());
0107   }
0108   V8_INLINE BasicMember(T& raw, AtomicInitializerTag atomic)
0109       : BasicMember(&raw, atomic) {}
0110 
0111   // Copy ctor.
0112   V8_INLINE BasicMember(const BasicMember& other)
0113       : BasicMember(other.GetRawStorage()) {}
0114 
0115   // Heterogeneous copy constructors. When the source pointer have a different
0116   // type, perform a compress-decompress round, because the source pointer may
0117   // need to be adjusted.
0118   template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
0119             typename OtherCheckingPolicy,
0120             std::enable_if_t<internal::IsDecayedSameV<T, U>>* = nullptr>
0121   V8_INLINE BasicMember(  // NOLINT
0122       const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
0123                         OtherCheckingPolicy, StorageType>& other)
0124       : BasicMember(other.GetRawStorage()) {}
0125 
0126   template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
0127             typename OtherCheckingPolicy,
0128             std::enable_if_t<internal::IsStrictlyBaseOfV<T, U>>* = nullptr>
0129   V8_INLINE BasicMember(  // NOLINT
0130       const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
0131                         OtherCheckingPolicy, StorageType>& other)
0132       : BasicMember(other.Get()) {}
0133 
0134   // Move ctor.
0135   V8_INLINE BasicMember(BasicMember&& other) noexcept
0136       : BasicMember(other.GetRawStorage()) {
0137     other.Clear();
0138   }
0139 
0140   // Heterogeneous move constructors. When the source pointer have a different
0141   // type, perform a compress-decompress round, because the source pointer may
0142   // need to be adjusted.
0143   template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
0144             typename OtherCheckingPolicy,
0145             std::enable_if_t<internal::IsDecayedSameV<T, U>>* = nullptr>
0146   V8_INLINE BasicMember(
0147       BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy,
0148                   StorageType>&& other) noexcept
0149       : BasicMember(other.GetRawStorage()) {
0150     other.Clear();
0151   }
0152 
0153   template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
0154             typename OtherCheckingPolicy,
0155             std::enable_if_t<internal::IsStrictlyBaseOfV<T, U>>* = nullptr>
0156   V8_INLINE BasicMember(
0157       BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy,
0158                   StorageType>&& other) noexcept
0159       : BasicMember(other.Get()) {
0160     other.Clear();
0161   }
0162 
0163   // Construction from Persistent.
0164   template <typename U, typename PersistentWeaknessPolicy,
0165             typename PersistentLocationPolicy,
0166             typename PersistentCheckingPolicy,
0167             typename = std::enable_if_t<std::is_base_of<T, U>::value>>
0168   V8_INLINE BasicMember(const BasicPersistent<U, PersistentWeaknessPolicy,
0169                                               PersistentLocationPolicy,
0170                                               PersistentCheckingPolicy>& p)
0171       : BasicMember(p.Get()) {}
0172 
0173   // Copy assignment.
0174   V8_INLINE BasicMember& operator=(const BasicMember& other) {
0175     return operator=(other.GetRawStorage());
0176   }
0177 
0178   // Heterogeneous copy assignment. When the source pointer have a different
0179   // type, perform a compress-decompress round, because the source pointer may
0180   // need to be adjusted.
0181   template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
0182             typename OtherCheckingPolicy>
0183   V8_INLINE BasicMember& operator=(
0184       const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
0185                         OtherCheckingPolicy, StorageType>& other) {
0186     if constexpr (internal::IsDecayedSameV<T, U>) {
0187       return operator=(other.GetRawStorage());
0188     } else {
0189       static_assert(internal::IsStrictlyBaseOfV<T, U>);
0190       return operator=(other.Get());
0191     }
0192   }
0193 
0194   // Move assignment.
0195   V8_INLINE BasicMember& operator=(BasicMember&& other) noexcept {
0196     operator=(other.GetRawStorage());
0197     other.Clear();
0198     return *this;
0199   }
0200 
0201   // Heterogeneous move assignment. When the source pointer have a different
0202   // type, perform a compress-decompress round, because the source pointer may
0203   // need to be adjusted.
0204   template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
0205             typename OtherCheckingPolicy>
0206   V8_INLINE BasicMember& operator=(
0207       BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy, OtherCheckingPolicy,
0208                   StorageType>&& other) noexcept {
0209     if constexpr (internal::IsDecayedSameV<T, U>) {
0210       operator=(other.GetRawStorage());
0211     } else {
0212       static_assert(internal::IsStrictlyBaseOfV<T, U>);
0213       operator=(other.Get());
0214     }
0215     other.Clear();
0216     return *this;
0217   }
0218 
0219   // Assignment from Persistent.
0220   template <typename U, typename PersistentWeaknessPolicy,
0221             typename PersistentLocationPolicy,
0222             typename PersistentCheckingPolicy,
0223             typename = std::enable_if_t<std::is_base_of<T, U>::value>>
0224   V8_INLINE BasicMember& operator=(
0225       const BasicPersistent<U, PersistentWeaknessPolicy,
0226                             PersistentLocationPolicy, PersistentCheckingPolicy>&
0227           other) {
0228     return operator=(other.Get());
0229   }
0230 
0231   V8_INLINE BasicMember& operator=(T* other) {
0232     Base::SetRawAtomic(other);
0233     AssigningWriteBarrier(other);
0234     this->CheckPointer(Get());
0235     return *this;
0236   }
0237 
0238   V8_INLINE BasicMember& operator=(std::nullptr_t) {
0239     Clear();
0240     return *this;
0241   }
0242   V8_INLINE BasicMember& operator=(SentinelPointer s) {
0243     Base::SetRawAtomic(s);
0244     return *this;
0245   }
0246 
0247   template <typename OtherWeaknessTag, typename OtherBarrierPolicy,
0248             typename OtherCheckingPolicy>
0249   V8_INLINE void Swap(BasicMember<T, OtherWeaknessTag, OtherBarrierPolicy,
0250                                   OtherCheckingPolicy, StorageType>& other) {
0251     auto tmp = GetRawStorage();
0252     *this = other;
0253     other = tmp;
0254   }
0255 
0256   V8_INLINE explicit operator bool() const { return !Base::IsCleared(); }
0257   V8_INLINE operator T*() const { return Get(); }
0258   V8_INLINE T* operator->() const { return Get(); }
0259   V8_INLINE T& operator*() const { return *Get(); }
0260 
0261   // CFI cast exemption to allow passing SentinelPointer through T* and support
0262   // heterogeneous assignments between different Member and Persistent handles
0263   // based on their actual types.
0264   V8_INLINE V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
0265     // Executed by the mutator, hence non atomic load.
0266     //
0267     // The const_cast below removes the constness from MemberBase storage. The
0268     // following static_cast re-adds any constness if specified through the
0269     // user-visible template parameter T.
0270     return static_cast<T*>(const_cast<void*>(Base::GetRaw()));
0271   }
0272 
0273   V8_INLINE void Clear() {
0274     Base::SetRawStorageAtomic(RawStorage{});
0275   }
0276 
0277   V8_INLINE T* Release() {
0278     T* result = Get();
0279     Clear();
0280     return result;
0281   }
0282 
0283   V8_INLINE const T** GetSlotForTesting() const {
0284     return reinterpret_cast<const T**>(Base::GetRawSlot());
0285   }
0286 
0287   V8_INLINE RawStorage GetRawStorage() const {
0288     return Base::GetRawStorage();
0289   }
0290 
0291  private:
0292   V8_INLINE explicit BasicMember(RawStorage raw) : Base(raw) {
0293     InitializingWriteBarrier(Get());
0294     this->CheckPointer(Get());
0295   }
0296 
0297   V8_INLINE BasicMember& operator=(RawStorage other) {
0298     Base::SetRawStorageAtomic(other);
0299     AssigningWriteBarrier();
0300     this->CheckPointer(Get());
0301     return *this;
0302   }
0303 
0304   V8_INLINE const T* GetRawAtomic() const {
0305     return static_cast<const T*>(Base::GetRawAtomic());
0306   }
0307 
0308   V8_INLINE void InitializingWriteBarrier(T* value) const {
0309     WriteBarrierPolicy::InitializingBarrier(Base::GetRawSlot(), value);
0310   }
0311   V8_INLINE void AssigningWriteBarrier(T* value) const {
0312     WriteBarrierPolicy::template AssigningBarrier<
0313         StorageType::kWriteBarrierSlotType>(Base::GetRawSlot(), value);
0314   }
0315   V8_INLINE void AssigningWriteBarrier() const {
0316     WriteBarrierPolicy::template AssigningBarrier<
0317         StorageType::kWriteBarrierSlotType>(Base::GetRawSlot(),
0318                                             Base::GetRawStorage());
0319   }
0320 
0321   V8_INLINE void ClearFromGC() const { Base::ClearFromGC(); }
0322 
0323   V8_INLINE T* GetFromGC() const { return Get(); }
0324 
0325   friend class cppgc::subtle::HeapConsistency;
0326   friend class cppgc::Visitor;
0327   template <typename U>
0328   friend struct cppgc::TraceTrait;
0329   template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0330             typename CheckingPolicy1, typename StorageType1>
0331   friend class BasicMember;
0332 };
0333 
0334 // Member equality operators.
0335 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0336           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0337           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0338           typename StorageType>
0339 V8_INLINE bool operator==(
0340     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0341                       StorageType>& member1,
0342     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0343                       StorageType>& member2) {
0344   if constexpr (internal::IsDecayedSameV<T1, T2>) {
0345     // Check compressed pointers if types are the same.
0346     return member1.GetRawStorage() == member2.GetRawStorage();
0347   } else {
0348     static_assert(internal::IsStrictlyBaseOfV<T1, T2> ||
0349                   internal::IsStrictlyBaseOfV<T2, T1>);
0350     // Otherwise, check decompressed pointers.
0351     return member1.Get() == member2.Get();
0352   }
0353 }
0354 
0355 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0356           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0357           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0358           typename StorageType>
0359 V8_INLINE bool operator!=(
0360     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0361                       StorageType>& member1,
0362     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0363                       StorageType>& member2) {
0364   return !(member1 == member2);
0365 }
0366 
0367 // Equality with raw pointers.
0368 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0369           typename CheckingPolicy, typename StorageType, typename U>
0370 V8_INLINE bool operator==(
0371     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0372                       StorageType>& member,
0373     U* raw) {
0374   // Never allow comparison with erased pointers.
0375   static_assert(!internal::IsDecayedSameV<void, U>);
0376 
0377   if constexpr (internal::IsDecayedSameV<T, U>) {
0378     // Check compressed pointers if types are the same.
0379     return member.GetRawStorage() == StorageType(raw);
0380   } else if constexpr (internal::IsStrictlyBaseOfV<T, U>) {
0381     // Cast the raw pointer to T, which may adjust the pointer.
0382     return member.GetRawStorage() == StorageType(static_cast<T*>(raw));
0383   } else {
0384     // Otherwise, decompressed the member.
0385     return member.Get() == raw;
0386   }
0387 }
0388 
0389 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0390           typename CheckingPolicy, typename StorageType, typename U>
0391 V8_INLINE bool operator!=(
0392     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0393                       StorageType>& member,
0394     U* raw) {
0395   return !(member == raw);
0396 }
0397 
0398 template <typename T, typename U, typename WeaknessTag,
0399           typename WriteBarrierPolicy, typename CheckingPolicy,
0400           typename StorageType>
0401 V8_INLINE bool operator==(
0402     T* raw, const BasicMember<U, WeaknessTag, WriteBarrierPolicy,
0403                               CheckingPolicy, StorageType>& member) {
0404   return member == raw;
0405 }
0406 
0407 template <typename T, typename U, typename WeaknessTag,
0408           typename WriteBarrierPolicy, typename CheckingPolicy,
0409           typename StorageType>
0410 V8_INLINE bool operator!=(
0411     T* raw, const BasicMember<U, WeaknessTag, WriteBarrierPolicy,
0412                               CheckingPolicy, StorageType>& member) {
0413   return !(raw == member);
0414 }
0415 
0416 // Equality with sentinel.
0417 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0418           typename CheckingPolicy, typename StorageType>
0419 V8_INLINE bool operator==(
0420     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0421                       StorageType>& member,
0422     SentinelPointer) {
0423   return member.GetRawStorage().IsSentinel();
0424 }
0425 
0426 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0427           typename CheckingPolicy, typename StorageType>
0428 V8_INLINE bool operator!=(
0429     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0430                       StorageType>& member,
0431     SentinelPointer s) {
0432   return !(member == s);
0433 }
0434 
0435 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0436           typename CheckingPolicy, typename StorageType>
0437 V8_INLINE bool operator==(
0438     SentinelPointer s, const BasicMember<T, WeaknessTag, WriteBarrierPolicy,
0439                                          CheckingPolicy, StorageType>& member) {
0440   return member == s;
0441 }
0442 
0443 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0444           typename CheckingPolicy, typename StorageType>
0445 V8_INLINE bool operator!=(
0446     SentinelPointer s, const BasicMember<T, WeaknessTag, WriteBarrierPolicy,
0447                                          CheckingPolicy, StorageType>& member) {
0448   return !(s == member);
0449 }
0450 
0451 // Equality with nullptr.
0452 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0453           typename CheckingPolicy, typename StorageType>
0454 V8_INLINE bool operator==(
0455     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0456                       StorageType>& member,
0457     std::nullptr_t) {
0458   return !static_cast<bool>(member);
0459 }
0460 
0461 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0462           typename CheckingPolicy, typename StorageType>
0463 V8_INLINE bool operator!=(
0464     const BasicMember<T, WeaknessTag, WriteBarrierPolicy, CheckingPolicy,
0465                       StorageType>& member,
0466     std::nullptr_t n) {
0467   return !(member == n);
0468 }
0469 
0470 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0471           typename CheckingPolicy, typename StorageType>
0472 V8_INLINE bool operator==(
0473     std::nullptr_t n, const BasicMember<T, WeaknessTag, WriteBarrierPolicy,
0474                                         CheckingPolicy, StorageType>& member) {
0475   return member == n;
0476 }
0477 
0478 template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
0479           typename CheckingPolicy, typename StorageType>
0480 V8_INLINE bool operator!=(
0481     std::nullptr_t n, const BasicMember<T, WeaknessTag, WriteBarrierPolicy,
0482                                         CheckingPolicy, StorageType>& member) {
0483   return !(n == member);
0484 }
0485 
0486 // Relational operators.
0487 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0488           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0489           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0490           typename StorageType>
0491 V8_INLINE bool operator<(
0492     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0493                       StorageType>& member1,
0494     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0495                       StorageType>& member2) {
0496   static_assert(
0497       internal::IsDecayedSameV<T1, T2>,
0498       "Comparison works only for same pointer type modulo cv-qualifiers");
0499   return member1.GetRawStorage() < member2.GetRawStorage();
0500 }
0501 
0502 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0503           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0504           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0505           typename StorageType>
0506 V8_INLINE bool operator<=(
0507     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0508                       StorageType>& member1,
0509     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0510                       StorageType>& member2) {
0511   static_assert(
0512       internal::IsDecayedSameV<T1, T2>,
0513       "Comparison works only for same pointer type modulo cv-qualifiers");
0514   return member1.GetRawStorage() <= member2.GetRawStorage();
0515 }
0516 
0517 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0518           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0519           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0520           typename StorageType>
0521 V8_INLINE bool operator>(
0522     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0523                       StorageType>& member1,
0524     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0525                       StorageType>& member2) {
0526   static_assert(
0527       internal::IsDecayedSameV<T1, T2>,
0528       "Comparison works only for same pointer type modulo cv-qualifiers");
0529   return member1.GetRawStorage() > member2.GetRawStorage();
0530 }
0531 
0532 template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
0533           typename CheckingPolicy1, typename T2, typename WeaknessTag2,
0534           typename WriteBarrierPolicy2, typename CheckingPolicy2,
0535           typename StorageType>
0536 V8_INLINE bool operator>=(
0537     const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1,
0538                       StorageType>& member1,
0539     const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2,
0540                       StorageType>& member2) {
0541   static_assert(
0542       internal::IsDecayedSameV<T1, T2>,
0543       "Comparison works only for same pointer type modulo cv-qualifiers");
0544   return member1.GetRawStorage() >= member2.GetRawStorage();
0545 }
0546 
0547 template <typename T, typename WriteBarrierPolicy, typename CheckingPolicy,
0548           typename StorageType>
0549 struct IsWeak<internal::BasicMember<T, WeakMemberTag, WriteBarrierPolicy,
0550                                     CheckingPolicy, StorageType>>
0551     : std::true_type {};
0552 
0553 }  // namespace internal
0554 
0555 /**
0556  * Members are used in classes to contain strong pointers to other garbage
0557  * collected objects. All Member fields of a class must be traced in the class'
0558  * trace method.
0559  */
0560 template <typename T>
0561 using Member = internal::BasicMember<
0562     T, internal::StrongMemberTag, internal::DijkstraWriteBarrierPolicy,
0563     internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>;
0564 
0565 /**
0566  * WeakMember is similar to Member in that it is used to point to other garbage
0567  * collected objects. However instead of creating a strong pointer to the
0568  * object, the WeakMember creates a weak pointer, which does not keep the
0569  * pointee alive. Hence if all pointers to to a heap allocated object are weak
0570  * the object will be garbage collected. At the time of GC the weak pointers
0571  * will automatically be set to null.
0572  */
0573 template <typename T>
0574 using WeakMember = internal::BasicMember<
0575     T, internal::WeakMemberTag, internal::DijkstraWriteBarrierPolicy,
0576     internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>;
0577 
0578 /**
0579  * UntracedMember is a pointer to an on-heap object that is not traced for some
0580  * reason. Do not use this unless you know what you are doing. Keeping raw
0581  * pointers to on-heap objects is prohibited unless used from stack. Pointee
0582  * must be kept alive through other means.
0583  */
0584 template <typename T>
0585 using UntracedMember = internal::BasicMember<
0586     T, internal::UntracedMemberTag, internal::NoWriteBarrierPolicy,
0587     internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>;
0588 
0589 namespace subtle {
0590 
0591 /**
0592  * UncompressedMember. Use with care in hot paths that would otherwise cause
0593  * many decompression cycles.
0594  */
0595 template <typename T>
0596 using UncompressedMember = internal::BasicMember<
0597     T, internal::StrongMemberTag, internal::DijkstraWriteBarrierPolicy,
0598     internal::DefaultMemberCheckingPolicy, internal::RawPointer>;
0599 
0600 #if defined(CPPGC_POINTER_COMPRESSION)
0601 /**
0602  * CompressedMember. Default implementation of cppgc::Member on builds with
0603  * pointer compression.
0604  */
0605 template <typename T>
0606 using CompressedMember = internal::BasicMember<
0607     T, internal::StrongMemberTag, internal::DijkstraWriteBarrierPolicy,
0608     internal::DefaultMemberCheckingPolicy, internal::CompressedPointer>;
0609 #endif  // defined(CPPGC_POINTER_COMPRESSION)
0610 
0611 }  // namespace subtle
0612 
0613 namespace internal {
0614 
0615 struct Dummy;
0616 
0617 static constexpr size_t kSizeOfMember = sizeof(Member<Dummy>);
0618 static constexpr size_t kSizeOfUncompressedMember =
0619     sizeof(subtle::UncompressedMember<Dummy>);
0620 #if defined(CPPGC_POINTER_COMPRESSION)
0621 static constexpr size_t kSizeofCompressedMember =
0622     sizeof(subtle::CompressedMember<Dummy>);
0623 #endif  // defined(CPPGC_POINTER_COMPRESSION)
0624 
0625 }  // namespace internal
0626 
0627 }  // namespace cppgc
0628 
0629 #endif  // INCLUDE_CPPGC_MEMBER_H_