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:
parent
f13c55d7b2
commit
c316d0ede4
@ -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,
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user