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 |
| 1108 // Returns true if deoptimization succeeds. |
| 1109 DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread, |
| 1110 RawObjectPool** pp, |
| 1111 uint32_t** pc, |
| 1112 RawObject*** FP, |
| 1113 RawObject*** SP, |
| 1114 bool is_lazy) { |
| 1115 // Note: frame translation will take care of preserving result at the |
| 1116 // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo. |
| 1117 |
| 1118 // Make sure we preserve SP[0] when entering synthetic frame below. |
| 1119 (*SP)++; |
| 1120 |
| 1121 // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame. |
| 1122 // The code in this frame may not cause GC. |
| 1123 // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls. |
| 1124 EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); |
| 1125 const intptr_t frame_size_in_bytes = |
| 1126 DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0); |
| 1127 LeaveSyntheticFrame(FP, SP); |
| 1128 |
| 1129 *SP = *FP + (frame_size_in_bytes / kWordSize); |
| 1130 EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0)); |
| 1131 DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP)); |
| 1132 |
| 1133 // We are now inside a valid frame. |
| 1134 { |
| 1135 *++(*SP) = 0; // Space for the result: number of materialization args. |
| 1136 Exit(thread, *FP, *SP + 1, /*pc=*/0); |
| 1137 NativeArguments native_args(thread, 0, *SP, *SP); |
| 1138 if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) { |
| 1139 return false; |
| 1140 } |
| 1141 } |
| 1142 const intptr_t materialization_arg_count = |
| 1143 Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize; |
| 1144 |
| 1145 // Restore caller PC. |
| 1146 *pc = SavedCallerPC(*FP); |
| 1147 pc_ = reinterpret_cast<uword>(*pc); // For the profiler. |
| 1148 |
| 1149 // Check if it is a fake PC marking the entry frame. |
| 1150 ASSERT((reinterpret_cast<uword>(*pc) & 2) == 0); |
| 1151 |
| 1152 // Restore SP, FP and PP. |
| 1153 // Unoptimized frame SP is one below FrameArguments(...) because |
| 1154 // FrameArguments(...) returns a pointer to the first argument. |
| 1155 *SP = FrameArguments(*FP, materialization_arg_count) - 1; |
| 1156 *FP = SavedCallerFP(*FP); |
| 1157 |
| 1158 // Restore pp. |
| 1159 *pp = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_->ptr(); |
| 1160 |
| 1161 return true; |
| 1162 } |
| 1163 |
| 1164 |
1107 RawObject* Simulator::Call(const Code& code, | 1165 RawObject* Simulator::Call(const Code& code, |
1108 const Array& arguments_descriptor, | 1166 const Array& arguments_descriptor, |
1109 const Array& arguments, | 1167 const Array& arguments, |
1110 Thread* thread) { | 1168 Thread* thread) { |
1111 // Dispatch used to interpret bytecode. Contains addresses of | 1169 // Dispatch used to interpret bytecode. Contains addresses of |
1112 // labels of bytecode handlers. Handlers themselves are defined below. | 1170 // labels of bytecode handlers. Handlers themselves are defined below. |
1113 static const void* dispatch[] = { | 1171 static const void* dispatch[] = { |
1114 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, | 1172 #define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name, |
1115 BYTECODES_LIST(TARGET) | 1173 BYTECODES_LIST(TARGET) |
1116 #undef TARGET | 1174 #undef TARGET |
(...skipping 2449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3566 BYTECODE(LoadIndexedTwoByteString, A_B_C); | 3624 BYTECODE(LoadIndexedTwoByteString, A_B_C); |
3567 RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); | 3625 RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); |
3568 RawSmi* index = RAW_CAST(Smi, FP[rC]); | 3626 RawSmi* index = RAW_CAST(Smi, FP[rC]); |
3569 ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); | 3627 ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_)); |
3570 FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); | 3628 FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); |
3571 DISPATCH(); | 3629 DISPATCH(); |
3572 } | 3630 } |
3573 | 3631 |
3574 { | 3632 { |
3575 BYTECODE(Deopt, A_D); | 3633 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; | 3634 const bool is_lazy = rD == 0; |
3580 | 3635 if (!Deoptimize(thread, &pp, &pc, &FP, &SP, is_lazy)) { |
3581 // Make sure we preserve SP[0] when entering synthetic frame below. | 3636 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 } | 3637 } |
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(); | 3638 DISPATCH(); |
3621 } | 3639 } |
3622 | 3640 |
| 3641 { |
| 3642 BYTECODE(DeoptRewind, 0); |
| 3643 pc = reinterpret_cast<uint32_t*>(thread->resume_pc()); |
| 3644 if (!Deoptimize(thread, &pp, &pc, &FP, &SP, false /* eager */)) { |
| 3645 HANDLE_EXCEPTION; |
| 3646 } |
| 3647 { |
| 3648 Exit(thread, FP, SP + 1, pc); |
| 3649 NativeArguments args(thread, 0, NULL, NULL); |
| 3650 INVOKE_RUNTIME(DRT_RewindPostDeopt, args); |
| 3651 } |
| 3652 UNREACHABLE(); // DRT_RewindPostDeopt does not exit normally. |
| 3653 DISPATCH(); |
| 3654 } |
| 3655 |
3623 { | 3656 { |
3624 BYTECODE(Nop, 0); | 3657 BYTECODE(Nop, 0); |
3625 DISPATCH(); | 3658 DISPATCH(); |
3626 } | 3659 } |
3627 | 3660 |
3628 { | 3661 { |
3629 BYTECODE(Trap, 0); | 3662 BYTECODE(Trap, 0); |
3630 UNIMPLEMENTED(); | 3663 UNIMPLEMENTED(); |
3631 DISPATCH(); | 3664 DISPATCH(); |
3632 } | 3665 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3692 DISPATCH(); | 3725 DISPATCH(); |
3693 } | 3726 } |
3694 | 3727 |
3695 UNREACHABLE(); | 3728 UNREACHABLE(); |
3696 return 0; | 3729 return 0; |
3697 } | 3730 } |
3698 | 3731 |
3699 | 3732 |
3700 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { | 3733 void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { |
3701 // Walk over all setjmp buffers (simulated --> C++ transitions) | 3734 // Walk over all setjmp buffers (simulated --> C++ transitions) |
3702 // and try to find the setjmp associated with the simulated stack pointer. | 3735 // and try to find the setjmp associated with the simulated frame pointer. |
3703 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); | 3736 SimulatorSetjmpBuffer* buf = last_setjmp_buffer(); |
3704 while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { | 3737 while ((buf->link() != NULL) && (buf->link()->fp() > fp)) { |
3705 buf = buf->link(); | 3738 buf = buf->link(); |
3706 } | 3739 } |
3707 ASSERT(buf != NULL); | 3740 ASSERT(buf != NULL); |
3708 ASSERT(last_setjmp_buffer() == buf); | 3741 ASSERT(last_setjmp_buffer() == buf); |
3709 | 3742 |
3710 // The C++ caller has not cleaned up the stack memory of C++ frames. | 3743 // The C++ caller has not cleaned up the stack memory of C++ frames. |
3711 // Prepare for unwinding frames by destroying all the stack resources | 3744 // Prepare for unwinding frames by destroying all the stack resources |
3712 // in the previous C++ frames. | 3745 // in the previous C++ frames. |
3713 StackResource::Unwind(thread); | 3746 StackResource::Unwind(thread); |
3714 | 3747 |
3715 // Set the tag. | 3748 // Set the tag. |
3716 thread->set_vm_tag(VMTag::kDartTagId); | 3749 thread->set_vm_tag(VMTag::kDartTagId); |
3717 // Clear top exit frame. | 3750 // Clear top exit frame. |
3718 thread->set_top_exit_frame_info(0); | 3751 thread->set_top_exit_frame_info(0); |
3719 | 3752 |
3720 fp_ = reinterpret_cast<RawObject**>(fp); | 3753 fp_ = reinterpret_cast<RawObject**>(fp); |
3721 | 3754 |
3722 if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) { | 3755 if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) { |
3723 // The RunExceptionHandler stub is a placeholder. We implement | 3756 // The RunExceptionHandler stub is a placeholder. We implement |
3724 // its behavior here. | 3757 // its behavior here. |
3725 RawObject* raw_exception = thread->active_exception(); | 3758 RawObject* raw_exception = thread->active_exception(); |
3726 RawObject* raw_stacktrace = thread->active_stacktrace(); | 3759 RawObject* raw_stacktrace = thread->active_stacktrace(); |
3727 ASSERT(raw_exception != Object::null()); | 3760 ASSERT(raw_exception != Object::null()); |
3728 special_[kExceptionSpecialIndex] = raw_exception; | 3761 special_[kExceptionSpecialIndex] = raw_exception; |
3729 special_[kStackTraceSpecialIndex] = raw_stacktrace; | 3762 special_[kStackTraceSpecialIndex] = raw_stacktrace; |
3730 pc_ = thread->resume_pc(); | 3763 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 { | 3764 } else { |
3743 pc_ = pc; | 3765 pc_ = pc; |
3744 } | 3766 } |
3745 | 3767 |
3746 buf->Longjmp(); | 3768 buf->Longjmp(); |
3747 UNREACHABLE(); | 3769 UNREACHABLE(); |
3748 } | 3770 } |
3749 | 3771 |
3750 } // namespace dart | 3772 } // namespace dart |
3751 | 3773 |
3752 #endif // defined TARGET_ARCH_DBC | 3774 #endif // defined TARGET_ARCH_DBC |
OLD | NEW |