Index: runtime/vm/code_generator.cc |
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
index 216c2add585f3afa62d9330a345439c4afc7474b..6bfbdb8158e818cc13aa4517f7602d438c824626 100644 |
--- a/runtime/vm/code_generator.cc |
+++ b/runtime/vm/code_generator.cc |
@@ -1996,10 +1996,15 @@ DEOPT_REASONS(DEOPT_REASON_TO_TEXT) |
} |
-void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { |
+void DeoptimizeAt(const Code& optimized_code, uword pc) { |
ASSERT(optimized_code.is_optimized()); |
Thread* thread = Thread::Current(); |
Zone* zone = thread->zone(); |
+ ICData::DeoptReasonId deopt_reason = ICData::kDeoptUnknown; |
+ uint32_t deopt_flags = 0; |
+ const TypedData& deopt_info = TypedData::Handle(zone, |
+ optimized_code.GetDeoptInfoAtPc(pc, &deopt_reason, &deopt_flags)); |
+ ASSERT(!deopt_info.IsNull()); |
const Function& function = Function::Handle(zone, optimized_code.function()); |
const Error& error = |
Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, function)); |
@@ -2013,18 +2018,24 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { |
if (function.HasOptimizedCode()) { |
function.SwitchToUnoptimizedCode(); |
} |
- |
-#if defined(TARGET_ARCH_DBC) |
+ // Patch call site (lazy deoptimization is quite rare, patching it twice |
+ // is not a performance issue). |
+ uword lazy_deopt_jump_return = optimized_code.GetLazyDeoptReturnPc(); |
+ uword lazy_deopt_jump_throw = optimized_code.GetLazyDeoptThrowPc(); |
+#if !defined(TARGET_ARCH_DBC) |
+ ASSERT(lazy_deopt_jump_return != 0); |
+ ASSERT(lazy_deopt_jump_throw != 0); |
+#endif |
const Instructions& instrs = |
Instructions::Handle(zone, optimized_code.instructions()); |
{ |
WritableInstructionsScope writable(instrs.PayloadStart(), instrs.size()); |
- CodePatcher::InsertDeoptimizationCallAt(frame->pc()); |
+ CodePatcher::InsertDeoptimizationCallAt(pc, lazy_deopt_jump_return); |
if (FLAG_trace_patching) { |
const String& name = String::Handle(function.name()); |
OS::PrintErr( |
- "InsertDeoptimizationCallAt: 0x%" Px " for %s\n", |
- frame->pc(), name.ToCString()); |
+ "InsertDeoptimizationCallAt: 0x%" Px " to 0x%" Px " for %s\n", |
+ pc, lazy_deopt_jump_return, name.ToCString()); |
} |
const ExceptionHandlers& handlers = |
ExceptionHandlers::Handle(zone, optimized_code.exception_handlers()); |
@@ -2032,34 +2043,12 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { |
for (intptr_t i = 0; i < handlers.num_entries(); ++i) { |
handlers.GetHandlerInfo(i, &info); |
const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; |
- CodePatcher::InsertDeoptimizationCallAt(patch_pc); |
+ CodePatcher::InsertDeoptimizationCallAt(patch_pc, lazy_deopt_jump_throw); |
if (FLAG_trace_patching) { |
OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); |
} |
} |
} |
-#else // !DBC |
- uword lazy_deopt_entry = |
- StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint(); |
- if (frame->pc() == lazy_deopt_entry) { |
- // Deopt already scheduled. |
- if (FLAG_trace_deoptimization) { |
- THR_Print("Lazy deopt already scheduled for fp=%" Pp "\n", frame->fp()); |
- } |
- } else { |
- uword deopt_pc = frame->pc(); |
- ASSERT(optimized_code.ContainsInstructionAt(deopt_pc)); |
- PendingLazyDeopt pair(frame->fp(), deopt_pc); |
- thread->isolate()->pending_deopts()->Add(pair); |
- frame->set_pc(lazy_deopt_entry); |
- |
- if (FLAG_trace_deoptimization) { |
- THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", |
- frame->fp(), deopt_pc); |
- } |
- } |
-#endif // !DBC |
- |
// Mark code as dead (do not GC its embedded objects). |
optimized_code.set_is_alive(false); |
} |
@@ -2074,7 +2063,7 @@ void DeoptimizeFunctionsOnStack() { |
while (frame != NULL) { |
optimized_code = frame->LookupDartCode(); |
if (optimized_code.is_optimized()) { |
- DeoptimizeAt(optimized_code, frame); |
+ DeoptimizeAt(optimized_code, frame->pc()); |
} |
frame = iterator.NextFrame(); |
} |
@@ -2155,40 +2144,6 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
is_lazy_deopt ? "lazy-deopt" : ""); |
} |
-#if !defined(TARGET_ARCH_DBC) |
- if (is_lazy_deopt) { |
- uword deopt_pc = 0; |
- MallocGrowableArray<PendingLazyDeopt>* pending_deopts = |
- isolate->pending_deopts(); |
- for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) { |
- if ((*pending_deopts)[i].fp() == caller_frame->fp()) { |
- deopt_pc = (*pending_deopts)[i].pc(); |
- break; |
- } |
- } |
- for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) { |
- if ((*pending_deopts)[i].fp() <= caller_frame->fp()) { |
- pending_deopts->RemoveAt(i); |
- } |
- } |
- if (FLAG_trace_deoptimization) { |
- THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", |
- caller_frame->fp(), deopt_pc); |
- THR_Print("%" Pd " pending lazy deopts\n", |
- pending_deopts->length()); |
- } |
- ASSERT(deopt_pc != 0); |
- caller_frame->set_pc(deopt_pc); |
- ASSERT(caller_frame->pc() == deopt_pc); |
- } else { |
- if (FLAG_trace_deoptimization) { |
- THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", |
- caller_frame->fp(), caller_frame->pc()); |
- } |
- } |
- ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); |
-#endif // !DBC |
- |
// Copy the saved registers from the stack. |
fpu_register_t* fpu_registers; |
intptr_t* cpu_registers; |
@@ -2249,7 +2204,6 @@ DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) { |
deopt_context->set_dest_frame(caller_frame); |
deopt_context->FillDestFrame(); |
- |
#else |
UNREACHABLE(); |
#endif // !DART_PRECOMPILED_RUNTIME |