[vm, gc] Interrupt to finalize concurrent marking.

STW marking is no longer O(new-space), so there's no longer a reason to delay finalizing marking hoping for a scavenge to make new-space mostly empty.

TEST=ci
Change-Id: Ie782e88852714d30e0c75aa9aecac62e56c434ce
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319880
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2023-12-14 17:27:49 +00:00 committed by Commit Queue
parent da0b9aa8b3
commit 2d01bf3779
7 changed files with 27 additions and 0 deletions

View file

@ -613,6 +613,20 @@ void Heap::CheckConcurrentMarking(Thread* thread,
}
}
void Heap::CheckFinalizeMarking(Thread* thread) {
ASSERT(!thread->force_growth());
PageSpace::Phase phase;
{
MonitorLocker ml(old_space_.tasks_lock());
phase = old_space_.phase();
}
if (phase == PageSpace::kAwaitingFinalization) {
CollectOldSpaceGarbage(thread, GCType::kMarkSweep, GCReason::kFinalize);
}
}
void Heap::StartConcurrentMarking(Thread* thread, GCReason reason) {
GcSafepointOperationScope safepoint_operation(thread);
RecordBeforeGC(GCType::kStartConcurrentMark, reason);

View file

@ -115,6 +115,7 @@ class Heap {
void CheckCatchUp(Thread* thread);
void CheckConcurrentMarking(Thread* thread, GCReason reason, intptr_t size);
void CheckFinalizeMarking(Thread* thread);
void StartConcurrentMarking(Thread* thread, GCReason reason);
void WaitForMarkerTasks(Thread* thread);
void WaitForSweeperTasks(Thread* thread);

View file

@ -920,6 +920,7 @@ class ConcurrentMarkTask : public ThreadPool::Task {
ASSERT(page_space_->phase() == PageSpace::kMarking);
if (page_space_->concurrent_marker_tasks() == 0) {
page_space_->set_phase(PageSpace::kAwaitingFinalization);
isolate_group_->ScheduleInterrupts(Thread::kVMInterrupt);
}
ml.NotifyAll();
}

View file

@ -1886,6 +1886,13 @@ void IsolateGroup::SetupImagePage(const uint8_t* image_buffer,
is_executable);
}
void IsolateGroup::ScheduleInterrupts(uword interrupt_bits) {
SafepointReadRwLocker ml(Thread::Current(), isolates_lock_.get());
for (Isolate* isolate : isolates_) {
isolate->ScheduleInterrupts(interrupt_bits);
}
}
void Isolate::ScheduleInterrupts(uword interrupt_bits) {
// We take the threads lock here to ensure that the mutator thread does not
// exit the isolate while we are trying to schedule interrupts on it.

View file

@ -335,6 +335,8 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
void RunWithLockedGroup(std::function<void()> fun);
void ScheduleInterrupts(uword interrupt_bits);
ThreadRegistry* thread_registry() const { return thread_registry_.get(); }
SafepointHandler* safepoint_handler() { return safepoint_handler_.get(); }

View file

@ -3152,6 +3152,7 @@ DEFINE_RUNTIME_ENTRY(InterruptOrStackOverflow, 0) {
// Handle interrupts:
// - store buffer overflow
// - OOB message (vm-service or dart:isolate)
// - marking ready for finalization
const Error& error = Error::Handle(thread->HandleInterrupts());
ThrowIfError(error);

View file

@ -741,6 +741,7 @@ ErrorPtr Thread::HandleInterrupts() {
// occur that does promote them.
heap()->CollectGarbage(this, GCType::kEvacuate, GCReason::kStoreBuffer);
}
heap()->CheckFinalizeMarking(this);
#if !defined(PRODUCT)
if (isolate()->TakeHasCompletedBlocks()) {