From 02afcd6b05c1692c5064e43d94464bfac43ecca9 Mon Sep 17 00:00:00 2001 From: Anton Bikineev Date: Thu, 26 Jan 2023 22:48:21 +0100 Subject: [PATCH] cppgc: Introduce subtle::UncompressedMember Some very hot getters in Blink can spend many cycles on decompression. We're planning to optimize such paths by selectively using uncompressed pointers. Change-Id: I78af751c423c56010a794448450032c66f8fa244 Bug: chromium:1410145 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4191778 Commit-Queue: Anton Bikineev Reviewed-by: Michael Lippautz Cr-Commit-Position: refs/heads/main@{#85508} --- include/cppgc/cross-thread-persistent.h | 6 +- include/cppgc/heap-consistency.h | 4 +- include/cppgc/internal/member-storage.h | 4 +- include/cppgc/internal/pointer-policies.h | 5 +- include/cppgc/internal/write-barrier.h | 11 +- include/cppgc/member.h | 294 +++++++++++-------- include/cppgc/persistent.h | 37 ++- include/cppgc/type-traits.h | 7 +- include/cppgc/visitor.h | 14 + src/heap/cppgc/member-storage.cc | 9 +- test/unittests/heap/cppgc/member-unittest.cc | 2 +- tools/gdbinit | 2 +- 12 files changed, 230 insertions(+), 165 deletions(-) diff --git a/include/cppgc/cross-thread-persistent.h b/include/cppgc/cross-thread-persistent.h index 1fa28afa13..a5f8bac0b1 100644 --- a/include/cppgc/cross-thread-persistent.h +++ b/include/cppgc/cross-thread-persistent.h @@ -148,10 +148,11 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase, template ::value>> BasicCrossThreadPersistent( internal::BasicMember + MemberCheckingPolicy, MemberStorageType> member, const SourceLocation& loc = SourceLocation::Current()) : BasicCrossThreadPersistent(member.Get(), loc) {} @@ -230,10 +231,11 @@ class BasicCrossThreadPersistent final : public CrossThreadPersistentBase, // Assignment from member. template ::value>> BasicCrossThreadPersistent& operator=( internal::BasicMember + MemberCheckingPolicy, MemberStorageType> member) { return operator=(member.Get()); } diff --git a/include/cppgc/heap-consistency.h b/include/cppgc/heap-consistency.h index 35c59ed1ad..eb7fdaee8c 100644 --- a/include/cppgc/heap-consistency.h +++ b/include/cppgc/heap-consistency.h @@ -62,10 +62,10 @@ class HeapConsistency final { * \returns whether a write barrier is needed and which barrier to invoke. */ template + typename CheckingPolicy, typename StorageType> static V8_INLINE WriteBarrierType GetWriteBarrierType( const internal::BasicMember& value, + CheckingPolicy, StorageType>& value, WriteBarrierParams& params) { return internal::WriteBarrier::GetWriteBarrierType( value.GetRawSlot(), value.GetRawStorage(), params); diff --git a/include/cppgc/internal/member-storage.h b/include/cppgc/internal/member-storage.h index 0eb6382070..cc803bdcb1 100644 --- a/include/cppgc/internal/member-storage.h +++ b/include/cppgc/internal/member-storage.h @@ -225,9 +225,9 @@ class V8_TRIVIAL_ABI RawPointer final { }; #if defined(CPPGC_POINTER_COMPRESSION) -using MemberStorage = CompressedPointer; +using DefaultMemberStorage = CompressedPointer; #else // !defined(CPPGC_POINTER_COMPRESSION) -using MemberStorage = RawPointer; +using DefaultMemberStorage = RawPointer; #endif // !defined(CPPGC_POINTER_COMPRESSION) } // namespace internal diff --git a/include/cppgc/internal/pointer-policies.h b/include/cppgc/internal/pointer-policies.h index e67da040db..a513968312 100644 --- a/include/cppgc/internal/pointer-policies.h +++ b/include/cppgc/internal/pointer-policies.h @@ -45,6 +45,7 @@ struct DijkstraWriteBarrierPolicy { #endif // !CPPGC_SLIM_WRITE_BARRIER } + template V8_INLINE static void AssigningBarrier(const void* slot, MemberStorage storage) { #ifdef CPPGC_SLIM_WRITE_BARRIER @@ -79,6 +80,7 @@ struct DijkstraWriteBarrierPolicy { struct NoWriteBarrierPolicy { V8_INLINE static void InitializingBarrier(const void*, const void*) {} V8_INLINE static void AssigningBarrier(const void*, const void*) {} + template V8_INLINE static void AssigningBarrier(const void*, MemberStorage) {} }; @@ -207,7 +209,8 @@ template class BasicPersistent; template + typename CheckingPolicy = DefaultMemberCheckingPolicy, + typename StorageType = DefaultMemberStorage> class BasicMember; } // namespace internal diff --git a/include/cppgc/internal/write-barrier.h b/include/cppgc/internal/write-barrier.h index 80c6ee33b2..ec941b171a 100644 --- a/include/cppgc/internal/write-barrier.h +++ b/include/cppgc/internal/write-barrier.h @@ -70,6 +70,7 @@ class V8_EXPORT WriteBarrier final { static V8_INLINE Type GetWriteBarrierType(const void* slot, const void* value, Params& params); // Returns the required write barrier for a given `slot` and `value`. + template static V8_INLINE Type GetWriteBarrierType(const void* slot, MemberStorage, Params& params); // Returns the required write barrier for a given `slot`. @@ -171,7 +172,8 @@ class V8_EXPORT WriteBarrierTypeForCagedHeapPolicy final { return ValueModeDispatch::Get(slot, value, params, callback); } - template + template static V8_INLINE WriteBarrier::Type Get(const void* slot, MemberStorage value, WriteBarrier::Params& params, HeapHandleCallback callback) { @@ -215,7 +217,7 @@ class V8_EXPORT WriteBarrierTypeForCagedHeapPolicy final { template <> struct WriteBarrierTypeForCagedHeapPolicy::ValueModeDispatch< WriteBarrier::ValueMode::kValuePresent> { - template + template static V8_INLINE WriteBarrier::Type Get(const void* slot, MemberStorage storage, WriteBarrier::Params& params, @@ -313,11 +315,9 @@ class V8_EXPORT WriteBarrierTypeForNonCagedHeapPolicy final { } template - static V8_INLINE WriteBarrier::Type Get(const void* slot, MemberStorage value, + static V8_INLINE WriteBarrier::Type Get(const void* slot, RawPointer value, WriteBarrier::Params& params, HeapHandleCallback callback) { - // `MemberStorage` will always be `RawPointer` for non-caged heap builds. - // Just convert to `void*` in this case. return ValueModeDispatch::Get(slot, value.Load(), params, callback); } @@ -391,6 +391,7 @@ WriteBarrier::Type WriteBarrier::GetWriteBarrierType( } // static +template WriteBarrier::Type WriteBarrier::GetWriteBarrierType( const void* slot, MemberStorage value, WriteBarrier::Params& params) { return WriteBarrierTypePolicy::Get(slot, value, diff --git a/include/cppgc/member.h b/include/cppgc/member.h index 9bc383634f..13d92b055d 100644 --- a/include/cppgc/member.h +++ b/include/cppgc/member.h @@ -28,13 +28,11 @@ namespace internal { // MemberBase always refers to the object as const object and defers to // BasicMember on casting to the right type as needed. +template class V8_TRIVIAL_ABI MemberBase { public: -#if defined(CPPGC_POINTER_COMPRESSION) - using RawStorage = CompressedPointer; -#else // !defined(CPPGC_POINTER_COMPRESSION) - using RawStorage = RawPointer; -#endif // !defined(CPPGC_POINTER_COMPRESSION) + using RawStorage = StorageType; + protected: struct AtomicInitializerTag {}; @@ -75,16 +73,19 @@ class V8_TRIVIAL_ABI MemberBase { // The basic class from which all Member classes are 'generated'. template -class V8_TRIVIAL_ABI BasicMember final : private MemberBase, + typename CheckingPolicy, typename StorageType> +class V8_TRIVIAL_ABI BasicMember final : private MemberBase, private CheckingPolicy { + using Base = MemberBase; + public: using PointeeType = T; + using RawStorage = typename Base::RawStorage; V8_INLINE constexpr BasicMember() = default; - V8_INLINE constexpr BasicMember(std::nullptr_t) {} // NOLINT - V8_INLINE BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT - V8_INLINE BasicMember(T* raw) : MemberBase(raw) { // NOLINT + V8_INLINE constexpr BasicMember(std::nullptr_t) {} // NOLINT + V8_INLINE BasicMember(SentinelPointer s) : Base(s) {} // NOLINT + V8_INLINE BasicMember(T* raw) : Base(raw) { // NOLINT InitializingWriteBarrier(raw); this->CheckPointer(Get()); } @@ -94,13 +95,13 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, // Atomic ctor. Using the AtomicInitializerTag forces BasicMember to // initialize using atomic assignments. This is required for preventing // data races with concurrent marking. - using AtomicInitializerTag = MemberBase::AtomicInitializerTag; + using AtomicInitializerTag = typename Base::AtomicInitializerTag; V8_INLINE BasicMember(std::nullptr_t, AtomicInitializerTag atomic) - : MemberBase(nullptr, atomic) {} + : Base(nullptr, atomic) {} V8_INLINE BasicMember(SentinelPointer s, AtomicInitializerTag atomic) - : MemberBase(s, atomic) {} + : Base(s, atomic) {} V8_INLINE BasicMember(T* raw, AtomicInitializerTag atomic) - : MemberBase(raw, atomic) { + : Base(raw, atomic) { InitializingWriteBarrier(raw); this->CheckPointer(Get()); } @@ -119,7 +120,7 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, std::enable_if_t>* = nullptr> V8_INLINE BasicMember( // NOLINT const BasicMember& other) + OtherCheckingPolicy, StorageType>& other) : BasicMember(other.GetRawStorage()) {} template >* = nullptr> V8_INLINE BasicMember( // NOLINT const BasicMember& other) + OtherCheckingPolicy, StorageType>& other) : BasicMember(other.Get()) {} // Move ctor. @@ -142,8 +143,9 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, template >* = nullptr> - V8_INLINE BasicMember(BasicMember&& other) noexcept + V8_INLINE BasicMember( + BasicMember&& other) noexcept : BasicMember(other.GetRawStorage()) { other.Clear(); } @@ -151,8 +153,9 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, template >* = nullptr> - V8_INLINE BasicMember(BasicMember&& other) noexcept + V8_INLINE BasicMember( + BasicMember&& other) noexcept : BasicMember(other.Get()) { other.Clear(); } @@ -179,7 +182,7 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, typename OtherCheckingPolicy> V8_INLINE BasicMember& operator=( const BasicMember& other) { + OtherCheckingPolicy, StorageType>& other) { if constexpr (internal::IsDecayedSameV) { return operator=(other.GetRawStorage()); } else { @@ -201,8 +204,8 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, template V8_INLINE BasicMember& operator=( - BasicMember&& other) noexcept { + BasicMember&& other) noexcept { if constexpr (internal::IsDecayedSameV) { operator=(other.GetRawStorage()); } else { @@ -226,7 +229,7 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, } V8_INLINE BasicMember& operator=(T* other) { - SetRawAtomic(other); + Base::SetRawAtomic(other); AssigningWriteBarrier(other); this->CheckPointer(Get()); return *this; @@ -237,20 +240,20 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, return *this; } V8_INLINE BasicMember& operator=(SentinelPointer s) { - SetRawAtomic(s); + Base::SetRawAtomic(s); return *this; } template V8_INLINE void Swap(BasicMember& other) { + OtherCheckingPolicy, StorageType>& other) { auto tmp = GetRawStorage(); *this = other; other = tmp; } - V8_INLINE explicit operator bool() const { return !IsCleared(); } + V8_INLINE explicit operator bool() const { return !Base::IsCleared(); } V8_INLINE operator T*() const { return Get(); } V8_INLINE T* operator->() const { return Get(); } V8_INLINE T& operator*() const { return *Get(); } @@ -264,10 +267,12 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, // The const_cast below removes the constness from MemberBase storage. The // following static_cast re-adds any constness if specified through the // user-visible template parameter T. - return static_cast(const_cast(MemberBase::GetRaw())); + return static_cast(const_cast(Base::GetRaw())); } - V8_INLINE void Clear() { SetRawStorageAtomic(RawStorage{}); } + V8_INLINE void Clear() { + Base::SetRawStorageAtomic(RawStorage{}); + } V8_INLINE T* Release() { T* result = Get(); @@ -276,41 +281,42 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, } V8_INLINE const T** GetSlotForTesting() const { - return reinterpret_cast(GetRawSlot()); + return reinterpret_cast(Base::GetRawSlot()); } V8_INLINE RawStorage GetRawStorage() const { - return MemberBase::GetRawStorage(); + return Base::GetRawStorage(); } private: - V8_INLINE explicit BasicMember(RawStorage raw) : MemberBase(raw) { + V8_INLINE explicit BasicMember(RawStorage raw) : Base(raw) { InitializingWriteBarrier(Get()); this->CheckPointer(Get()); } V8_INLINE BasicMember& operator=(RawStorage other) { - SetRawStorageAtomic(other); + Base::SetRawStorageAtomic(other); AssigningWriteBarrier(); this->CheckPointer(Get()); return *this; } V8_INLINE const T* GetRawAtomic() const { - return static_cast(MemberBase::GetRawAtomic()); + return static_cast(Base::GetRawAtomic()); } V8_INLINE void InitializingWriteBarrier(T* value) const { - WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), value); + WriteBarrierPolicy::InitializingBarrier(Base::GetRawSlot(), value); } V8_INLINE void AssigningWriteBarrier(T* value) const { - WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), value); + WriteBarrierPolicy::AssigningBarrier(Base::GetRawSlot(), value); } V8_INLINE void AssigningWriteBarrier() const { - WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRawStorage()); + WriteBarrierPolicy::AssigningBarrier(Base::GetRawSlot(), + Base::GetRawStorage()); } - V8_INLINE void ClearFromGC() const { MemberBase::ClearFromGC(); } + V8_INLINE void ClearFromGC() const { Base::ClearFromGC(); } V8_INLINE T* GetFromGC() const { return Get(); } @@ -319,19 +325,20 @@ class V8_TRIVIAL_ABI BasicMember final : private MemberBase, template friend struct cppgc::TraceTrait; template + typename CheckingPolicy1, typename StorageType1> friend class BasicMember; }; // Member equality operators. template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator==( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { if constexpr (internal::IsDecayedSameV) { // Check compressed pointers if types are the same. return member1.GetRawStorage() == member2.GetRawStorage(); @@ -345,31 +352,32 @@ V8_INLINE bool operator==( template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator!=( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { return !(member1 == member2); } // Equality with raw pointers. template -V8_INLINE bool operator==(const BasicMember& member, - U* raw) { + typename CheckingPolicy, typename StorageType, typename U> +V8_INLINE bool operator==( + const BasicMember& member, + U* raw) { // Never allow comparison with erased pointers. static_assert(!internal::IsDecayedSameV); if constexpr (internal::IsDecayedSameV) { // Check compressed pointers if types are the same. - return member.GetRawStorage() == MemberBase::RawStorage(raw); + return member.GetRawStorage() == StorageType(raw); } else if constexpr (internal::IsStrictlyBaseOfV) { // Cast the raw pointer to T, which may adjust the pointer. - return member.GetRawStorage() == - MemberBase::RawStorage(static_cast(raw)); + return member.GetRawStorage() == StorageType(static_cast(raw)); } else { // Otherwise, decompressed the member. return member.Get() == raw; @@ -377,104 +385,112 @@ V8_INLINE bool operator==(const BasicMember -V8_INLINE bool operator!=(const BasicMember& member, - U* raw) { + typename CheckingPolicy, typename StorageType, typename U> +V8_INLINE bool operator!=( + const BasicMember& member, + U* raw) { return !(member == raw); } template -V8_INLINE bool operator==(T* raw, - const BasicMember& member) { + typename WriteBarrierPolicy, typename CheckingPolicy, + typename StorageType> +V8_INLINE bool operator==( + T* raw, const BasicMember& member) { return member == raw; } template -V8_INLINE bool operator!=(T* raw, - const BasicMember& member) { + typename WriteBarrierPolicy, typename CheckingPolicy, + typename StorageType> +V8_INLINE bool operator!=( + T* raw, const BasicMember& member) { return !(raw == member); } // Equality with sentinel. template -V8_INLINE bool operator==(const BasicMember& member, - SentinelPointer) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator==( + const BasicMember& member, + SentinelPointer) { return member.GetRawStorage().IsSentinel(); } template -V8_INLINE bool operator!=(const BasicMember& member, - SentinelPointer s) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator!=( + const BasicMember& member, + SentinelPointer s) { return !(member == s); } template -V8_INLINE bool operator==(SentinelPointer s, - const BasicMember& member) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator==( + SentinelPointer s, const BasicMember& member) { return member == s; } template -V8_INLINE bool operator!=(SentinelPointer s, - const BasicMember& member) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator!=( + SentinelPointer s, const BasicMember& member) { return !(s == member); } // Equality with nullptr. template -V8_INLINE bool operator==(const BasicMember& member, - std::nullptr_t) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator==( + const BasicMember& member, + std::nullptr_t) { return !static_cast(member); } template -V8_INLINE bool operator!=(const BasicMember& member, - std::nullptr_t n) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator!=( + const BasicMember& member, + std::nullptr_t n) { return !(member == n); } template -V8_INLINE bool operator==(std::nullptr_t n, - const BasicMember& member) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator==( + std::nullptr_t n, const BasicMember& member) { return member == n; } template -V8_INLINE bool operator!=(std::nullptr_t n, - const BasicMember& member) { + typename CheckingPolicy, typename StorageType> +V8_INLINE bool operator!=( + std::nullptr_t n, const BasicMember& member) { return !(n == member); } // Relational operators. template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator<( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { static_assert( internal::IsDecayedSameV, "Comparison works only for same pointer type modulo cv-qualifiers"); @@ -483,12 +499,13 @@ V8_INLINE bool operator<( template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator<=( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { static_assert( internal::IsDecayedSameV, "Comparison works only for same pointer type modulo cv-qualifiers"); @@ -497,12 +514,13 @@ V8_INLINE bool operator<=( template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator>( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { static_assert( internal::IsDecayedSameV, "Comparison works only for same pointer type modulo cv-qualifiers"); @@ -511,21 +529,23 @@ V8_INLINE bool operator>( template + typename WriteBarrierPolicy2, typename CheckingPolicy2, + typename StorageType> V8_INLINE bool operator>=( - const BasicMember& - member1, - const BasicMember& - member2) { + const BasicMember& member1, + const BasicMember& member2) { static_assert( internal::IsDecayedSameV, "Comparison works only for same pointer type modulo cv-qualifiers"); return member1.GetRawStorage() >= member2.GetRawStorage(); } -template -struct IsWeak< - internal::BasicMember> +template +struct IsWeak> : std::true_type {}; } // namespace internal @@ -536,8 +556,9 @@ struct IsWeak< * trace method. */ template -using Member = internal::BasicMember; +using Member = internal::BasicMember< + T, internal::StrongMemberTag, internal::DijkstraWriteBarrierPolicy, + internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>; /** * WeakMember is similar to Member in that it is used to point to other garbage @@ -548,8 +569,9 @@ using Member = internal::BasicMember -using WeakMember = internal::BasicMember; +using WeakMember = internal::BasicMember< + T, internal::WeakMemberTag, internal::DijkstraWriteBarrierPolicy, + internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>; /** * UntracedMember is a pointer to an on-heap object that is not traced for some @@ -558,8 +580,22 @@ using WeakMember = internal::BasicMember -using UntracedMember = internal::BasicMember; +using UntracedMember = internal::BasicMember< + T, internal::UntracedMemberTag, internal::NoWriteBarrierPolicy, + internal::DefaultMemberCheckingPolicy, internal::DefaultMemberStorage>; + +namespace subtle { + +/** + * UncompressedMember. Use with care in hot paths that would otherwise cause + * many decompression cycles. + */ +template +using UncompressedMember = internal::BasicMember< + T, internal::StrongMemberTag, internal::DijkstraWriteBarrierPolicy, + internal::DefaultMemberCheckingPolicy, internal::RawPointer>; + +} // namespace subtle } // namespace cppgc diff --git a/include/cppgc/persistent.h b/include/cppgc/persistent.h index 3a66ccc086..709f3fd6ab 100644 --- a/include/cppgc/persistent.h +++ b/include/cppgc/persistent.h @@ -114,11 +114,12 @@ class BasicPersistent final : public PersistentBase, // Constructor from member. template ::value>> - BasicPersistent( - const internal::BasicMember& member, - const SourceLocation& loc = SourceLocation::Current()) + BasicPersistent(const internal::BasicMember< + U, MemberBarrierPolicy, MemberWeaknessTag, + MemberCheckingPolicy, MemberStorageType>& member, + const SourceLocation& loc = SourceLocation::Current()) : BasicPersistent(member.Get(), loc) {} ~BasicPersistent() { Clear(); } @@ -154,10 +155,12 @@ class BasicPersistent final : public PersistentBase, // Assignment from member. template ::value>> BasicPersistent& operator=( const internal::BasicMember& member) { + MemberCheckingPolicy, MemberStorageType>& + member) { return operator=(member.Get()); } @@ -286,36 +289,39 @@ bool operator!=(const BasicPersistent + typename MemberWeaknessTag, typename MemberCheckingPolicy, + typename MemberStorageType> bool operator==( const BasicPersistent& p, const BasicMember& m) { + MemberCheckingPolicy, MemberStorageType>& m) { return p.Get() == m.Get(); } template + typename MemberWeaknessTag, typename MemberCheckingPolicy, + typename MemberStorageType> bool operator!=( const BasicPersistent& p, const BasicMember& m) { + MemberCheckingPolicy, MemberStorageType>& m) { return !(p == m); } template + typename MemberStorageType, typename T2, + typename PersistentWeaknessPolicy, typename PersistentLocationPolicy, + typename PersistentCheckingPolicy> bool operator==( const BasicMember& m, + MemberCheckingPolicy, MemberStorageType>& m, const BasicPersistent& p) { @@ -324,11 +330,12 @@ bool operator==( template + typename MemberStorageType, typename T2, + typename PersistentWeaknessPolicy, typename PersistentLocationPolicy, + typename PersistentCheckingPolicy> bool operator!=( const BasicMember& m, + MemberCheckingPolicy, MemberStorageType>& m, const BasicPersistent& p) { diff --git a/include/cppgc/type-traits.h b/include/cppgc/type-traits.h index 2f499e6886..4651435390 100644 --- a/include/cppgc/type-traits.h +++ b/include/cppgc/type-traits.h @@ -16,7 +16,7 @@ class Visitor; namespace internal { template + typename CheckingPolicy, typename StorageType> class BasicMember; struct DijkstraWriteBarrierPolicy; struct NoWriteBarrierPolicy; @@ -126,9 +126,10 @@ template struct IsSubclassOfBasicMemberTemplate { private: - template + template static std::true_type SubclassCheck( - BasicMember*); + BasicMember*); static std::false_type SubclassCheck(...); public: diff --git a/include/cppgc/visitor.h b/include/cppgc/visitor.h index 704aabcdb0..9b135e39a0 100644 --- a/include/cppgc/visitor.h +++ b/include/cppgc/visitor.h @@ -99,6 +99,20 @@ class V8_EXPORT Visitor { &HandleWeak>, &weak_member); } +#if defined(CPPGC_POINTER_COMPRESSION) + /** + * Trace method for UncompressedMember. + * + * \param member UncompressedMember reference retaining an object. + */ + template + void Trace(const subtle::UncompressedMember& member) { + const T* value = member.GetRawAtomic(); + CPPGC_DCHECK(value != kSentinelPointer); + TraceImpl(value); + } +#endif // defined(CPPGC_POINTER_COMPRESSION) + /** * Trace method for inlined objects that are not allocated themselves but * otherwise follow managed heap layout and have a Trace() method. diff --git a/src/heap/cppgc/member-storage.cc b/src/heap/cppgc/member-storage.cc index c457c60ba4..c79ab42e91 100644 --- a/src/heap/cppgc/member-storage.cc +++ b/src/heap/cppgc/member-storage.cc @@ -21,20 +21,21 @@ uintptr_t CageBaseGlobal::g_base_ = CageBaseGlobal::kLowerHalfWordMask; #if defined(CPPGC_POINTER_COMPRESSION) extern "C" V8_DONT_STRIP_SYMBOL V8_EXPORT_PRIVATE void* _cppgc_internal_Decompress_Compressed_Pointer(uint32_t cmprsd) { - return MemberStorage::Decompress(cmprsd); + return CompressedPointer::Decompress(cmprsd); } #endif // !defined(CPPGC_POINTER_COMPRESSION) class MemberDebugHelper final { public: - static void* PrintUncompressed(MemberBase* m) { + static void* Uncompress(MemberBase* m) { return const_cast(m->GetRaw()); } }; extern "C" V8_DONT_STRIP_SYMBOL V8_EXPORT_PRIVATE void* -_cppgc_internal_Print_Member(MemberBase* m) { - return MemberDebugHelper::PrintUncompressed(m); +_cppgc_internal_Uncompress_Member(void* m) { + return MemberDebugHelper::Uncompress( + static_cast*>(m)); } } // namespace internal diff --git a/test/unittests/heap/cppgc/member-unittest.cc b/test/unittests/heap/cppgc/member-unittest.cc index b6dd973c49..78c0bffc8d 100644 --- a/test/unittests/heap/cppgc/member-unittest.cc +++ b/test/unittests/heap/cppgc/member-unittest.cc @@ -68,7 +68,7 @@ struct CustomWriteBarrierPolicy { static void AssigningBarrier(const void* slot, const void* value) { ++AssigningWriteBarriersTriggered; } - static void AssigningBarrier(const void* slot, MemberStorage) { + static void AssigningBarrier(const void* slot, DefaultMemberStorage) { ++AssigningWriteBarriersTriggered; } }; diff --git a/tools/gdbinit b/tools/gdbinit index 3f012be4c3..745e24dcbd 100644 --- a/tools/gdbinit +++ b/tools/gdbinit @@ -297,7 +297,7 @@ class CppGCMemberPrinter(object): def to_string(self): pointer = gdb.parse_and_eval( - "_cppgc_internal_Print_Member((cppgc::internal::MemberBase*){})".format( + "_cppgc_internal_Uncompress_Member((void*){})".format( self.val.address)) return "{}Member<{}> pointing to {}".format( '' if self.category is None else self.category, self.pointee_type,