Commit 8ba4bcea authored by Omer Katz's avatar Omer Katz Committed by Commit Bot

cppgc: Fix crash when finalizing incremental GC.

The gc_in_progress flag was reset to false only after sweeping was done.
As a result, if we call CollectGarbage during an incremental GC and
after marking has finished, the we will observe that a gc is still in
progress but will not have a marker and crash.

The immediate solution is to move resetting the gc_in_progress flag such
that it indicates whether we didn't have the atomic pause yet. That
means we could have gc_in_progress==false and incremental sweeping still
running, which semantically negates the meaning of gc_in_progress.

Observing that gc_in_progress essentially becomes equivalent to having a
marker, this CL removes the gc_in_progress flag and replaces checks on
it with checks on marker.

Bug: chromium:1156170
Change-Id: Ic4b441ec248b5f7e222e988870e46d5166dd4dcc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2584875
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Auto-Submit: Omer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71712}
parent fcfd4b11
...@@ -105,6 +105,8 @@ Heap::~Heap() { ...@@ -105,6 +105,8 @@ Heap::~Heap() {
sweeper_.FinishIfRunning(); sweeper_.FinishIfRunning();
} }
bool Heap::IsMarking() const { return marker_.get(); }
void Heap::CollectGarbage(Config config) { void Heap::CollectGarbage(Config config) {
DCHECK_EQ(Config::MarkingType::kAtomic, config.marking_type); DCHECK_EQ(Config::MarkingType::kAtomic, config.marking_type);
CheckConfig(config, marking_support_, sweeping_support_); CheckConfig(config, marking_support_, sweeping_support_);
...@@ -113,9 +115,9 @@ void Heap::CollectGarbage(Config config) { ...@@ -113,9 +115,9 @@ void Heap::CollectGarbage(Config config) {
config_ = config; config_ = config;
if (!gc_in_progress_) StartGarbageCollection(config); if (!IsMarking()) StartGarbageCollection(config);
DCHECK(marker_); DCHECK(IsMarking());
FinalizeGarbageCollection(config.stack_state); FinalizeGarbageCollection(config.stack_state);
} }
...@@ -125,7 +127,7 @@ void Heap::StartIncrementalGarbageCollection(Config config) { ...@@ -125,7 +127,7 @@ void Heap::StartIncrementalGarbageCollection(Config config) {
DCHECK_NE(marking_support_, MarkingType::kAtomic); DCHECK_NE(marking_support_, MarkingType::kAtomic);
CheckConfig(config, marking_support_, sweeping_support_); CheckConfig(config, marking_support_, sweeping_support_);
if (gc_in_progress_ || in_no_gc_scope()) return; if (IsMarking() || in_no_gc_scope()) return;
config_ = config; config_ = config;
...@@ -136,7 +138,7 @@ void Heap::FinalizeIncrementalGarbageCollectionIfRunning(Config config) { ...@@ -136,7 +138,7 @@ void Heap::FinalizeIncrementalGarbageCollectionIfRunning(Config config) {
DCHECK_NE(marking_support_, MarkingType::kAtomic); DCHECK_NE(marking_support_, MarkingType::kAtomic);
CheckConfig(config, marking_support_, sweeping_support_); CheckConfig(config, marking_support_, sweeping_support_);
if (!gc_in_progress_) return; if (!IsMarking()) return;
DCHECK(!in_no_gc_scope()); DCHECK(!in_no_gc_scope());
...@@ -146,14 +148,13 @@ void Heap::FinalizeIncrementalGarbageCollectionIfRunning(Config config) { ...@@ -146,14 +148,13 @@ void Heap::FinalizeIncrementalGarbageCollectionIfRunning(Config config) {
} }
void Heap::StartGarbageCollection(Config config) { void Heap::StartGarbageCollection(Config config) {
DCHECK(!gc_in_progress_); DCHECK(!IsMarking());
DCHECK(!in_no_gc_scope()); DCHECK(!in_no_gc_scope());
// Finish sweeping in case it is still running. // Finish sweeping in case it is still running.
sweeper_.FinishIfRunning(); sweeper_.FinishIfRunning();
gc_in_progress_ = true;
epoch_++; epoch_++;
#if defined(CPPGC_YOUNG_GENERATION) #if defined(CPPGC_YOUNG_GENERATION)
...@@ -169,10 +170,9 @@ void Heap::StartGarbageCollection(Config config) { ...@@ -169,10 +170,9 @@ void Heap::StartGarbageCollection(Config config) {
} }
void Heap::FinalizeGarbageCollection(Config::StackState stack_state) { void Heap::FinalizeGarbageCollection(Config::StackState stack_state) {
DCHECK(gc_in_progress_); DCHECK(IsMarking());
DCHECK(!in_no_gc_scope()); DCHECK(!in_no_gc_scope());
config_.stack_state = stack_state; config_.stack_state = stack_state;
DCHECK(marker_);
{ {
// This guards atomic pause marking, meaning that no internal method or // This guards atomic pause marking, meaning that no internal method or
// external callbacks are allowed to allocate new objects. // external callbacks are allowed to allocate new objects.
...@@ -199,7 +199,7 @@ void Heap::FinalizeGarbageCollection(Config::StackState stack_state) { ...@@ -199,7 +199,7 @@ void Heap::FinalizeGarbageCollection(Config::StackState stack_state) {
sweeper_.NotifyDoneIfNeeded(); sweeper_.NotifyDoneIfNeeded();
} }
void Heap::PostGarbageCollection() { gc_in_progress_ = false; } void Heap::PostGarbageCollection() {}
void Heap::DisableHeapGrowingForTesting() { growing_.DisableForTesting(); } void Heap::DisableHeapGrowingForTesting() { growing_.DisableForTesting(); }
......
...@@ -48,6 +48,8 @@ class V8_EXPORT_PRIVATE Heap final : public HeapBase, ...@@ -48,6 +48,8 @@ class V8_EXPORT_PRIVATE Heap final : public HeapBase,
void PostGarbageCollection() final; void PostGarbageCollection() final;
bool IsMarking() const;
Config config_; Config config_;
GCInvoker gc_invoker_; GCInvoker gc_invoker_;
HeapGrowing growing_; HeapGrowing growing_;
...@@ -55,7 +57,6 @@ class V8_EXPORT_PRIVATE Heap final : public HeapBase, ...@@ -55,7 +57,6 @@ class V8_EXPORT_PRIVATE Heap final : public HeapBase,
const MarkingType marking_support_; const MarkingType marking_support_;
const SweepingType sweeping_support_; const SweepingType sweeping_support_;
bool gc_in_progress_ = false;
size_t epoch_ = 0; size_t epoch_ = 0;
}; };
......
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