cppgc: Avoid compression/decompression in Member operators/ctors

1) In copy/move ctors and operator=() we can just copy raw compressed
   value;
2) For null check we don't need to decompress the value;
3) Same for operator==().
4) Hashing can also be optimized in a followup.

Bug: chromium:1325007
Change-Id: Ic1bf2c5049802c078b3e0121dcbe62d9ecea83b3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3647359
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80571}
This commit is contained in:
Anton Bikineev 2022-05-16 16:09:33 +02:00 committed by V8 LUCI CQ
parent 93446e3c12
commit 5c416ad2c3

View File

@ -62,6 +62,9 @@ class CompressedPointer final {
V8_INLINE CompressedPointer() : value_(0u) {}
V8_INLINE explicit CompressedPointer(const void* ptr)
: value_(Compress(ptr)) {}
V8_INLINE explicit CompressedPointer(std::nullptr_t) : value_(0u) {}
V8_INLINE explicit CompressedPointer(SentinelPointer)
: value_(kCompressedSentinel) {}
V8_INLINE const void* Load() const { return Decompress(value_); }
V8_INLINE const void* LoadAtomic() const {
@ -69,14 +72,19 @@ class CompressedPointer final {
reinterpret_cast<const std::atomic<Storage>&>(value_).load(
std::memory_order_relaxed));
}
V8_INLINE Storage LoadRaw() const { return value_; }
V8_INLINE void Store(const void* ptr) { value_ = Compress(ptr); }
V8_INLINE void StoreAtomic(const void* value) {
reinterpret_cast<std::atomic<Storage>&>(value_).store(
Compress(value), std::memory_order_relaxed);
}
V8_INLINE void StoreRaw(Storage value) { value_ = value; }
V8_INLINE void Clear() { value_ = 0u; }
V8_INLINE bool IsCleared() const { return !value_; }
V8_INLINE friend bool operator==(CompressedPointer a, CompressedPointer b) {
return a.value_ == b.value_;
}
static V8_INLINE Storage Compress(const void* ptr) {
static_assert(
@ -112,6 +120,8 @@ class CompressedPointer final {
}
private:
static constexpr Storage kCompressedSentinel =
SentinelPointer::kSentinelValue >> 1;
// All constructors initialize `value_`. Do not add a default value here as it
// results in a non-atomic write on some builds, even when the atomic version
// of the constructor is used.
@ -124,45 +134,55 @@ class RawPointer final {
public:
using Storage = uintptr_t;
RawPointer() : value_(0u) {}
explicit RawPointer(const void* ptr)
: value_(reinterpret_cast<uintptr_t>(ptr)) {}
RawPointer() : ptr_(nullptr) {}
explicit RawPointer(const void* ptr) : ptr_(ptr) {}
V8_INLINE const void* Load() const {
return reinterpret_cast<const void*>(value_);
}
V8_INLINE const void* Load() const { return ptr_; }
V8_INLINE const void* LoadAtomic() const {
return reinterpret_cast<const std::atomic<const void*>&>(value_).load(
return reinterpret_cast<const std::atomic<const void*>&>(ptr_).load(
std::memory_order_relaxed);
}
V8_INLINE Storage LoadRaw() const { return value_; }
V8_INLINE void Store(const void* ptr) {
value_ = reinterpret_cast<uintptr_t>(ptr);
}
V8_INLINE void Store(const void* ptr) { ptr_ = ptr; }
V8_INLINE void StoreAtomic(const void* ptr) {
reinterpret_cast<std::atomic<uintptr_t>&>(value_).store(
reinterpret_cast<uintptr_t>(ptr), std::memory_order_relaxed);
reinterpret_cast<std::atomic<const void*>&>(ptr_).store(
ptr, std::memory_order_relaxed);
}
V8_INLINE void Clear() { ptr_ = nullptr; }
V8_INLINE bool IsCleared() const { return !ptr_; }
V8_INLINE friend bool operator==(RawPointer a, RawPointer b) {
return a.ptr_ == b.ptr_;
}
V8_INLINE void StoreRaw(Storage value) { value_ = value; }
private:
// All constructors initialize `ptr_`. Do not add a default value here as it
// results in a non-atomic write on some builds, even when the atomic version
// of the constructor is used.
uintptr_t value_;
const void* ptr_;
};
// MemberBase always refers to the object as const object and defers to
// BasicMember on casting to the right type as needed.
class MemberBase {
protected:
#if defined(CPPGC_POINTER_COMPRESSION)
using RawStorage = CompressedPointer;
#else // !defined(CPPGC_POINTER_COMPRESSION)
using RawStorage = RawPointer;
#endif // !defined(CPPGC_POINTER_COMPRESSION)
struct AtomicInitializerTag {};
MemberBase() = default;
explicit MemberBase(const void* value) : raw_(value) {}
MemberBase(const void* value, AtomicInitializerTag) { SetRawAtomic(value); }
explicit MemberBase(RawStorage raw) : raw_(raw) {}
explicit MemberBase(std::nullptr_t) : raw_(nullptr) {}
explicit MemberBase(SentinelPointer s) : raw_(s) {}
const void** GetRawSlot() const {
return reinterpret_cast<const void**>(const_cast<MemberBase*>(this));
}
@ -172,16 +192,18 @@ class MemberBase {
const void* GetRawAtomic() const { return raw_.LoadAtomic(); }
void SetRawAtomic(const void* value) { raw_.StoreAtomic(value); }
void ClearFromGC() const { raw_.StoreRaw(0u); }
RawStorage GetRawStorage() const { return raw_; }
void SetRawStorageAtomic(RawStorage other) {
reinterpret_cast<std::atomic<RawStorage>&>(raw_).store(
other, std::memory_order_relaxed);
}
bool IsCleared() const { return raw_.IsCleared(); }
void ClearFromGC() const { raw_.Clear(); }
private:
#if defined(CPPGC_POINTER_COMPRESSION)
using Storage = CompressedPointer;
#else // !defined(CPPGC_POINTER_COMPRESSION)
using Storage = RawPointer;
#endif // !defined(CPPGC_POINTER_COMPRESSION)
mutable Storage raw_;
mutable RawStorage raw_;
};
// The basic class from which all Member classes are 'generated'.
@ -214,7 +236,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
BasicMember(T& raw, AtomicInitializerTag atomic)
: BasicMember(&raw, atomic) {}
// Copy ctor.
BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
BasicMember(const BasicMember& other) : BasicMember(other.GetRawStorage()) {}
// Allow heterogeneous construction.
template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
typename OtherCheckingPolicy,
@ -222,9 +244,10 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
BasicMember( // NOLINT
const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>& other)
: BasicMember(other.Get()) {}
: BasicMember(other.GetRawStorage()) {}
// Move ctor.
BasicMember(BasicMember&& other) noexcept : BasicMember(other.Get()) {
BasicMember(BasicMember&& other) noexcept
: BasicMember(other.GetRawStorage()) {
other.Clear();
}
// Allow heterogeneous move construction.
@ -233,7 +256,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
BasicMember(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>&& other) noexcept
: BasicMember(other.Get()) {
: BasicMember(other.GetRawStorage()) {
other.Clear();
}
// Construction from Persistent.
@ -248,7 +271,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
// Copy assignment.
BasicMember& operator=(const BasicMember& other) {
return operator=(other.Get());
return operator=(other.GetRawStorage());
}
// Allow heterogeneous copy assignment.
template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
@ -257,11 +280,11 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
BasicMember& operator=(
const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>& other) {
return operator=(other.Get());
return operator=(other.GetRawStorage());
}
// Move assignment.
BasicMember& operator=(BasicMember&& other) noexcept {
operator=(other.Get());
operator=(other.GetRawStorage());
other.Clear();
return *this;
}
@ -271,7 +294,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
BasicMember& operator=(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>&& other) noexcept {
operator=(other.Get());
operator=(other.GetRawStorage());
other.Clear();
return *this;
}
@ -305,12 +328,12 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
typename OtherCheckingPolicy>
void Swap(BasicMember<T, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>& other) {
T* tmp = Get();
auto tmp = GetRawStorage();
*this = other;
other = tmp;
}
explicit operator bool() const { return Get(); }
explicit operator bool() const { return !IsCleared(); }
operator T*() const { return Get(); }
T* operator->() const { return Get(); }
T& operator*() const { return *Get(); }
@ -327,7 +350,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
return static_cast<T*>(const_cast<void*>(MemberBase::GetRaw()));
}
void Clear() { SetRawAtomic(nullptr); }
void Clear() { SetRawStorageAtomic(RawStorage{}); }
T* Release() {
T* result = Get();
@ -340,6 +363,18 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
}
private:
explicit BasicMember(RawStorage raw) : MemberBase(raw) {
InitializingWriteBarrier();
this->CheckPointer(Get());
}
BasicMember& operator=(RawStorage other) {
SetRawStorageAtomic(other);
AssigningWriteBarrier();
this->CheckPointer(Get());
return *this;
}
const T* GetRawAtomic() const {
return static_cast<const T*>(MemberBase::GetRawAtomic());
}
@ -358,6 +393,17 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
friend class cppgc::Visitor;
template <typename U>
friend struct cppgc::TraceTrait;
template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
typename CheckingPolicy1>
friend class BasicMember;
template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
typename CheckingPolicy1, typename T2, typename WeaknessTag2,
typename WriteBarrierPolicy2, typename CheckingPolicy2>
friend bool operator==(
const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1, CheckingPolicy1>&
member1,
const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2, CheckingPolicy2>&
member2);
};
template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,
@ -367,7 +413,7 @@ bool operator==(const BasicMember<T1, WeaknessTag1, WriteBarrierPolicy1,
CheckingPolicy1>& member1,
const BasicMember<T2, WeaknessTag2, WriteBarrierPolicy2,
CheckingPolicy2>& member2) {
return member1.Get() == member2.Get();
return member1.GetRawStorage() == member2.GetRawStorage();
}
template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,