cppgc: Add TraceTrait<Member<T>>

Embedders forward the Value in TraceEphemeron as Member reference (as
depicted in the API docs). Add TraceTrait<Member<T>> that forwards to
TraceTrait<T> accordingly, supporting the intended use case.

Bug: chromium:1056170
Change-Id: I3b247cb3553ae34d9ff5393aefeaec24068e78c2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2656255
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72412}
This commit is contained in:
Michael Lippautz 2021-01-28 20:50:36 +01:00 committed by Commit Bot
parent 6f973ba8de
commit 677a9ad9cd
3 changed files with 52 additions and 6 deletions

View File

@ -203,6 +203,8 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
void ClearFromGC() const { MemberBase::ClearFromGC(); }
friend class cppgc::Visitor;
template <typename U>
friend struct cppgc::TraceTrait;
};
template <typename T1, typename WeaknessTag1, typename WriteBarrierPolicy1,

View File

@ -151,7 +151,7 @@ class V8_EXPORT Visitor {
*/
template <typename K, typename V>
void Trace(const EphemeronPair<K, V>& ephemeron_pair) {
TraceEphemeron(ephemeron_pair.key, ephemeron_pair.value.GetRawAtomic());
TraceEphemeron(ephemeron_pair.key, &ephemeron_pair.value);
}
/**
@ -164,6 +164,7 @@ class V8_EXPORT Visitor {
template <typename K, typename V>
void TraceEphemeron(const WeakMember<K>& key, const V* value) {
TraceDescriptor value_desc = TraceTrait<V>::GetTraceDescriptor(value);
if (!value_desc.base_object_payload) return;
VisitEphemeron(key, value_desc);
}
@ -317,6 +318,14 @@ class V8_EXPORT Visitor {
friend class internal::VisitorBase;
};
template <typename T>
struct TraceTrait<Member<T>> {
static TraceDescriptor GetTraceDescriptor(const void* self) {
return TraceTrait<T>::GetTraceDescriptor(
static_cast<const Member<T>*>(self)->GetRawAtomic());
}
};
} // namespace cppgc
#endif // INCLUDE_CPPGC_VISITOR_H_

View File

@ -30,7 +30,20 @@ class EphemeronHolder : public GarbageCollected<GCed> {
EphemeronPair<GCed, GCed> ephemeron_pair_;
};
class EhpemeronPairTest : public testing::TestWithHeap {
class EphemeronHolderTraceEphemeron
: public GarbageCollected<EphemeronHolderTraceEphemeron> {
public:
EphemeronHolderTraceEphemeron(GCed* key, GCed* value)
: ephemeron_pair_(key, value) {}
void Trace(cppgc::Visitor* visitor) const {
visitor->TraceEphemeron(ephemeron_pair_.key, &ephemeron_pair_.value);
}
private:
EphemeronPair<GCed, GCed> ephemeron_pair_;
};
class EphemeronPairTest : public testing::TestWithHeap {
using MarkingConfig = Marker::MarkingConfig;
static constexpr Marker::MarkingConfig IncrementalPreciseMarkingConfig = {
@ -69,11 +82,11 @@ class EhpemeronPairTest : public testing::TestWithHeap {
// static
constexpr Marker::MarkingConfig
EhpemeronPairTest::IncrementalPreciseMarkingConfig;
EphemeronPairTest::IncrementalPreciseMarkingConfig;
} // namespace
TEST_F(EhpemeronPairTest, ValueMarkedWhenKeyIsMarked) {
TEST_F(EphemeronPairTest, ValueMarkedWhenKeyIsMarked) {
GCed* key = MakeGarbageCollected<GCed>(GetAllocationHandle());
GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
Persistent<EphemeronHolder> holder =
@ -84,7 +97,7 @@ TEST_F(EhpemeronPairTest, ValueMarkedWhenKeyIsMarked) {
EXPECT_TRUE(HeapObjectHeader::FromPayload(value).IsMarked());
}
TEST_F(EhpemeronPairTest, ValueNotMarkedWhenKeyIsNotMarked) {
TEST_F(EphemeronPairTest, ValueNotMarkedWhenKeyIsNotMarked) {
GCed* key = MakeGarbageCollected<GCed>(GetAllocationHandle());
GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
Persistent<EphemeronHolder> holder =
@ -95,7 +108,7 @@ TEST_F(EhpemeronPairTest, ValueNotMarkedWhenKeyIsNotMarked) {
EXPECT_FALSE(HeapObjectHeader::FromPayload(value).IsMarked());
}
TEST_F(EhpemeronPairTest, ValueNotMarkedBeforeKey) {
TEST_F(EphemeronPairTest, ValueNotMarkedBeforeKey) {
GCed* key = MakeGarbageCollected<GCed>(GetAllocationHandle());
GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
Persistent<EphemeronHolder> holder =
@ -108,5 +121,27 @@ TEST_F(EhpemeronPairTest, ValueNotMarkedBeforeKey) {
EXPECT_TRUE(HeapObjectHeader::FromPayload(value).IsMarked());
}
TEST_F(EphemeronPairTest, TraceEphemeronDispatch) {
GCed* key = MakeGarbageCollected<GCed>(GetAllocationHandle());
GCed* value = MakeGarbageCollected<GCed>(GetAllocationHandle());
Persistent<EphemeronHolderTraceEphemeron> holder =
MakeGarbageCollected<EphemeronHolderTraceEphemeron>(GetAllocationHandle(),
key, value);
HeapObjectHeader::FromPayload(key).TryMarkAtomic();
InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get());
FinishMarking();
EXPECT_TRUE(HeapObjectHeader::FromPayload(value).IsMarked());
}
TEST_F(EphemeronPairTest, EmptyValue) {
GCed* key = MakeGarbageCollected<GCed>(GetAllocationHandle());
Persistent<EphemeronHolderTraceEphemeron> holder =
MakeGarbageCollected<EphemeronHolderTraceEphemeron>(GetAllocationHandle(),
key, nullptr);
HeapObjectHeader::FromPayload(key).TryMarkAtomic();
InitializeMarker(*Heap::From(GetHeap()), GetPlatformHandle().get());
FinishMarking();
}
} // namespace internal
} // namespace cppgc