Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
| 6 #include <stdlib.h> | 6 #include <stdlib.h> |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #if defined(TARGET_ARCH_DBC) | 9 #if defined(TARGET_ARCH_DBC) |
| 10 | 10 |
| (...skipping 1086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1097 HANDLE_EXCEPTION; \ | 1097 HANDLE_EXCEPTION; \ |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 #define INVOKE_NATIVE_WRAPPER(Func, Args) \ | 1100 #define INVOKE_NATIVE_WRAPPER(Func, Args) \ |
| 1101 if (!InvokeNativeWrapper(thread, this, Func, &Args)) { \ | 1101 if (!InvokeNativeWrapper(thread, this, Func, &Args)) { \ |
| 1102 HANDLE_EXCEPTION; \ | 1102 HANDLE_EXCEPTION; \ |
| 1103 } | 1103 } |
| 1104 | 1104 |
| 1105 #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_) | 1105 #define LOAD_CONSTANT(index) (pp->data()[(index)].raw_obj_) |
| 1106 | 1106 |
| 1107 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.
| |
| 1108 RawObjectPool** pp, | |
| 1109 uint32_t** pc, | |
| 1110 RawObject*** FP, | |
| 1111 RawObject*** SP, | |
| 1112 bool is_lazy) { | |
| 1113 // Note: frame translation will take care of preserving result at the | |
| 1114 // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. | |
| 1115 | |
| 1116 // Make sure we preserve SP[0] when entering synthetic frame below. | |
| 1117 (*SP)++; | |
| 1118 | |
| 1119 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. | |
| 1120 // The code in this frame may not cause GC. | |
| 1121 // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. | |
| 1122 EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); | |
| 1123 const intptr_t frame_size_in_bytes = | |
| 1124 DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0); | |
| 1125 LeaveSyntheticFrame(FP, SP); | |
| 1126 | |
| 1127 *SP = *FP + (frame_size_in_bytes / kWordSize); | |
| 1128 EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); | |
| 1129 DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP)); | |
| 1130 | |
| 1131 // We are now inside a valid frame. | |
| 1132 { | |
| 1133 *++(*SP) = 0; // Space for the result: number of materialization args. | |
| 1134 Exit(thread, *FP, *SP + 1, /*pc=*/0); | |
| 1135 NativeArguments native_args(thread, 0, *SP, *SP); | |
| 1136 if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) { | |
| 1137 return false; | |
| 1138 } | |
| 1139 } | |
| 1140 const intptr_t materialization_arg_count = | |
| 1141 Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize; | |
| 1142 | |
| 1143 // Restore caller PC. | |
| 1144 *pc = SavedCallerPC(*FP); | |
| 1145 pc_ = reinterpret_cast<uword>(*pc); // For the profiler. | |
| 1146 | |
| 1147 // Check if it is a fake PC marking the entry frame. | |
| 1148 ASSERT((reinterpret_cast<uword>(*pc) & 2) == 0); | |
| 1149 | |
| 1150 // Restore SP, FP and PP. | |
| 1151 // Unoptimized frame SP is one below FrameArguments(...) because | |
| 1152 // FrameArguments(...) returns a pointer to the first argument. | |
| 1153 *SP = FrameArguments(*FP, materialization_arg_count) - 1; | |
| 1154 *FP = SavedCallerFP(*FP); | |
| 1155 | |
| 1156 // Restore pp. | |
| 1157 *pp = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_->ptr(); | |
| 1158 | |
| 1159 return true; | |
| 1160 } | |
| 1161 | |
| 1162 | |
| 1107 RawObject* Simulator::Call(const Code& code, | 1163 RawObject* Simulator::Call(const Code& code, |
| 1108 const Array& arguments_descriptor, | 1164 const Array& arguments_descriptor, |
| 1109 const Array& arguments, | 1165 const Array& arguments, |
| 1110 Thread* thread) { | 1166 Thread* thread) { |
| 1111 // Dispatch used to interpret bytecode. Contains addresses of | 1167 // Dispatch used to interpret bytecode. Contains addresses of |
| 1112 // labels of bytecode handlers. Handlers themselves are defined below. | 1168 // labels of bytecode handlers. Handlers themselves are defined below. |
| 1113 static const void* dispatch[] = { | 1169 static const void* dispatch[] = { |
| 1114 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, | 1170 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, |
| 1115 BYTECODES_LIST(TARGET) | 1171 BYTECODES_LIST(TARGET) |
| 1116 #undef TARGET | 1172 #undef TARGET |
| (...skipping 2449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3566 BYTECODE(LoadIndexedTwoByteString, A_B_C); | 3622 BYTECODE(LoadIndexedTwoByteString, A_B_C); |
| 3567 RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); | 3623 RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); |
| 3568 RawSmi* index = RAW_CAST(Smi, FP[rC]); | 3624 RawSmi* index = RAW_CAST(Smi, FP[rC]); |
| 3569 ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); | 3625 ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); |
| 3570 FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); | 3626 FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); |
| 3571 DISPATCH(); | 3627 DISPATCH(); |
| 3572 } | 3628 } |
| 3573 | 3629 |
| 3574 { | 3630 { |
| 3575 BYTECODE(Deopt, A_D); | 3631 BYTECODE(Deopt, A_D); |
| 3576 | |
| 3577 // Note: frame translation will take care of preserving result at the | |
| 3578 // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. | |
| 3579 const bool is_lazy = rD == 0; | 3632 const bool is_lazy = rD == 0; |
| 3580 | 3633 if (!Deoptimize(thread, &pp, &pc, &FP, &SP, is_lazy)) { |
| 3581 // Make sure we preserve SP[0] when entering synthetic frame below. | 3634 HANDLE_EXCEPTION; |
| 3582 SP++; | |
| 3583 | |
| 3584 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. | |
| 3585 // The code in this frame may not cause GC. | |
| 3586 // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. | |
| 3587 EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0)); | |
| 3588 const intptr_t frame_size_in_bytes = | |
| 3589 DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(FP), is_lazy ? 1 : 0); | |
| 3590 LeaveSyntheticFrame(&FP, &SP); | |
| 3591 | |
| 3592 SP = FP + (frame_size_in_bytes / kWordSize); | |
| 3593 EnterSyntheticFrame(&FP, &SP, pc - (is_lazy ? 1 : 0)); | |
| 3594 DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(FP)); | |
| 3595 | |
| 3596 // We are now inside a valid frame. | |
| 3597 { | |
| 3598 *++SP = 0; // Space for the result: number of materialization args. | |
| 3599 Exit(thread, FP, SP + 1, /*pc=*/0); | |
| 3600 NativeArguments native_args(thread, 0, SP, SP); | |
| 3601 INVOKE_RUNTIME(DRT_DeoptimizeMaterialize, native_args); | |
| 3602 } | 3635 } |
| 3603 const intptr_t materialization_arg_count = | |
| 3604 Smi::Value(RAW_CAST(Smi, *SP--)) / kWordSize; | |
| 3605 | |
| 3606 // Restore caller PC. | |
| 3607 pc = SavedCallerPC(FP); | |
| 3608 pc_ = reinterpret_cast<uword>(pc); // For the profiler. | |
| 3609 | |
| 3610 // Check if it is a fake PC marking the entry frame. | |
| 3611 ASSERT((reinterpret_cast<uword>(pc) & 2) == 0); | |
| 3612 | |
| 3613 // Restore SP, FP and PP. | |
| 3614 // Unoptimized frame SP is one below FrameArguments(...) because | |
| 3615 // FrameArguments(...) returns a pointer to the first argument. | |
| 3616 SP = FrameArguments(FP, materialization_arg_count) - 1; | |
| 3617 FP = SavedCallerFP(FP); | |
| 3618 pp = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_->ptr(); | |
| 3619 | |
| 3620 DISPATCH(); | 3636 DISPATCH(); |
| 3621 } | 3637 } |
| 3622 | 3638 |
| 3639 { | |
| 3640 BYTECODE(DeoptRewind, 0); | |
| 3641 pc = reinterpret_cast<uint32_t*>(thread->resume_pc()); | |
| 3642 if (!Deoptimize(thread, &pp, &pc, &FP, &SP, false /* eager */)) { | |
| 3643 HANDLE_EXCEPTION; | |
| 3644 } | |
| 3645 { | |
| 3646 Exit(thread, FP, SP + 1, pc); | |
| 3647 NativeArguments args(thread, 0, NULL, NULL); | |
| 3648 INVOKE_RUNTIME(DRT_RewindPostDeopt, args); | |
| 3649 } | |
| 3650 UNREACHABLE(); // DRT_RewindPostDeopt does not exit normally. | |
| 3651 DISPATCH(); | |
| 3652 } | |
| 3653 | |
| 3623 { | 3654 { |
| 3624 BYTECODE(Nop, 0); | 3655 BYTECODE(Nop, 0); |
| 3625 DISPATCH(); | 3656 DISPATCH(); |
| 3626 } | 3657 } |
| 3627 | 3658 |
| 3628 { | 3659 { |
| 3629 BYTECODE(Trap, 0); | 3660 BYTECODE(Trap, 0); |
| 3630 UNIMPLEMENTED(); | 3661 UNIMPLEMENTED(); |
| 3631 DISPATCH(); | 3662 DISPATCH(); |
| 3632 } | 3663 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3692 DISPATCH(); | 3723 DISPATCH(); |
| 3693 } | 3724 } |
| 3694 | 3725 |
| 3695 UNREACHABLE(); | 3726 UNREACHABLE(); |
| 3696 return 0; | 3727 return 0; |
| 3697 } | 3728 } |
| 3698 | 3729 |
| 3699 | 3730 |
| 3700 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { | 3731 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
| 3701 // Walk over all setjmp buffers (simulated --> C++ transitions) | 3732 // Walk over all setjmp buffers (simulated --> C++ transitions) |
| 3702 // and try to find the setjmp associated with the simulated stack pointer. | 3733 // and try to find the setjmp associated with the simulated frame pointer. |
| 3703 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); | 3734 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); |
| 3704 while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { | 3735 while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { |
| 3705 buf = buf->link(); | 3736 buf = buf->link(); |
| 3706 } | 3737 } |
| 3707 ASSERT(buf != NULL); | 3738 ASSERT(buf != NULL); |
| 3708 ASSERT(last_setjmp_buffer() == buf); | 3739 ASSERT(last_setjmp_buffer() == buf); |
| 3709 | 3740 |
| 3710 // The C++ caller has not cleaned up the stack memory of C++ frames. | 3741 // The C++ caller has not cleaned up the stack memory of C++ frames. |
| 3711 // Prepare for unwinding frames by destroying all the stack resources | 3742 // Prepare for unwinding frames by destroying all the stack resources |
| 3712 // in the previous C++ frames. | 3743 // in the previous C++ frames. |
| 3713 StackResource::Unwind(thread); | 3744 StackResource::Unwind(thread); |
| 3714 | 3745 |
| 3715 // Set the tag. | 3746 // Set the tag. |
| 3716 thread->set_vm_tag(VMTag::kDartTagId); | 3747 thread->set_vm_tag(VMTag::kDartTagId); |
| 3717 // Clear top exit frame. | 3748 // Clear top exit frame. |
| 3718 thread->set_top_exit_frame_info(0); | 3749 thread->set_top_exit_frame_info(0); |
| 3719 | 3750 |
| 3720 fp_ = reinterpret_cast<RawObject**>(fp); | 3751 fp_ = reinterpret_cast<RawObject**>(fp); |
| 3721 | 3752 |
| 3722 if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) { | 3753 if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) { |
| 3723 // The RunExceptionHandler stub is a placeholder. We implement | 3754 // The RunExceptionHandler stub is a placeholder. We implement |
| 3724 // its behavior here. | 3755 // its behavior here. |
| 3725 RawObject* raw_exception = thread->active_exception(); | 3756 RawObject* raw_exception = thread->active_exception(); |
| 3726 RawObject* raw_stacktrace = thread->active_stacktrace(); | 3757 RawObject* raw_stacktrace = thread->active_stacktrace(); |
| 3727 ASSERT(raw_exception != Object::null()); | 3758 ASSERT(raw_exception != Object::null()); |
| 3728 special_[kExceptionSpecialIndex] = raw_exception; | 3759 special_[kExceptionSpecialIndex] = raw_exception; |
| 3729 special_[kStackTraceSpecialIndex] = raw_stacktrace; | 3760 special_[kStackTraceSpecialIndex] = raw_stacktrace; |
| 3730 pc_ = thread->resume_pc(); | 3761 pc_ = thread->resume_pc(); |
| 3731 } else if (pc == StubCode::DeoptForRewind_entry()->EntryPoint()) { | |
| 3732 // The DeoptForRewind stub is a placeholder. We will eventually | |
| 3733 // implement its behavior here. | |
| 3734 // | |
| 3735 // TODO(turnidge): Refactor the Deopt bytecode so that we can use | |
| 3736 // the implementation here too. The deopt pc is stored in | |
| 3737 // Thread::resume_pc(). After invoking deoptimization, we usually | |
| 3738 // call into Debugger::RewindPostDeopt(), but I need to figure out | |
| 3739 // if that makes any sense (it would JumpToFrame during a | |
| 3740 // JumpToFrame, which seems wrong). | |
| 3741 UNIMPLEMENTED(); | |
| 3742 } else { | 3762 } else { |
| 3743 pc_ = pc; | 3763 pc_ = pc; |
| 3744 } | 3764 } |
| 3745 | 3765 |
| 3746 buf->Longjmp(); | 3766 buf->Longjmp(); |
| 3747 UNREACHABLE(); | 3767 UNREACHABLE(); |
| 3748 } | 3768 } |
| 3749 | 3769 |
| 3750 } // namespace dart | 3770 } // namespace dart |
| 3751 | 3771 |
| 3752 #endif // defined TARGET_ARCH_DBC | 3772 #endif // defined TARGET_ARCH_DBC |
| OLD | NEW |