Commit 8a27d9f9 authored by Zhi An Ng's avatar Zhi An Ng Committed by Commit Bot

Revert "cppgc: Properly clear (Weak)Peristent and WeakMember pointers"

This reverts commit e0c1a349.

Reason for revert: Fails on Linux 64 cfi https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20-%20cfi/25283?

TBR=omerkatz@chromium.org,mlippautz@chromium.org,bikineev@chromium.org,bikineev@chromium.org

Change-Id: I2b208c4019979735925bff5e0551291fae6a14d6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2250320Reviewed-by: 's avatarZhi An Ng <zhin@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68396}
parent cad1845a
...@@ -56,11 +56,6 @@ class PersistentNode final { ...@@ -56,11 +56,6 @@ class PersistentNode final {
bool IsUsed() const { return trace_; } bool IsUsed() const { return trace_; }
void* owner() const {
CPPGC_DCHECK(IsUsed());
return owner_;
}
private: private:
// PersistentNode acts as a designated union: // PersistentNode acts as a designated union:
// If trace_ != nullptr, owner_ points to the corresponding Persistent handle. // If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
...@@ -72,13 +67,11 @@ class PersistentNode final { ...@@ -72,13 +67,11 @@ class PersistentNode final {
TraceCallback trace_ = nullptr; TraceCallback trace_ = nullptr;
}; };
class V8_EXPORT PersistentRegion final { class V8_EXPORT PersistentRegion {
using PersistentNodeSlots = std::array<PersistentNode, 256u>; using PersistentNodeSlots = std::array<PersistentNode, 256u>;
public: public:
PersistentRegion() = default; PersistentRegion() = default;
// Clears Persistent fields to avoid stale pointers after heap teardown.
~PersistentRegion();
PersistentRegion(const PersistentRegion&) = delete; PersistentRegion(const PersistentRegion&) = delete;
PersistentRegion& operator=(const PersistentRegion&) = delete; PersistentRegion& operator=(const PersistentRegion&) = delete;
......
...@@ -49,6 +49,12 @@ class V8_EXPORT LivenessBroker final { ...@@ -49,6 +49,12 @@ class V8_EXPORT LivenessBroker final {
TraceTrait<T>::GetTraceDescriptor(object).base_object_payload); TraceTrait<T>::GetTraceDescriptor(object).base_object_payload);
} }
template <typename T>
bool IsHeapObjectAlive(const WeakMember<T>& weak_member) const {
return (weak_member != kSentinelPointer) &&
IsHeapObjectAlive<T>(weak_member.Get());
}
template <typename T> template <typename T>
bool IsHeapObjectAlive(const UntracedMember<T>& untraced_member) const { bool IsHeapObjectAlive(const UntracedMember<T>& untraced_member) const {
return (untraced_member != kSentinelPointer) && return (untraced_member != kSentinelPointer) &&
......
...@@ -19,43 +19,19 @@ class Visitor; ...@@ -19,43 +19,19 @@ class Visitor;
namespace internal { namespace internal {
class MemberBase {
protected:
MemberBase() = default;
explicit MemberBase(void* value) : raw_(value) {}
void* const* GetRawSlot() const { return &raw_; }
void* GetRaw() const { return raw_; }
void SetRaw(void* value) { raw_ = value; }
void* GetRawAtomic() const {
return reinterpret_cast<const std::atomic<void*>*>(&raw_)->load(
std::memory_order_relaxed);
}
void SetRawAtomic(void* value) {
reinterpret_cast<std::atomic<void*>*>(&raw_)->store(
value, std::memory_order_relaxed);
}
void ClearFromGC() const { raw_ = nullptr; }
private:
mutable void* raw_ = nullptr;
};
// The basic class from which all Member classes are 'generated'. // The basic class from which all Member classes are 'generated'.
template <typename T, typename WeaknessTag, typename WriteBarrierPolicy, template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
typename CheckingPolicy> typename CheckingPolicy>
class BasicMember final : private MemberBase, private CheckingPolicy { class BasicMember : private CheckingPolicy {
public: public:
using PointeeType = T; using PointeeType = T;
constexpr BasicMember() = default; constexpr BasicMember() = default;
constexpr BasicMember(std::nullptr_t) {} // NOLINT constexpr BasicMember(std::nullptr_t) {} // NOLINT
BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT BasicMember(SentinelPointer s) : raw_(s) {} // NOLINT
BasicMember(T* raw) : MemberBase(raw) { // NOLINT BasicMember(T* raw) : raw_(raw) { // NOLINT
InitializingWriteBarrier(); InitializingWriteBarrier();
this->CheckPointer(Get()); this->CheckPointer(raw_);
} }
BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
BasicMember(const BasicMember& other) : BasicMember(other.Get()) {} BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
...@@ -132,7 +108,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy { ...@@ -132,7 +108,7 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
T* Get() const { T* Get() const {
// Executed by the mutator, hence non atomic load. // Executed by the mutator, hence non atomic load.
return static_cast<T*>(MemberBase::GetRaw()); return raw_;
} }
void Clear() { SetRawAtomic(nullptr); } void Clear() { SetRawAtomic(nullptr); }
...@@ -144,18 +120,25 @@ class BasicMember final : private MemberBase, private CheckingPolicy { ...@@ -144,18 +120,25 @@ class BasicMember final : private MemberBase, private CheckingPolicy {
} }
private: private:
void SetRawAtomic(T* raw) {
reinterpret_cast<std::atomic<T*>*>(&raw_)->store(raw,
std::memory_order_relaxed);
}
T* GetRawAtomic() const { T* GetRawAtomic() const {
return static_cast<T*>(MemberBase::GetRawAtomic()); return reinterpret_cast<const std::atomic<T*>*>(&raw_)->load(
std::memory_order_relaxed);
} }
void InitializingWriteBarrier() const { void InitializingWriteBarrier() const {
WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw()); WriteBarrierPolicy::InitializingBarrier(
reinterpret_cast<const void*>(&raw_), static_cast<const void*>(raw_));
} }
void AssigningWriteBarrier() const { void AssigningWriteBarrier() const {
WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw()); WriteBarrierPolicy::AssigningBarrier(reinterpret_cast<const void*>(&raw_),
static_cast<const void*>(raw_));
} }
void ClearFromGC() const { MemberBase::ClearFromGC(); } T* raw_ = nullptr;
friend class cppgc::Visitor; friend class cppgc::Visitor;
}; };
......
...@@ -15,41 +15,12 @@ ...@@ -15,41 +15,12 @@
#include "v8config.h" // NOLINT(build/include_directory) #include "v8config.h" // NOLINT(build/include_directory)
namespace cppgc { namespace cppgc {
class Visitor;
namespace internal { namespace internal {
class PersistentBase {
protected:
PersistentBase() = default;
explicit PersistentBase(void* raw) : raw_(raw) {}
void* GetValue() const { return raw_; }
void SetValue(void* value) { raw_ = value; }
PersistentNode* GetNode() const { return node_; }
void SetNode(PersistentNode* node) { node_ = node; }
// Performs a shallow clear which assumes that internal persistent nodes are
// destroyed elsewhere.
void ClearFromGC() const {
raw_ = nullptr;
node_ = nullptr;
}
private:
mutable void* raw_ = nullptr;
mutable PersistentNode* node_ = nullptr;
friend class PersistentRegion;
};
// The basic class from which all Persistent classes are generated. // The basic class from which all Persistent classes are generated.
template <typename T, typename WeaknessPolicy, typename LocationPolicy, template <typename T, typename WeaknessPolicy, typename LocationPolicy,
typename CheckingPolicy> typename CheckingPolicy>
class BasicPersistent final : public PersistentBase, class BasicPersistent : public LocationPolicy,
public LocationPolicy,
private WeaknessPolicy, private WeaknessPolicy,
private CheckingPolicy { private CheckingPolicy {
public: public:
...@@ -67,15 +38,15 @@ class BasicPersistent final : public PersistentBase, ...@@ -67,15 +38,15 @@ class BasicPersistent final : public PersistentBase,
BasicPersistent( // NOLINT BasicPersistent( // NOLINT
SentinelPointer s, const SourceLocation& loc = SourceLocation::Current()) SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
: PersistentBase(s), LocationPolicy(loc) {} : LocationPolicy(loc), raw_(s) {}
// Raw value constructors. // Raw value contstructors.
BasicPersistent(T* raw, // NOLINT BasicPersistent(T* raw, // NOLINT
const SourceLocation& loc = SourceLocation::Current()) const SourceLocation& loc = SourceLocation::Current())
: PersistentBase(raw), LocationPolicy(loc) { : LocationPolicy(loc), raw_(raw) {
if (!IsValid()) return; if (!IsValid()) return;
SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode(
.AllocateNode(this, &BasicPersistent::Trace)); this, &BasicPersistent::Trace);
this->CheckPointer(Get()); this->CheckPointer(Get());
} }
...@@ -103,11 +74,13 @@ class BasicPersistent final : public PersistentBase, ...@@ -103,11 +74,13 @@ class BasicPersistent final : public PersistentBase,
BasicPersistent( BasicPersistent(
BasicPersistent&& other, BasicPersistent&& other,
const SourceLocation& loc = SourceLocation::Current()) noexcept const SourceLocation& loc = SourceLocation::Current()) noexcept
: PersistentBase(std::move(other)), LocationPolicy(std::move(other)) { : LocationPolicy(std::move(other)),
raw_(std::move(other.raw_)),
node_(std::move(other.node_)) {
if (!IsValid()) return; if (!IsValid()) return;
GetNode()->UpdateOwner(this); node_->UpdateOwner(this);
other.SetValue(nullptr); other.raw_ = nullptr;
other.SetNode(nullptr); other.node_ = nullptr;
this->CheckPointer(Get()); this->CheckPointer(Get());
} }
...@@ -141,12 +114,13 @@ class BasicPersistent final : public PersistentBase, ...@@ -141,12 +114,13 @@ class BasicPersistent final : public PersistentBase,
BasicPersistent& operator=(BasicPersistent&& other) { BasicPersistent& operator=(BasicPersistent&& other) {
if (this == &other) return *this; if (this == &other) return *this;
Clear(); Clear();
PersistentBase::operator=(std::move(other));
LocationPolicy::operator=(std::move(other)); LocationPolicy::operator=(std::move(other));
raw_ = std::move(other.raw_);
node_ = std::move(other.node_);
if (!IsValid()) return *this; if (!IsValid()) return *this;
GetNode()->UpdateOwner(this); node_->UpdateOwner(this);
other.SetValue(nullptr); other.raw_ = nullptr;
other.SetNode(nullptr); other.node_ = nullptr;
this->CheckPointer(Get()); this->CheckPointer(Get());
return *this; return *this;
} }
...@@ -182,7 +156,7 @@ class BasicPersistent final : public PersistentBase, ...@@ -182,7 +156,7 @@ class BasicPersistent final : public PersistentBase,
T* operator->() const { return Get(); } T* operator->() const { return Get(); }
T& operator*() const { return *Get(); } T& operator*() const { return *Get(); }
T* Get() const { return static_cast<T*>(GetValue()); } T* Get() const { return raw_; }
void Clear() { Assign(nullptr); } void Clear() { Assign(nullptr); }
...@@ -202,35 +176,29 @@ class BasicPersistent final : public PersistentBase, ...@@ -202,35 +176,29 @@ class BasicPersistent final : public PersistentBase,
// Ideally, handling kSentinelPointer would be done by the embedder. On the // Ideally, handling kSentinelPointer would be done by the embedder. On the
// other hand, having Persistent aware of it is beneficial since no node // other hand, having Persistent aware of it is beneficial since no node
// gets wasted. // gets wasted.
return GetValue() != nullptr && GetValue() != kSentinelPointer; return raw_ != nullptr && raw_ != kSentinelPointer;
} }
void Assign(T* ptr) { void Assign(T* ptr) {
if (IsValid()) { if (IsValid()) {
if (ptr && ptr != kSentinelPointer) { if (ptr && ptr != kSentinelPointer) {
// Simply assign the pointer reusing the existing node. // Simply assign the pointer reusing the existing node.
SetValue(ptr); raw_ = ptr;
this->CheckPointer(ptr); this->CheckPointer(ptr);
return; return;
} }
WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode()); WeaknessPolicy::GetPersistentRegion(raw_).FreeNode(node_);
SetNode(nullptr); node_ = nullptr;
} }
SetValue(ptr); raw_ = ptr;
if (!IsValid()) return; if (!IsValid()) return;
SetNode(WeaknessPolicy::GetPersistentRegion(GetValue()) node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode(
.AllocateNode(this, &BasicPersistent::Trace)); this, &BasicPersistent::Trace);
this->CheckPointer(Get()); this->CheckPointer(Get());
} }
void ClearFromGC() const { T* raw_ = nullptr;
if (IsValid()) { PersistentNode* node_ = nullptr;
WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
PersistentBase::ClearFromGC();
}
}
friend class cppgc::Visitor;
}; };
template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1, template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
......
...@@ -136,11 +136,12 @@ class Visitor { ...@@ -136,11 +136,12 @@ class Visitor {
template <typename PointerType> template <typename PointerType>
static void HandleWeak(const LivenessBroker& info, const void* object) { static void HandleWeak(const LivenessBroker& info, const void* object) {
const PointerType* weak = static_cast<const PointerType*>(object); const PointerType* weak = static_cast<const PointerType*>(object);
// Sentinel values are preserved for weak pointers.
if (*weak == kSentinelPointer) return;
const auto* raw = weak->Get(); const auto* raw = weak->Get();
if (!info.IsHeapObjectAlive(raw)) { if (raw && !info.IsHeapObjectAlive(raw)) {
weak->ClearFromGC(); // Object is passed down through the marker as const. Alternatives are
// - non-const Trace method;
// - mutable pointer in MemberBase;
const_cast<PointerType*>(weak)->Clear();
} }
} }
......
...@@ -7,21 +7,9 @@ ...@@ -7,21 +7,9 @@
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
#include "include/cppgc/persistent.h"
namespace cppgc { namespace cppgc {
namespace internal { namespace internal {
PersistentRegion::~PersistentRegion() {
for (auto& slots : nodes_) {
for (auto& node : *slots) {
if (node.IsUsed()) {
static_cast<PersistentBase*>(node.owner())->ClearFromGC();
}
}
}
}
size_t PersistentRegion::NodesInUse() const { size_t PersistentRegion::NodesInUse() const {
return std::accumulate( return std::accumulate(
nodes_.cbegin(), nodes_.cend(), 0u, [](size_t acc, const auto& slots) { nodes_.cbegin(), nodes_.cend(), 0u, [](size_t acc, const auto& slots) {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "src/heap/cppgc/marker.h" #include "src/heap/cppgc/marker.h"
#include "include/cppgc/allocation.h" #include "include/cppgc/allocation.h"
#include "include/cppgc/internal/pointer-policies.h"
#include "include/cppgc/member.h" #include "include/cppgc/member.h"
#include "include/cppgc/persistent.h" #include "include/cppgc/persistent.h"
#include "src/heap/cppgc/heap-object-header-inl.h" #include "src/heap/cppgc/heap-object-header-inl.h"
...@@ -246,20 +245,5 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedNonEmptyStack) { ...@@ -246,20 +245,5 @@ TEST_F(MarkerTest, InConstructionObjectIsEventuallyMarkedNonEmptyStack) {
}); });
} }
TEST_F(MarkerTest, SentinelNotClearedOnWeakPersistentHandling) {
Marker marker(Heap::From(GetHeap())->AsBase());
Persistent<GCed> root = MakeGarbageCollected<GCed>(GetAllocationHandle());
auto* tmp = MakeGarbageCollected<GCed>(GetAllocationHandle());
root->SetWeakChild(tmp);
static const Marker::MarkingConfig config = {
MarkingConfig::CollectionType::kMajor,
MarkingConfig::StackState::kNoHeapPointers};
marker.StartMarking(config);
marker.FinishMarking(config);
root->SetWeakChild(kSentinelPointer);
marker.ProcessWeakness();
EXPECT_EQ(kSentinelPointer, root->weak_child());
}
} // namespace internal } // namespace internal
} // namespace cppgc } // namespace cppgc
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "include/cppgc/allocation.h" #include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h" #include "include/cppgc/garbage-collected.h"
#include "include/cppgc/internal/pointer-policies.h"
#include "include/cppgc/member.h" #include "include/cppgc/member.h"
#include "include/cppgc/type-traits.h" #include "include/cppgc/type-traits.h"
#include "src/heap/cppgc/heap.h" #include "src/heap/cppgc/heap.h"
...@@ -71,7 +70,6 @@ class RootVisitor final : public VisitorBase { ...@@ -71,7 +70,6 @@ class RootVisitor final : public VisitorBase {
private: private:
std::vector<std::pair<WeakCallback, const void*>> weak_callbacks_; std::vector<std::pair<WeakCallback, const void*>> weak_callbacks_;
}; };
class PersistentTest : public testing::TestSupportingAllocationOnly {}; class PersistentTest : public testing::TestSupportingAllocationOnly {};
} // namespace } // namespace
...@@ -619,25 +617,6 @@ TEST_F(PersistentTest, TraceWeak) { ...@@ -619,25 +617,6 @@ TEST_F(PersistentTest, TraceWeak) {
EXPECT_EQ(0u, GetRegion<WeakPersistent>(heap).NodesInUse()); EXPECT_EQ(0u, GetRegion<WeakPersistent>(heap).NodesInUse());
} }
TEST_F(PersistentTest, ClearOnHeapDestruction) {
Persistent<GCed> persistent;
WeakPersistent<GCed> weak_persistent;
// Create another heap that can be destroyed during the test.
auto heap = Heap::Create(GetPlatformHandle());
persistent = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
weak_persistent = MakeGarbageCollected<GCed>(heap->GetAllocationHandle());
const Persistent<GCed> persistent_sentinel(kSentinelPointer);
const WeakPersistent<GCed> weak_persistent_sentinel(kSentinelPointer);
heap.reset();
EXPECT_EQ(nullptr, persistent);
EXPECT_EQ(nullptr, weak_persistent);
// Sentinel values survive as they do not represent actual heap objects.
EXPECT_EQ(kSentinelPointer, persistent_sentinel);
EXPECT_EQ(kSentinelPointer, weak_persistent_sentinel);
}
#if CPPGC_SUPPORTS_SOURCE_LOCATION #if CPPGC_SUPPORTS_SOURCE_LOCATION
TEST_F(PersistentTest, LocalizedPersistent) { TEST_F(PersistentTest, LocalizedPersistent) {
GCed* gced = MakeGarbageCollected<GCed>(GetAllocationHandle()); GCed* gced = MakeGarbageCollected<GCed>(GetAllocationHandle());
......
...@@ -22,8 +22,6 @@ class TestWithPlatform : public ::testing::Test { ...@@ -22,8 +22,6 @@ class TestWithPlatform : public ::testing::Test {
TestPlatform& GetPlatform() const { return *platform_; } TestPlatform& GetPlatform() const { return *platform_; }
std::shared_ptr<TestPlatform> GetPlatformHandle() const { return platform_; }
protected: protected:
static std::shared_ptr<TestPlatform> platform_; static std::shared_ptr<TestPlatform> platform_;
}; };
......
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