| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "vm/debugger.h" | 5 #include "vm/debugger.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 next_id_(1), | 1251 next_id_(1), |
| 1252 latent_locations_(NULL), | 1252 latent_locations_(NULL), |
| 1253 breakpoint_locations_(NULL), | 1253 breakpoint_locations_(NULL), |
| 1254 code_breakpoints_(NULL), | 1254 code_breakpoints_(NULL), |
| 1255 resume_action_(kContinue), | 1255 resume_action_(kContinue), |
| 1256 ignore_breakpoints_(false), | 1256 ignore_breakpoints_(false), |
| 1257 pause_event_(NULL), | 1257 pause_event_(NULL), |
| 1258 obj_cache_(NULL), | 1258 obj_cache_(NULL), |
| 1259 stack_trace_(NULL), | 1259 stack_trace_(NULL), |
| 1260 stepping_fp_(0), | 1260 stepping_fp_(0), |
| 1261 skip_next_step_(false), |
| 1261 exc_pause_info_(kNoPauseOnExceptions) { | 1262 exc_pause_info_(kNoPauseOnExceptions) { |
| 1262 } | 1263 } |
| 1263 | 1264 |
| 1264 | 1265 |
| 1265 Debugger::~Debugger() { | 1266 Debugger::~Debugger() { |
| 1266 isolate_id_ = ILLEGAL_ISOLATE_ID; | 1267 isolate_id_ = ILLEGAL_ISOLATE_ID; |
| 1267 ASSERT(!IsPaused()); | 1268 ASSERT(!IsPaused()); |
| 1268 ASSERT(latent_locations_ == NULL); | 1269 ASSERT(latent_locations_ == NULL); |
| 1269 ASSERT(breakpoint_locations_ == NULL); | 1270 ASSERT(breakpoint_locations_ == NULL); |
| 1270 ASSERT(code_breakpoints_ == NULL); | 1271 ASSERT(code_breakpoints_ == NULL); |
| (...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2525 } | 2526 } |
| 2526 | 2527 |
| 2527 | 2528 |
| 2528 void Debugger::EnterSingleStepMode() { | 2529 void Debugger::EnterSingleStepMode() { |
| 2529 stepping_fp_ = 0; | 2530 stepping_fp_ = 0; |
| 2530 DeoptimizeWorld(); | 2531 DeoptimizeWorld(); |
| 2531 isolate_->set_single_step(true); | 2532 isolate_->set_single_step(true); |
| 2532 } | 2533 } |
| 2533 | 2534 |
| 2534 | 2535 |
| 2535 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) { | 2536 void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, |
| 2537 bool skip_next_step) { |
| 2536 stepping_fp_ = 0; | 2538 stepping_fp_ = 0; |
| 2537 if (resume_action_ == kSingleStep) { | 2539 if (resume_action_ == kSingleStep) { |
| 2538 // When single stepping, we need to deoptimize because we might be | 2540 // When single stepping, we need to deoptimize because we might be |
| 2539 // stepping into optimized code. This happens in particular if | 2541 // stepping into optimized code. This happens in particular if |
| 2540 // the isolate has been interrupted, but can happen in other cases | 2542 // the isolate has been interrupted, but can happen in other cases |
| 2541 // as well. We need to deoptimize the world in case we are about | 2543 // as well. We need to deoptimize the world in case we are about |
| 2542 // to call an optimized function. | 2544 // to call an optimized function. |
| 2543 DeoptimizeWorld(); | 2545 DeoptimizeWorld(); |
| 2544 isolate_->set_single_step(true); | 2546 isolate_->set_single_step(true); |
| 2547 skip_next_step_ = skip_next_step; |
| 2545 if (FLAG_verbose_debug) { | 2548 if (FLAG_verbose_debug) { |
| 2546 OS::Print("HandleSteppingRequest- kSingleStep\n"); | 2549 OS::Print("HandleSteppingRequest- kSingleStep\n"); |
| 2547 } | 2550 } |
| 2548 } else if (resume_action_ == kStepOver) { | 2551 } else if (resume_action_ == kStepOver) { |
| 2549 DeoptimizeWorld(); | 2552 DeoptimizeWorld(); |
| 2550 isolate_->set_single_step(true); | 2553 isolate_->set_single_step(true); |
| 2554 skip_next_step_ = skip_next_step; |
| 2551 ASSERT(stack_trace->Length() > 0); | 2555 ASSERT(stack_trace->Length() > 0); |
| 2552 stepping_fp_ = stack_trace->FrameAt(0)->fp(); | 2556 stepping_fp_ = stack_trace->FrameAt(0)->fp(); |
| 2553 if (FLAG_verbose_debug) { | 2557 if (FLAG_verbose_debug) { |
| 2554 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_); | 2558 OS::Print("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_); |
| 2555 } | 2559 } |
| 2556 } else if (resume_action_ == kStepOut) { | 2560 } else if (resume_action_ == kStepOut) { |
| 2557 DeoptimizeWorld(); | 2561 DeoptimizeWorld(); |
| 2558 isolate_->set_single_step(true); | 2562 isolate_->set_single_step(true); |
| 2559 // Find topmost caller that is debuggable. | 2563 // Find topmost caller that is debuggable. |
| 2560 for (intptr_t i = 1; i < stack_trace->Length(); i++) { | 2564 for (intptr_t i = 1; i < stack_trace->Length(); i++) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2617 Pause(&event); | 2621 Pause(&event); |
| 2618 } | 2622 } |
| 2619 | 2623 |
| 2620 | 2624 |
| 2621 RawError* Debugger::DebuggerStepCallback() { | 2625 RawError* Debugger::DebuggerStepCallback() { |
| 2622 ASSERT(isolate_->single_step()); | 2626 ASSERT(isolate_->single_step()); |
| 2623 // Don't pause recursively. | 2627 // Don't pause recursively. |
| 2624 if (IsPaused()) { | 2628 if (IsPaused()) { |
| 2625 return Error::null(); | 2629 return Error::null(); |
| 2626 } | 2630 } |
| 2631 if (skip_next_step_) { |
| 2632 skip_next_step_ = false; |
| 2633 return Error::null(); |
| 2634 } |
| 2627 | 2635 |
| 2628 // Check whether we are in a Dart function that the user is | 2636 // Check whether we are in a Dart function that the user is |
| 2629 // interested in. If we saved the frame pointer of a stack frame | 2637 // interested in. If we saved the frame pointer of a stack frame |
| 2630 // the user is interested in, we ignore the single step if we are | 2638 // the user is interested in, we ignore the single step if we are |
| 2631 // in a callee of that frame. Note that we assume that the stack | 2639 // in a callee of that frame. Note that we assume that the stack |
| 2632 // grows towards lower addresses. | 2640 // grows towards lower addresses. |
| 2633 ActivationFrame* frame = TopDartFrame(); | 2641 ActivationFrame* frame = TopDartFrame(); |
| 2634 ASSERT(frame != NULL); | 2642 ASSERT(frame != NULL); |
| 2635 | 2643 |
| 2636 if (stepping_fp_ != 0) { | 2644 if (stepping_fp_ != 0) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2648 } | 2656 } |
| 2649 } | 2657 } |
| 2650 | 2658 |
| 2651 if (!frame->IsDebuggable()) { | 2659 if (!frame->IsDebuggable()) { |
| 2652 return Error::null(); | 2660 return Error::null(); |
| 2653 } | 2661 } |
| 2654 if (!Token::IsDebugPause(frame->TokenPos())) { | 2662 if (!Token::IsDebugPause(frame->TokenPos())) { |
| 2655 return Error::null(); | 2663 return Error::null(); |
| 2656 } | 2664 } |
| 2657 | 2665 |
| 2658 // Don't pause for a single step if there is a breakpoint set | 2666 // If there is an active breakpoint at this pc, then we should have |
| 2659 // at this location. | 2667 // already bailed out of this function in the skip_next_step_ test |
| 2660 if (HasActiveBreakpoint(frame->pc())) { | 2668 // above. |
| 2661 return Error::null(); | 2669 ASSERT(!HasActiveBreakpoint(frame->pc())); |
| 2662 } | |
| 2663 | 2670 |
| 2664 if (FLAG_verbose_debug) { | 2671 if (FLAG_verbose_debug) { |
| 2665 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", | 2672 OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n", |
| 2666 String::Handle(frame->SourceUrl()).ToCString(), | 2673 String::Handle(frame->SourceUrl()).ToCString(), |
| 2667 frame->LineNumber(), | 2674 frame->LineNumber(), |
| 2668 String::Handle(frame->QualifiedFunctionName()).ToCString(), | 2675 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
| 2669 frame->TokenPos()); | 2676 frame->TokenPos()); |
| 2670 } | 2677 } |
| 2671 | 2678 |
| 2672 ASSERT(stack_trace_ == NULL); | 2679 ASSERT(stack_trace_ == NULL); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 cbpt->IsInternal() ? "internal" : "user", | 2758 cbpt->IsInternal() ? "internal" : "user", |
| 2752 String::Handle(cbpt->SourceUrl()).ToCString(), | 2759 String::Handle(cbpt->SourceUrl()).ToCString(), |
| 2753 cbpt->LineNumber(), | 2760 cbpt->LineNumber(), |
| 2754 cbpt->token_pos(), | 2761 cbpt->token_pos(), |
| 2755 top_frame->pc()); | 2762 top_frame->pc()); |
| 2756 } | 2763 } |
| 2757 | 2764 |
| 2758 ASSERT(stack_trace_ == NULL); | 2765 ASSERT(stack_trace_ == NULL); |
| 2759 stack_trace_ = stack_trace; | 2766 stack_trace_ = stack_trace; |
| 2760 SignalPausedEvent(top_frame, bpt_hit); | 2767 SignalPausedEvent(top_frame, bpt_hit); |
| 2761 HandleSteppingRequest(stack_trace_); | 2768 // When we single step from a user breakpoint, our next stepping |
| 2769 // point will be at the exact same pc. Skip it. |
| 2770 HandleSteppingRequest(stack_trace_, true /* skip next step */); |
| 2762 stack_trace_ = NULL; | 2771 stack_trace_ = NULL; |
| 2763 if (cbpt->IsInternal()) { | 2772 if (cbpt->IsInternal()) { |
| 2764 RemoveInternalBreakpoints(); | 2773 RemoveInternalBreakpoints(); |
| 2765 } | 2774 } |
| 2766 | 2775 |
| 2767 // If any error occurred while in the debug message loop, return it here. | 2776 // If any error occurred while in the debug message loop, return it here. |
| 2768 const Error& error = | 2777 const Error& error = |
| 2769 Error::Handle(isolate_->object_store()->sticky_error()); | 2778 Error::Handle(isolate_->object_store()->sticky_error()); |
| 2770 isolate_->object_store()->clear_sticky_error(); | 2779 isolate_->object_store()->clear_sticky_error(); |
| 2771 return error.raw(); | 2780 return error.raw(); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3114 } | 3123 } |
| 3115 | 3124 |
| 3116 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt); | 3125 SendServiceBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt); |
| 3117 | 3126 |
| 3118 // Remove references from the current debugger pause event. | 3127 // Remove references from the current debugger pause event. |
| 3119 if (pause_event_ != NULL && | 3128 if (pause_event_ != NULL && |
| 3120 pause_event_->type() == DebuggerEvent::kBreakpointReached && | 3129 pause_event_->type() == DebuggerEvent::kBreakpointReached && |
| 3121 pause_event_->breakpoint() == curr_bpt) { | 3130 pause_event_->breakpoint() == curr_bpt) { |
| 3122 pause_event_->set_breakpoint(NULL); | 3131 pause_event_->set_breakpoint(NULL); |
| 3123 } | 3132 } |
| 3124 return; | 3133 break; |
| 3125 } | 3134 } |
| 3126 | 3135 |
| 3127 prev_bpt = curr_bpt; | 3136 prev_bpt = curr_bpt; |
| 3128 curr_bpt = curr_bpt->next(); | 3137 curr_bpt = curr_bpt->next(); |
| 3129 } | 3138 } |
| 3130 | 3139 |
| 3131 if (curr_loc->breakpoints() == NULL) { | 3140 if (curr_loc->breakpoints() == NULL) { |
| 3132 if (prev_loc == NULL) { | 3141 if (prev_loc == NULL) { |
| 3133 breakpoint_locations_ = curr_loc->next(); | 3142 breakpoint_locations_ = curr_loc->next(); |
| 3134 } else { | 3143 } else { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3253 } | 3262 } |
| 3254 | 3263 |
| 3255 | 3264 |
| 3256 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3265 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3257 ASSERT(bpt->next() == NULL); | 3266 ASSERT(bpt->next() == NULL); |
| 3258 bpt->set_next(code_breakpoints_); | 3267 bpt->set_next(code_breakpoints_); |
| 3259 code_breakpoints_ = bpt; | 3268 code_breakpoints_ = bpt; |
| 3260 } | 3269 } |
| 3261 | 3270 |
| 3262 } // namespace dart | 3271 } // namespace dart |
| OLD | NEW |