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 |