[vm/shared] Remove "single mutator" fastpath from RunWithStoppedMutators.

In presence of isolate-less mutators, the check for "single mutator"-scenario is not-trivial, acquiring active_mutator_count mutex results in circular mutex dependencies.

BUG=https://github.com/dart-lang/sdk/issues/60857
BUG=https://github.com/dart-lang/sdk/issues/60953
TEST=ci

Change-Id: I5a12f9b8d4bc54042137012668ed1afee7c7739f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/435241
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
Alexander Aprelev
2025-06-30 10:31:57 -07:00
committed by Commit Queue
parent 29698c70a3
commit bd0d029792
5 changed files with 19 additions and 41 deletions
+1 -1
View File
@@ -145,8 +145,8 @@ DEFINE_FFI_NATIVE_ENTRY(IsolateGroup_runSync,
Thread::EnterIsolate(saved_isolate);
Thread* T = Thread::Current();
T->EnterSafepointToNative();
T->set_execution_state(Thread::kThreadInNative);
T->EnterSafepoint();
Dart_Handle local_handle = Dart_HandleFromPersistent(persistent_result);
Dart_DeletePersistentHandle(persistent_result);
+1 -1
View File
@@ -1554,8 +1554,8 @@ DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate) {
// TransitionXXX scope objects as the reverse transition happens
// outside this scope in Dart_ExitIsolate/Dart_ShutdownIsolate.
Thread* T = Thread::Current();
T->EnterSafepointToNative();
T->set_execution_state(Thread::kThreadInNative);
T->EnterSafepointToNative();
}
DART_EXPORT void Dart_StartProfiling() {
+6 -16
View File
@@ -2909,37 +2909,27 @@ Isolate* IsolateGroup::FirstIsolateLocked() const {
return isolates_.IsEmpty() ? nullptr : isolates_.First();
}
void IsolateGroup::RunWithStoppedMutatorsCallable(
Callable* single_current_mutator,
Callable* otherwise,
bool use_force_growth_in_otherwise) {
void IsolateGroup::RunWithStoppedMutatorsCallable(Callable* callable,
bool use_force_growth) {
auto thread = Thread::Current();
StoppedMutatorsScope stopped_mutators_scope(thread);
if (thread->OwnsSafepoint()) {
RELEASE_ASSERT(thread->OwnsSafepoint());
single_current_mutator->Call();
callable->Call();
return;
}
{
SafepointReadRwLocker ml(thread, isolates_lock_.get());
if (thread->IsDartMutatorThread() && ContainsOnlyOneIsolate()) {
single_current_mutator->Call();
return;
}
}
// We use the more strict safepoint operation scope here (which ensures that
// all other threads, including auxiliary threads are at a safepoint), even
// though we only need to ensure that the mutator threads are stopped.
if (use_force_growth_in_otherwise) {
if (use_force_growth) {
ForceGrowthSafepointOperationScope safepoint_scope(
thread, SafepointLevel::kGCAndDeopt);
otherwise->Call();
callable->Call();
} else {
DeoptSafepointOperationScope safepoint_scope(thread);
otherwise->Call();
callable->Call();
}
}
+5 -18
View File
@@ -61,7 +61,6 @@ class IsolateProfilerData;
class Log;
class Message;
class MessageHandler;
class MonitorLocker;
class Mutex;
class Object;
class ObjectIdRing;
@@ -599,32 +598,20 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
// Ensures mutators are stopped during execution of the provided function.
//
// If the current thread is the only mutator in the isolate group,
// [single_current_mutator] will be called. Otherwise [otherwise] will be
// [callable] will be called directly. Otherwise [callable] will be
// called inside a [SafepointOperationsScope] (or
// [ForceGrowthSafepointOperationScope] if [use_force_growth_in_otherwise]
// [ForceGrowthSafepointOperationScope] if [use_force_growth]
// is set).
//
// During the duration of this function, no new isolates can be added to the
// isolate group.
void RunWithStoppedMutatorsCallable(
Callable* single_current_mutator,
Callable* otherwise,
bool use_force_growth_in_otherwise = false);
template <typename T, typename S>
void RunWithStoppedMutators(T single_current_mutator,
S otherwise,
bool use_force_growth_in_otherwise = false) {
LambdaCallable<T> single_callable(single_current_mutator);
LambdaCallable<S> otherwise_callable(otherwise);
RunWithStoppedMutatorsCallable(&single_callable, &otherwise_callable,
use_force_growth_in_otherwise);
}
void RunWithStoppedMutatorsCallable(Callable* callable,
bool use_force_growth = false);
template <typename T>
void RunWithStoppedMutators(T function, bool use_force_growth = false) {
LambdaCallable<T> callable(function);
RunWithStoppedMutatorsCallable(&callable, &callable, use_force_growth);
RunWithStoppedMutatorsCallable(&callable, use_force_growth);
}
#ifndef PRODUCT
+6 -5
View File
@@ -520,6 +520,10 @@ void Thread::ExitIsolateGroupAsHelper(bool bypass_safepoint) {
void Thread::EnterIsolateGroupAsMutator(IsolateGroup* isolate_group,
bool bypass_safepoint) {
isolate_group->IncreaseMutatorCount(/*thread=*/nullptr,
/*is_nested_reenter=*/true,
/*was_stolen=*/false);
Thread* thread = AddActiveThread(isolate_group, /*isolate=*/nullptr,
kMutatorTask, bypass_safepoint);
RELEASE_ASSERT(thread != nullptr);
@@ -542,10 +546,6 @@ void Thread::EnterIsolateGroupAsMutator(IsolateGroup* isolate_group,
thread->SetStackLimit(OSThread::Current()->overflow_stack_limit());
#endif
isolate_group->IncreaseMutatorCount(/*thread=*/thread,
/*is_nested_reenter=*/false,
/*was_stolen=*/true);
thread->AssertDartMutatorInvariants();
}
@@ -559,8 +559,9 @@ void Thread::ExitIsolateGroupAsMutator(bool bypass_safepoint) {
thread->ResetMutatorState();
thread->ClearStackLimit();
SuspendThreadInternal(thread, VMTag::kInvalidTagId);
thread->isolate_group()->DecreaseMutatorCount(/*is_nested_exit=*/true);
auto group = thread->isolate_group();
FreeActiveThread(thread, /*isolate=*/nullptr, bypass_safepoint);
group->DecreaseMutatorCount(/*is_nested_exit=*/true);
}
void Thread::EnterIsolateGroupAsNonMutator(IsolateGroup* isolate_group,