cppgc: Nullify source Members on move

Explicit nullification aims to simplify migration to Oilpan, in the
case when unique_ptrs are converted to Member and user code relies on
source pointers to be in "empty" state.

Change-Id: Ia54137d53ca03f93932b3c1f2eaba439a416a06e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2379857
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Auto-Submit: Anton Bikineev <bikineev@chromium.org>
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69603}
This commit is contained in:
Anton Bikineev 2020-08-27 19:01:25 +02:00 committed by Commit Bot
parent f13c55d7b2
commit c316d0ede4
2 changed files with 68 additions and 1 deletions

View File

@ -58,6 +58,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
this->CheckPointer(Get());
}
BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
// Copy ctor.
BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
// Allow heterogeneous construction.
template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
@ -67,6 +68,20 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
const BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>& other)
: BasicMember(other.Get()) {}
// Move ctor.
BasicMember(BasicMember&& other) noexcept : BasicMember(other.Get()) {
other.Clear();
}
// Allow heterogeneous move construction.
template <typename U, typename OtherBarrierPolicy, typename OtherWeaknessTag,
typename OtherCheckingPolicy,
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
BasicMember( // NOLINT
BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>&& other) noexcept
: BasicMember(other.Get()) {
other.Clear();
}
// Construction from Persistent.
template <typename U, typename PersistentWeaknessPolicy,
typename PersistentLocationPolicy,
@ -78,10 +93,11 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
p)
: BasicMember(p.Get()) {}
// Copy assignment.
BasicMember& operator=(const BasicMember& other) {
return operator=(other.Get());
}
// Allow heterogeneous assignment.
// Allow heterogeneous copy assignment.
template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
typename OtherCheckingPolicy,
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
@ -90,6 +106,22 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
OtherCheckingPolicy>& other) {
return operator=(other.Get());
}
// Move assignment.
BasicMember& operator=(BasicMember&& other) noexcept {
operator=(other.Get());
other.Clear();
return *this;
}
// Heterogeneous move assignment.
template <typename U, typename OtherWeaknessTag, typename OtherBarrierPolicy,
typename OtherCheckingPolicy,
typename = std::enable_if_t<std::is_base_of<T, U>::value>>
BasicMember& operator=(BasicMember<U, OtherWeaknessTag, OtherBarrierPolicy,
OtherCheckingPolicy>&& other) noexcept {
operator=(other.Get());
other.Clear();
return *this;
}
// Assignment from Persistent.
template <typename U, typename PersistentWeaknessPolicy,
typename PersistentLocationPolicy,

View File

@ -145,6 +145,41 @@ TEST_F(MemberTest, Swap) {
SwapTest<UntracedMember, UntracedMember>(heap);
}
template <template <typename> class MemberType1,
template <typename> class MemberType2>
void MoveTest(cppgc::Heap* heap) {
{
GCed* gced1 = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
MemberType1<GCed> member1 = gced1;
MemberType2<GCed> member2(std::move(member1));
// Move-from member must be in empty state.
EXPECT_FALSE(member1);
EXPECT_EQ(gced1, member2.Get());
}
{
GCed* gced1 = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
MemberType1<GCed> member1 = gced1;
MemberType2<GCed> member2;
member2 = std::move(member1);
// Move-from member must be in empty state.
EXPECT_FALSE(member1);
EXPECT_EQ(gced1, member2.Get());
}
}
TEST_F(MemberTest, Move) {
cppgc::Heap* heap = GetHeap();
MoveTest<Member, Member>(heap);
MoveTest<Member, WeakMember>(heap);
MoveTest<Member, UntracedMember>(heap);
MoveTest<WeakMember, Member>(heap);
MoveTest<WeakMember, WeakMember>(heap);
MoveTest<WeakMember, UntracedMember>(heap);
MoveTest<UntracedMember, Member>(heap);
MoveTest<UntracedMember, WeakMember>(heap);
MoveTest<UntracedMember, UntracedMember>(heap);
}
template <template <typename> class MemberType1,
template <typename> class MemberType2>
void HeterogeneousConversionTest(cppgc::Heap* heap) {