Commit 39c43692 authored by Omer Katz's avatar Omer Katz Committed by V8 LUCI CQ

cppgc: Add AtomicCtorTag to Member types

AtomicCtorTag is needed by Blink to force atomic initialization of
members. This is used when reinitializing a member in a backing store.

Bug: chromium:1056170
Change-Id: I410766a9c9133a1f1c2ea2e1153cb1c61363459f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2859944
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74341}
parent dc354358
......@@ -24,8 +24,11 @@ namespace internal {
// BasicMember on casting to the right type as needed.
class MemberBase {
protected:
struct AtomicInitializerTag {};
MemberBase() = default;
explicit MemberBase(const void* value) : raw_(value) {}
MemberBase(const void* value, AtomicInitializerTag) { SetRawAtomic(value); }
const void** GetRawSlot() const { return &raw_; }
const void* GetRaw() const { return raw_; }
......@@ -61,6 +64,20 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
this->CheckPointer(Get());
}
BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
// 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;
BasicMember(std::nullptr_t, AtomicInitializerTag atomic)
: MemberBase(nullptr, atomic) {}
BasicMember(SentinelPointer s, AtomicInitializerTag atomic)
: MemberBase(s, atomic) {}
BasicMember(T* raw, AtomicInitializerTag atomic) : MemberBase(raw, atomic) {
InitializingWriteBarrier();
this->CheckPointer(Get());
}
BasicMember(T& raw, AtomicInitializerTag atomic)
: BasicMember(&raw, atomic) {}
// Copy ctor.
BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
// Allow heterogeneous construction.
......
......@@ -10,6 +10,7 @@
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/persistent.h"
#include "include/cppgc/sentinel-pointer.h"
#include "include/cppgc/type-traits.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -112,6 +113,40 @@ TEST_F(MemberTest, Empty) {
EmptyTest<UntracedMember>();
}
template <template <typename> class MemberType>
void AtomicCtorTest(cppgc::Heap* heap) {
{
GCed* gced = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
MemberType<GCed> member(gced,
typename MemberType<GCed>::AtomicInitializerTag());
EXPECT_EQ(gced, member.Get());
}
{
GCed gced;
MemberType<GCed> member(gced,
typename MemberType<GCed>::AtomicInitializerTag());
EXPECT_EQ(&gced, member.Get());
}
{
MemberType<GCed> member(nullptr,
typename MemberType<GCed>::AtomicInitializerTag());
EXPECT_FALSE(member.Get());
}
{
SentinelPointer s;
MemberType<GCed> member(s,
typename MemberType<GCed>::AtomicInitializerTag());
EXPECT_EQ(s, member.Get());
}
}
TEST_F(MemberTest, AtomicCtor) {
cppgc::Heap* heap = GetHeap();
AtomicCtorTest<Member>(heap);
AtomicCtorTest<WeakMember>(heap);
AtomicCtorTest<UntracedMember>(heap);
}
template <template <typename> class MemberType>
void ClearTest(cppgc::Heap* heap) {
MemberType<GCed> member =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment