| 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
|
|
|