| Index: runtime/vm/simulator_dbc.cc
|
| diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
|
| index 86ca930a41aaaa0c5d639f206872e2fb6d65326c..d16a5a375869ea3c06faeb2d7826d0b627feec63 100644
|
| --- a/runtime/vm/simulator_dbc.cc
|
| +++ b/runtime/vm/simulator_dbc.cc
|
| @@ -1104,6 +1104,64 @@ static DART_NOINLINE bool InvokeNativeWrapper(Thread* thread,
|
|
|
| #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_)
|
|
|
| +
|
| +// Returns true if deoptimization succeeds.
|
| +DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread,
|
| + 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 +3631,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 +3732,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 +3761,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;
|
| }
|
|
|