Commit 61521ebd authored by Michael Lippautz's avatar Michael Lippautz Committed by V8 LUCI CQ

cppgc: Heap termination loop must consider CrossThreadPersistent

HeapBase::Terminate must consider newly created CrossThreadPersistent
when evaluating whether to conitnue the loop. This allows for catching
one off creations in destructors but will still crash for
>kMaxTerminationGCs chains.

Bug: chromium:1245519
Change-Id: I264f1b8f0de9f0bfeb66ca6b14c41faf15e4340c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3140606
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76659}
parent ee3016b7
...@@ -121,6 +121,7 @@ void HeapBase::Terminate() { ...@@ -121,6 +121,7 @@ void HeapBase::Terminate() {
constexpr size_t kMaxTerminationGCs = 20; constexpr size_t kMaxTerminationGCs = 20;
size_t gc_count = 0; size_t gc_count = 0;
bool more_termination_gcs_needed = false;
do { do {
CHECK_LT(gc_count++, kMaxTerminationGCs); CHECK_LT(gc_count++, kMaxTerminationGCs);
...@@ -143,7 +144,14 @@ void HeapBase::Terminate() { ...@@ -143,7 +144,14 @@ void HeapBase::Terminate() {
{Sweeper::SweepingConfig::SweepingType::kAtomic, {Sweeper::SweepingConfig::SweepingType::kAtomic,
Sweeper::SweepingConfig::CompactableSpaceHandling::kSweep}); Sweeper::SweepingConfig::CompactableSpaceHandling::kSweep});
sweeper().NotifyDoneIfNeeded(); sweeper().NotifyDoneIfNeeded();
} while (strong_persistent_region_.NodesInUse() > 0); more_termination_gcs_needed =
strong_persistent_region_.NodesInUse() ||
weak_persistent_region_.NodesInUse() || [this]() {
PersistentRegionLock guard;
return strong_cross_thread_persistent_region_.NodesInUse() ||
weak_cross_thread_persistent_region_.NodesInUse();
}();
} while (more_termination_gcs_needed);
object_allocator().Terminate(); object_allocator().Terminate();
disallow_gc_scope_++; disallow_gc_scope_++;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <numeric> #include <numeric>
#include "include/cppgc/allocation.h" #include "include/cppgc/allocation.h"
#include "include/cppgc/cross-thread-persistent.h"
#include "include/cppgc/heap-consistency.h" #include "include/cppgc/heap-consistency.h"
#include "include/cppgc/persistent.h" #include "include/cppgc/persistent.h"
#include "include/cppgc/prefinalizer.h" #include "include/cppgc/prefinalizer.h"
...@@ -311,7 +312,8 @@ TEST_F(GCHeapTest, TerminateInvokesDestructor) { ...@@ -311,7 +312,8 @@ TEST_F(GCHeapTest, TerminateInvokesDestructor) {
namespace { namespace {
class Cloner final : public GarbageCollected<Cloner> { template <template <typename> class PersistentType>
class Cloner final : public GarbageCollected<Cloner<PersistentType>> {
public: public:
static size_t destructor_count; static size_t destructor_count;
...@@ -330,25 +332,41 @@ class Cloner final : public GarbageCollected<Cloner> { ...@@ -330,25 +332,41 @@ class Cloner final : public GarbageCollected<Cloner> {
void Trace(Visitor*) const {} void Trace(Visitor*) const {}
private: private:
static Persistent<Cloner> new_instance_; static PersistentType<Cloner> new_instance_;
cppgc::AllocationHandle& handle_; cppgc::AllocationHandle& handle_;
size_t count_; size_t count_;
}; };
Persistent<Cloner> Cloner::new_instance_; // static
size_t Cloner::destructor_count; template <template <typename> class PersistentType>
PersistentType<Cloner<PersistentType>> Cloner<PersistentType>::new_instance_;
// static
template <template <typename> class PersistentType>
size_t Cloner<PersistentType>::destructor_count;
} // namespace } // namespace
TEST_F(GCHeapTest, TerminateReclaimsNewState) { template <template <typename> class PersistentType>
Persistent<Cloner> cloner = MakeGarbageCollected<Cloner>( void TerminateReclaimsNewState(std::shared_ptr<Platform> platform) {
GetAllocationHandle(), GetAllocationHandle(), 1); auto heap = cppgc::Heap::Create(platform);
Cloner::destructor_count = 0; using ClonerImpl = Cloner<PersistentType>;
Persistent<ClonerImpl> cloner = MakeGarbageCollected<ClonerImpl>(
heap->GetAllocationHandle(), heap->GetAllocationHandle(), 1);
ClonerImpl::destructor_count = 0;
EXPECT_TRUE(cloner.Get()); EXPECT_TRUE(cloner.Get());
Heap::From(GetHeap())->Terminate(); Heap::From(heap.get())->Terminate();
EXPECT_FALSE(cloner.Get()); EXPECT_FALSE(cloner.Get());
EXPECT_EQ(2u, Cloner::destructor_count); EXPECT_EQ(2u, ClonerImpl::destructor_count);
}
TEST_F(GCHeapTest, TerminateReclaimsNewState) {
TerminateReclaimsNewState<Persistent>(GetPlatformHandle());
TerminateReclaimsNewState<WeakPersistent>(GetPlatformHandle());
TerminateReclaimsNewState<cppgc::subtle::CrossThreadPersistent>(
GetPlatformHandle());
TerminateReclaimsNewState<cppgc::subtle::WeakCrossThreadPersistent>(
GetPlatformHandle());
} }
TEST_F(GCHeapDeathTest, TerminateProhibitsAllocation) { TEST_F(GCHeapDeathTest, TerminateProhibitsAllocation) {
...@@ -357,14 +375,24 @@ TEST_F(GCHeapDeathTest, TerminateProhibitsAllocation) { ...@@ -357,14 +375,24 @@ TEST_F(GCHeapDeathTest, TerminateProhibitsAllocation) {
""); "");
} }
TEST_F(GCHeapDeathTest, LargeChainOfNewStates) { template <template <typename> class PersistentType>
Persistent<Cloner> cloner = MakeGarbageCollected<Cloner>( void LargeChainOfNewStates(cppgc::Heap& heap) {
GetAllocationHandle(), GetAllocationHandle(), 1000); using ClonerImpl = Cloner<PersistentType>;
Cloner::destructor_count = 0; Persistent<ClonerImpl> cloner = MakeGarbageCollected<ClonerImpl>(
heap.GetAllocationHandle(), heap.GetAllocationHandle(), 1000);
ClonerImpl::destructor_count = 0;
EXPECT_TRUE(cloner.Get()); EXPECT_TRUE(cloner.Get());
// Terminate() requires destructors to stop creating new state within a few // Terminate() requires destructors to stop creating new state within a few
// garbage collections. // garbage collections.
EXPECT_DEATH_IF_SUPPORTED(Heap::From(GetHeap())->Terminate(), ""); EXPECT_DEATH_IF_SUPPORTED(Heap::From(&heap)->Terminate(), "");
}
TEST_F(GCHeapDeathTest, LargeChainOfNewStatesPersistent) {
LargeChainOfNewStates<Persistent>(*GetHeap());
}
TEST_F(GCHeapDeathTest, LargeChainOfNewStatesCrossThreadPersistent) {
LargeChainOfNewStates<subtle::CrossThreadPersistent>(*GetHeap());
} }
} // namespace internal } // namespace internal
......
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