[vm/concurrency] Avoid relying on Isolate::Current() when deoptimizing code.

The background compiler can cause finalization of classes which can
cause deoptimization of code.

Any deoptimization will iterate over all mutator threads and marks
frames on the stack to be deoptimized. This requires saving old
(fp, pc) state. This state is currently saved on the current isolate's
pending deopt array (via `Thread::Current()->isolate()->AddPendingDeopt()`)
instead of the isolate whose stack got walked.

As part of making the compiler independent of `Isolate::Current()` we
pass the isolate explicitly.

Issue https://github.com/dart-lang/sdk/issues/36097

TEST=Refactoring of existing code.

Change-Id: I9327f3b76981fc16c1879a873edf37df1cbdd8bf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182380
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Martin Kustermann 2021-02-04 11:45:22 +00:00 committed by commit-bot@chromium.org
parent 59aa375d22
commit d604461fc5
4 changed files with 25 additions and 28 deletions

View file

@ -76,24 +76,20 @@ void WeakCodeReferences::DisableCode() {
// Deoptimize stacks and disable code with mutators stopped.
isolate_group->RunWithStoppedMutators([&]() {
Code& code = Code::Handle();
Thread* current = isolate_group->thread_registry()->active_list();
while (current != NULL) {
// Disable all code on stack.
{
DartFrameIterator iterator(
current, StackFrameIterator::kAllowCrossThreadIteration);
StackFrame* frame = iterator.NextFrame();
while (frame != NULL) {
code = frame->LookupDartCode();
if (IsOptimizedCode(code_objects, code)) {
ReportDeoptimization(code);
DeoptimizeAt(code, frame);
}
frame = iterator.NextFrame();
isolate_group->ForEachIsolate([&](Isolate* isolate) {
DartFrameIterator iterator(
isolate->mutator_thread(),
StackFrameIterator::kAllowCrossThreadIteration);
StackFrame* frame = iterator.NextFrame();
while (frame != nullptr) {
code = frame->LookupDartCode();
if (IsOptimizedCode(code_objects, code)) {
ReportDeoptimization(code);
DeoptimizeAt(isolate, code, frame);
}
frame = iterator.NextFrame();
}
current = current->next();
}
});
// Switch functions that use dependent code to unoptimized code.
WeakProperty& weak_property = WeakProperty::Handle();

View file

@ -2952,7 +2952,9 @@ const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason) {
}
}
void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) {
void DeoptimizeAt(Isolate* isolate,
const Code& optimized_code,
StackFrame* frame) {
ASSERT(optimized_code.is_optimized());
// Force-optimized code is optimized code which cannot deoptimize and doesn't
@ -2993,7 +2995,7 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) {
// N.B.: Update the pending deopt table before updating the frame. The
// profiler may attempt a stack walk in between.
thread->isolate()->AddPendingDeopt(frame->fp(), deopt_pc);
isolate->AddPendingDeopt(frame->fp(), deopt_pc);
frame->MarkForLazyDeopt();
if (FLAG_trace_deoptimization) {
@ -3011,22 +3013,21 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) {
void DeoptimizeFunctionsOnStack() {
auto isolate_group = IsolateGroup::Current();
isolate_group->RunWithStoppedMutators([&]() {
auto current = isolate_group->thread_registry()->active_list();
Code& optimized_code = Code::Handle();
while (current != nullptr) {
isolate_group->ForEachIsolate([&](Isolate* isolate) {
DartFrameIterator iterator(
current, StackFrameIterator::kAllowCrossThreadIteration);
isolate->mutator_thread(),
StackFrameIterator::kAllowCrossThreadIteration);
StackFrame* frame = iterator.NextFrame();
while (frame != NULL) {
while (frame != nullptr) {
optimized_code = frame->LookupDartCode();
if (optimized_code.is_optimized() &&
!optimized_code.is_force_optimized()) {
DeoptimizeAt(optimized_code, frame);
DeoptimizeAt(isolate, optimized_code, frame);
}
frame = iterator.NextFrame();
}
current = current->next();
}
});
});
}

View file

@ -160,7 +160,9 @@ extern "C" LocalHandle* DLRT_AllocateHandle(ApiLocalScope* scope);
const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
void DeoptimizeAt(const Code& optimized_code, StackFrame* frame);
void DeoptimizeAt(Isolate* isolate,
const Code& optimized_code,
StackFrame* frame);
void DeoptimizeFunctionsOnStack();
double DartModulo(double a, double b);

View file

@ -58,8 +58,6 @@ class ThreadRegistry {
friend class IsolateGroup;
friend class SafepointHandler;
friend class Scavenger;
friend class WeakCodeReferences;
friend void DeoptimizeFunctionsOnStack();
DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
};