Chromium Code Reviews| Index: runtime/vm/simulator_dbc.cc |
| diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc |
| index 86ca930a41aaaa0c5d639f206872e2fb6d65326c..9d2dc3c3a348c01ea9991a50cb92582647d4d92e 100644 |
| --- a/runtime/vm/simulator_dbc.cc |
| +++ b/runtime/vm/simulator_dbc.cc |
| @@ -1104,6 +1104,62 @@ static DART_NOINLINE bool InvokeNativeWrapper(Thread* thread, |
| #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_) |
| +DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread, |
|
Cutch
2017/03/07 00:22:29
Maybe add a comment that says "Returns false if th
turnidge
2017/03/08 19:24:08
Done.
|
| + RawObjectPool** pp, |
| + uint32_t** pc, |
| + RawObject*** FP, |
| + RawObject*** SP, |
| + bool is_lazy) { |
| + // Note: frame translation will take care of preserving result at the |
| + // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. |
| + |
| + // Make sure we preserve SP[0] when entering synthetic frame below. |
| + (*SP)++; |
| + |
| + // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
| + // The code in this frame may not cause GC. |
| + // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. |
| + EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); |
| + const intptr_t frame_size_in_bytes = |
| + DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0); |
| + LeaveSyntheticFrame(FP, SP); |
| + |
| + *SP = *FP + (frame_size_in_bytes / kWordSize); |
| + EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); |
| + DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP)); |
| + |
| + // We are now inside a valid frame. |
| + { |
| + *++(*SP) = 0; // Space for the result: number of materialization args. |
| + Exit(thread, *FP, *SP + 1, /*pc=*/0); |
| + NativeArguments native_args(thread, 0, *SP, *SP); |
| + if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) { |
| + return false; |
| + } |
| + } |
| + const intptr_t materialization_arg_count = |
| + Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize; |
| + |
| + // Restore caller PC. |
| + *pc = SavedCallerPC(*FP); |
| + pc_ = reinterpret_cast<uword>(*pc); // For the profiler. |
| + |
| + // Check if it is a fake PC marking the entry frame. |
| + ASSERT((reinterpret_cast<uword>(*pc) & 2) == 0); |
| + |
| + // Restore SP, FP and PP. |
| + // Unoptimized frame SP is one below FrameArguments(...) because |
| + // FrameArguments(...) returns a pointer to the first argument. |
| + *SP = FrameArguments(*FP, materialization_arg_count) - 1; |
| + *FP = SavedCallerFP(*FP); |
| + |
| + // Restore pp. |
| + *pp = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_->ptr(); |
| + |
| + return true; |
| +} |
| + |
| + |
| RawObject* Simulator::Call(const Code& code, |
| const Array& arguments_descriptor, |
| const Array& arguments, |
| @@ -3573,50 +3629,25 @@ RawObject* Simulator::Call(const Code& code, |
| { |
| BYTECODE(Deopt, A_D); |
| - |
| - // Note: frame translation will take care of preserving result at the |
| - // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. |
| const bool is_lazy = rD == 0; |
| + if (!Deoptimize(thread, &pp, &pc, &FP, &SP, is_lazy)) { |
| + HANDLE_EXCEPTION; |
| + } |
| + DISPATCH(); |
| + } |
| - // Make sure we preserve SP[0] when entering synthetic frame below. |
| - SP++; |
| - |
| - // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
| - // The code in this frame may not cause GC. |
| - // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. |
| - EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0)); |
| - const intptr_t frame_size_in_bytes = |
| - DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(FP), is_lazy ? 1 : 0); |
| - LeaveSyntheticFrame(&FP, &SP); |
| - |
| - SP = FP + (frame_size_in_bytes / kWordSize); |
| - EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0)); |
| - DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(FP)); |
| - |
| - // We are now inside a valid frame. |
| + { |
| + BYTECODE(DeoptRewind, 0); |
| + pc = reinterpret_cast<uint32_t*>(thread->resume_pc()); |
| + if (!Deoptimize(thread, &pp, &pc, &FP, &SP, false /* eager */)) { |
| + HANDLE_EXCEPTION; |
| + } |
| { |
| - *++SP = 0; // Space for the result: number of materialization args. |
| - Exit(thread, FP, SP + 1, /*pc=*/0); |
| - NativeArguments native_args(thread, 0, SP, SP); |
| - INVOKE_RUNTIME(DRT_DeoptimizeMaterialize, native_args); |
| + Exit(thread, FP, SP + 1, pc); |
| + NativeArguments args(thread, 0, NULL, NULL); |
| + INVOKE_RUNTIME(DRT_RewindPostDeopt, args); |
| } |
| - const intptr_t materialization_arg_count = |
| - Smi::Value(RAW_CAST(Smi, *SP--)) / kWordSize; |
| - |
| - // Restore caller PC. |
| - pc = SavedCallerPC(FP); |
| - pc_ = reinterpret_cast<uword>(pc); // For the profiler. |
| - |
| - // Check if it is a fake PC marking the entry frame. |
| - ASSERT((reinterpret_cast<uword>(pc) & 2) == 0); |
| - |
| - // Restore SP, FP and PP. |
| - // Unoptimized frame SP is one below FrameArguments(...) because |
| - // FrameArguments(...) returns a pointer to the first argument. |
| - SP = FrameArguments(FP, materialization_arg_count) - 1; |
| - FP = SavedCallerFP(FP); |
| - pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); |
| - |
| + UNREACHABLE(); // DRT_RewindPostDeopt does not exit normally. |
| DISPATCH(); |
| } |
| @@ -3699,7 +3730,7 @@ RawObject* Simulator::Call(const Code& code, |
| void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
| // Walk over all setjmp buffers (simulated --> C++ transitions) |
| - // and try to find the setjmp associated with the simulated stack pointer. |
| + // and try to find the setjmp associated with the simulated frame pointer. |
| SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); |
| while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { |
| buf = buf->link(); |
| @@ -3728,17 +3759,6 @@ void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
| special_[kExceptionSpecialIndex] = raw_exception; |
| special_[kStackTraceSpecialIndex] = raw_stacktrace; |
| pc_ = thread->resume_pc(); |
| - } else if (pc == StubCode::DeoptForRewind_entry()->EntryPoint()) { |
| - // The DeoptForRewind stub is a placeholder. We will eventually |
| - // implement its behavior here. |
| - // |
| - // TODO(turnidge): Refactor the Deopt bytecode so that we can use |
| - // the implementation here too. The deopt pc is stored in |
| - // Thread::resume_pc(). After invoking deoptimization, we usually |
| - // call into Debugger::RewindPostDeopt(), but I need to figure out |
| - // if that makes any sense (it would JumpToFrame during a |
| - // JumpToFrame, which seems wrong). |
| - UNIMPLEMENTED(); |
| } else { |
| pc_ = pc; |
| } |