#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MEMBER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MEMBER_H_
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/thread_state_storage.h"
#include "third_party/blink/renderer/platform/heap/write_barrier.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
#include "v8/include/cppgc/member.h"
#include "v8/include/cppgc/tagged-member.h"
namespace blink {
template <typename T>
using Member = cppgc::Member<T>;
template <typename T>
using WeakMember = cppgc::WeakMember<T>;
template <typename T>
using UntracedMember = cppgc::UntracedMember<T>;
namespace subtle {
template <typename T>
using UncompressedMember = cppgc::subtle::UncompressedMember<T>;
template <typename T, typename Tag1, typename Tag2>
using TaggedUncompressedMember =
cppgc::subtle::TaggedUncompressedMember<T, Tag1, Tag2>;
}
template <typename T>
inline bool IsHashTableDeletedValue(const Member<T>& m) {
return m == cppgc::kSentinelPointer;
}
constexpr auto kMemberDeletedValue = cppgc::kSentinelPointer;
template <typename T>
struct ThreadingTrait<blink::Member<T>> {
STATIC_ONLY(ThreadingTrait);
static constexpr ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
template <typename T>
struct ThreadingTrait<blink::WeakMember<T>> {
STATIC_ONLY(ThreadingTrait);
static constexpr ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
template <typename T>
struct ThreadingTrait<blink::UntracedMember<T>> {
STATIC_ONLY(ThreadingTrait);
static constexpr ThreadAffinity kAffinity = ThreadingTrait<T>::kAffinity;
};
template <typename T>
inline void swap(Member<T>& a, Member<T>& b) {
a.Swap(b);
}
static constexpr bool kBlinkMemberGCHasDebugChecks =
!std::is_same<cppgc::internal::DefaultMemberCheckingPolicy,
cppgc::internal::DisabledCheckingPolicy>::value;
static_assert(kBlinkMemberGCHasDebugChecks ||
sizeof(Member<void*>) <= sizeof(void*),
"Member<> should stay small!");
template <typename T>
struct IsTraceable<Member<T>> {
STATIC_ONLY(IsTraceable);
static const bool value = true;
};
template <typename T>
struct IsWeak<WeakMember<T>> : std::true_type {};
template <typename T>
struct IsTraceable<WeakMember<T>> {
STATIC_ONLY(IsTraceable);
static const bool value = true;
};
template <typename T>
class ValuePeeker final {
STACK_ALLOCATED();
public:
ALWAYS_INLINE ValuePeeker(T* ptr) : ptr_(ptr) {}
template <typename U>
ALWAYS_INLINE ValuePeeker(const Member<U>& m) : ptr_(m.Get()) {}
template <typename U>
ALWAYS_INLINE ValuePeeker(const WeakMember<U>& m) : ptr_(m.Get()) {}
template <typename U>
ALWAYS_INLINE ValuePeeker(const UntracedMember<U>& m) : ptr_(m.Get()) {}
template <typename U>
ALWAYS_INLINE ValuePeeker(const Persistent<U>& p) : ptr_(p.Get()) {}
template <typename U>
ALWAYS_INLINE ValuePeeker(const WeakPersistent<U>& p) : ptr_(p.Get()) {}
ALWAYS_INLINE operator T*() const { return ptr_; }
ALWAYS_INLINE operator Member<T>() const { return ptr_; }
ALWAYS_INLINE operator WeakMember<T>() const { return ptr_; }
ALWAYS_INLINE operator UntracedMember<T>() const { return ptr_; }
private:
T* ptr_;
};
template <typename T, typename MemberType>
struct BaseMemberHashTraits : SimpleClassHashTraits<MemberType> {
STATIC_ONLY(BaseMemberHashTraits);
static unsigned GetHash(const T* key) {
#if defined(CPPGC_POINTER_COMPRESSION)
cppgc::internal::CompressedPointer st(key);
#else
cppgc::internal::RawPointer st(key);
#endif
return blink::GetHash(st.GetAsInteger());
}
template <typename Member>
requires(IsAnyMemberType<Member>::value)
static unsigned GetHash(const Member& m) {
return blink::GetHash(m.GetRawStorage().GetAsInteger());
}
static constexpr bool kEmptyValueIsZero = true;
using PeekInType = ValuePeeker<T>;
using PeekOutType = T*;
using IteratorGetType = MemberType*;
using IteratorConstGetType = const MemberType*;
using IteratorReferenceType = MemberType&;
using IteratorConstReferenceType = const MemberType&;
static PeekOutType Peek(const MemberType& value) { return value.Get(); }
static void ConstructDeletedValue(MemberType& slot) {
slot = cppgc::kSentinelPointer;
}
static bool IsDeletedValue(const MemberType& value) {
return value == cppgc::kSentinelPointer;
}
};
template <typename T>
struct MemberHashTraits : BaseMemberHashTraits<T, blink::Member<T>> {
static constexpr bool kCanTraceConcurrently = true;
static constexpr bool kSupportsCompaction = true;
};
template <typename T>
struct HashTraits<blink::Member<T>> : MemberHashTraits<T> {};
template <typename T>
struct WeakMemberHashTraits : BaseMemberHashTraits<T, blink::WeakMember<T>> {
static constexpr bool kCanTraceConcurrently = true;
static constexpr bool kSupportsCompaction = true;
};
template <typename T>
struct HashTraits<blink::WeakMember<T>> : WeakMemberHashTraits<T> {};
template <typename T>
struct UntracedMemberHashTraits
: BaseMemberHashTraits<T, blink::UntracedMember<T>> {};
template <typename T>
struct HashTraits<blink::UntracedMember<T>> : UntracedMemberHashTraits<T> {};
template <typename T>
class MemberConstructTraits {
STATIC_ONLY(MemberConstructTraits);
public:
template <typename... Args>
static T* Construct(void* location, Args&&... args) {
return new (base::NotNullTag::kNotNull, location)
T(std::forward<Args>(args)...);
}
template <typename... Args>
static T* ConstructAndNotifyElement(void* location, Args&&... args) {
T* object = new (base::NotNullTag::kNotNull, location)
T(std::forward<Args>(args)..., typename T::AtomicInitializerTag());
NotifyNewElement(object);
return object;
}
static void NotifyNewElement(T* element) {
WriteBarrier::DispatchForObject(element);
}
static void NotifyNewElements(base::span<T> members) {
if (members.empty() ||
!WriteBarrier::IsWriteBarrierNeeded(&members.front())) [[likely]] {
return;
}
for (auto& member : members) {
WriteBarrier::DispatchForObject(&member);
}
}
};
template <typename T, typename Traits, typename Allocator>
class ConstructTraits<Member<T>, Traits, Allocator> final
: public MemberConstructTraits<Member<T>> {};
template <typename T, typename Traits, typename Allocator>
class ConstructTraits<WeakMember<T>, Traits, Allocator> final
: public MemberConstructTraits<WeakMember<T>> {};
}
#endif