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 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 : isolate_(NULL), | 766 : isolate_(NULL), |
767 isolate_id_(ILLEGAL_ISOLATE_ID), | 767 isolate_id_(ILLEGAL_ISOLATE_ID), |
768 initialized_(false), | 768 initialized_(false), |
769 next_id_(1), | 769 next_id_(1), |
770 stack_trace_(NULL), | 770 stack_trace_(NULL), |
771 obj_cache_(NULL), | 771 obj_cache_(NULL), |
772 src_breakpoints_(NULL), | 772 src_breakpoints_(NULL), |
773 code_breakpoints_(NULL), | 773 code_breakpoints_(NULL), |
774 resume_action_(kContinue), | 774 resume_action_(kContinue), |
775 ignore_breakpoints_(false), | 775 ignore_breakpoints_(false), |
| 776 in_event_notification_(false), |
776 exc_pause_info_(kNoPauseOnExceptions) { | 777 exc_pause_info_(kNoPauseOnExceptions) { |
777 } | 778 } |
778 | 779 |
779 | 780 |
780 Debugger::~Debugger() { | 781 Debugger::~Debugger() { |
781 PortMap::ClosePort(isolate_id_); | 782 PortMap::ClosePort(isolate_id_); |
782 isolate_id_ = ILLEGAL_ISOLATE_ID; | 783 isolate_id_ = ILLEGAL_ISOLATE_ID; |
| 784 ASSERT(!in_event_notification_); |
783 ASSERT(src_breakpoints_ == NULL); | 785 ASSERT(src_breakpoints_ == NULL); |
784 ASSERT(code_breakpoints_ == NULL); | 786 ASSERT(code_breakpoints_ == NULL); |
785 ASSERT(stack_trace_ == NULL); | 787 ASSERT(stack_trace_ == NULL); |
786 ASSERT(obj_cache_ == NULL); | 788 ASSERT(obj_cache_ == NULL); |
787 } | 789 } |
788 | 790 |
789 | 791 |
790 void Debugger::Shutdown() { | 792 void Debugger::Shutdown() { |
791 while (src_breakpoints_ != NULL) { | 793 while (src_breakpoints_ != NULL) { |
792 SourceBreakpoint* bpt = src_breakpoints_; | 794 SourceBreakpoint* bpt = src_breakpoints_; |
(...skipping 15 matching lines...) Expand all Loading... |
808 const Library& library, | 810 const Library& library, |
809 const String& fname) { | 811 const String& fname) { |
810 ASSERT(!library.IsNull()); | 812 ASSERT(!library.IsNull()); |
811 const Object& object = Object::Handle(library.LookupObject(fname)); | 813 const Object& object = Object::Handle(library.LookupObject(fname)); |
812 if (!object.IsNull() && object.IsFunction()) { | 814 if (!object.IsNull() && object.IsFunction()) { |
813 return Function::Cast(object).raw(); | 815 return Function::Cast(object).raw(); |
814 } | 816 } |
815 return Function::null(); | 817 return Function::null(); |
816 } | 818 } |
817 | 819 |
| 820 void Debugger::SetSingleStep() { |
| 821 isolate_->set_single_step(true); |
| 822 resume_action_ = kSingleStep; |
| 823 } |
| 824 |
| 825 void Debugger::SetStepOver() { |
| 826 isolate_->set_single_step(false); |
| 827 resume_action_ = kStepOver; |
| 828 } |
| 829 |
| 830 void Debugger::SetStepOut() { |
| 831 isolate_->set_single_step(false); |
| 832 resume_action_ = kStepOut; |
| 833 } |
818 | 834 |
819 RawFunction* Debugger::ResolveFunction(const Library& library, | 835 RawFunction* Debugger::ResolveFunction(const Library& library, |
820 const String& class_name, | 836 const String& class_name, |
821 const String& function_name) { | 837 const String& function_name) { |
822 ASSERT(!library.IsNull()); | 838 ASSERT(!library.IsNull()); |
823 ASSERT(!class_name.IsNull()); | 839 ASSERT(!class_name.IsNull()); |
824 ASSERT(!function_name.IsNull()); | 840 ASSERT(!function_name.IsNull()); |
825 if (class_name.Length() == 0) { | 841 if (class_name.Length() == 0) { |
826 return ResolveLibraryFunction(library, function_name); | 842 return ResolveLibraryFunction(library, function_name); |
827 } | 843 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 if (function.HasOptimizedCode()) { | 878 if (function.HasOptimizedCode()) { |
863 function.SwitchToUnoptimizedCode(); | 879 function.SwitchToUnoptimizedCode(); |
864 } | 880 } |
865 } | 881 } |
866 } | 882 } |
867 } | 883 } |
868 } | 884 } |
869 | 885 |
870 | 886 |
871 void Debugger::InstrumentForStepping(const Function& target_function) { | 887 void Debugger::InstrumentForStepping(const Function& target_function) { |
| 888 if (target_function.is_native()) { |
| 889 // Can't instrument native functions. |
| 890 return; |
| 891 } |
872 if (!target_function.HasCode()) { | 892 if (!target_function.HasCode()) { |
873 Compiler::CompileFunction(target_function); | 893 Compiler::CompileFunction(target_function); |
874 // If there were any errors, ignore them silently and return without | 894 // If there were any errors, ignore them silently and return without |
875 // adding breakpoints to target. | 895 // adding breakpoints to target. |
876 if (!target_function.HasCode()) { | 896 if (!target_function.HasCode()) { |
877 return; | 897 return; |
878 } | 898 } |
879 } | 899 } |
880 DeoptimizeWorld(); | 900 DeoptimizeWorld(); |
881 ASSERT(!target_function.HasOptimizedCode()); | 901 ASSERT(!target_function.HasOptimizedCode()); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 } else if (frame->IsEntryFrame()) { | 979 } else if (frame->IsEntryFrame()) { |
960 ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext(); | 980 ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext(); |
961 callee_activation = NULL; | 981 callee_activation = NULL; |
962 } | 982 } |
963 frame = iterator.NextFrame(); | 983 frame = iterator.NextFrame(); |
964 } | 984 } |
965 return stack_trace; | 985 return stack_trace; |
966 } | 986 } |
967 | 987 |
968 | 988 |
| 989 ActivationFrame* Debugger::TopDartFrame() const { |
| 990 StackFrameIterator iterator(false); |
| 991 StackFrame* frame = iterator.NextFrame(); |
| 992 while ((frame != NULL) && !frame->IsDartFrame()) { |
| 993 frame = iterator.NextFrame(); |
| 994 } |
| 995 Code& code = Code::Handle(isolate_, frame->LookupDartCode()); |
| 996 ActivationFrame* activation = |
| 997 new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), code); |
| 998 return activation; |
| 999 } |
| 1000 |
| 1001 |
| 1002 DebuggerStackTrace* Debugger::StackTrace() { |
| 1003 return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace(); |
| 1004 } |
| 1005 |
| 1006 |
969 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { | 1007 void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) { |
970 ASSERT((pause_info == kNoPauseOnExceptions) || | 1008 ASSERT((pause_info == kNoPauseOnExceptions) || |
971 (pause_info == kPauseOnUnhandledExceptions) || | 1009 (pause_info == kPauseOnUnhandledExceptions) || |
972 (pause_info == kPauseOnAllExceptions)); | 1010 (pause_info == kPauseOnAllExceptions)); |
973 exc_pause_info_ = pause_info; | 1011 exc_pause_info_ = pause_info; |
974 } | 1012 } |
975 | 1013 |
976 | 1014 |
977 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() { | 1015 Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() { |
978 return exc_pause_info_; | 1016 return exc_pause_info_; |
(...skipping 21 matching lines...) Expand all Loading... |
1000 return false; | 1038 return false; |
1001 } | 1039 } |
1002 | 1040 |
1003 | 1041 |
1004 void Debugger::SignalExceptionThrown(const Instance& exc) { | 1042 void Debugger::SignalExceptionThrown(const Instance& exc) { |
1005 // We ignore this exception event when the VM is executing code invoked | 1043 // We ignore this exception event when the VM is executing code invoked |
1006 // by the debugger to evaluate variables values, when we see a nested | 1044 // by the debugger to evaluate variables values, when we see a nested |
1007 // breakpoint or exception event, or if the debugger is not | 1045 // breakpoint or exception event, or if the debugger is not |
1008 // interested in exception events. | 1046 // interested in exception events. |
1009 if (ignore_breakpoints_ || | 1047 if (ignore_breakpoints_ || |
1010 (stack_trace_ != NULL) || | 1048 in_event_notification_ || |
1011 (event_handler_ == NULL) || | 1049 (event_handler_ == NULL) || |
1012 (exc_pause_info_ == kNoPauseOnExceptions)) { | 1050 (exc_pause_info_ == kNoPauseOnExceptions)) { |
1013 return; | 1051 return; |
1014 } | 1052 } |
1015 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1053 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1016 if (!ShouldPauseOnException(stack_trace, exc)) { | 1054 if (!ShouldPauseOnException(stack_trace, exc)) { |
1017 return; | 1055 return; |
1018 } | 1056 } |
1019 ASSERT(stack_trace_ == NULL); | 1057 ASSERT(stack_trace_ == NULL); |
1020 stack_trace_ = stack_trace; | 1058 stack_trace_ = stack_trace; |
1021 ASSERT(obj_cache_ == NULL); | 1059 ASSERT(obj_cache_ == NULL); |
1022 obj_cache_ = new RemoteObjectCache(64); | 1060 obj_cache_ = new RemoteObjectCache(64); |
1023 DebuggerEvent event; | 1061 DebuggerEvent event; |
1024 event.type = kExceptionThrown; | 1062 event.type = kExceptionThrown; |
1025 event.exception = &exc; | 1063 event.exception = &exc; |
1026 ASSERT(event_handler_ != NULL); | |
1027 (*event_handler_)(&event); | 1064 (*event_handler_)(&event); |
1028 stack_trace_ = NULL; | 1065 stack_trace_ = NULL; |
1029 obj_cache_ = NULL; // Remote object cache is zone allocated. | 1066 obj_cache_ = NULL; // Remote object cache is zone allocated. |
1030 } | 1067 } |
1031 | 1068 |
1032 | 1069 |
1033 // Given a function and a token position range, return the best fit | 1070 // Given a function and a token position range, return the best fit |
1034 // token position to set a breakpoint. | 1071 // token position to set a breakpoint. |
1035 // If multiple possible breakpoint positions are within the given range, | 1072 // If multiple possible breakpoint positions are within the given range, |
1036 // the one with the lowest machine code address is picked. | 1073 // the one with the lowest machine code address is picked. |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 (fkind == RawFunction::kMethodExtractor) || | 1536 (fkind == RawFunction::kMethodExtractor) || |
1500 (fkind == RawFunction::kNoSuchMethodDispatcher)) { | 1537 (fkind == RawFunction::kNoSuchMethodDispatcher)) { |
1501 return false; | 1538 return false; |
1502 } | 1539 } |
1503 const Class& cls = Class::Handle(func.Owner()); | 1540 const Class& cls = Class::Handle(func.Owner()); |
1504 const Library& lib = Library::Handle(cls.library()); | 1541 const Library& lib = Library::Handle(cls.library()); |
1505 return lib.IsDebuggable(); | 1542 return lib.IsDebuggable(); |
1506 } | 1543 } |
1507 | 1544 |
1508 | 1545 |
| 1546 void Debugger::SignalPausedEvent(ActivationFrame* top_frame) { |
| 1547 resume_action_ = kContinue; |
| 1548 isolate_->set_single_step(false); |
| 1549 ASSERT(!in_event_notification_); |
| 1550 ASSERT(obj_cache_ == NULL); |
| 1551 in_event_notification_ = true; |
| 1552 obj_cache_ = new RemoteObjectCache(64); |
| 1553 DebuggerEvent event; |
| 1554 event.type = kBreakpointReached; |
| 1555 event.top_frame = top_frame; |
| 1556 (*event_handler_)(&event); |
| 1557 in_event_notification_ = false; |
| 1558 obj_cache_ = NULL; // Remote object cache is zone allocated. |
| 1559 } |
| 1560 |
| 1561 |
| 1562 void Debugger::SingleStepCallback() { |
| 1563 ASSERT(resume_action_ == kSingleStep); |
| 1564 ASSERT(isolate_->single_step()); |
| 1565 // We can't get here unless the debugger event handler enabled |
| 1566 // single stepping. |
| 1567 ASSERT(event_handler_ != NULL); |
| 1568 // Don't pause recursively. |
| 1569 if (in_event_notification_) return; |
| 1570 |
| 1571 // Check whether we are in a Dart function that the user is |
| 1572 // interested in. |
| 1573 ActivationFrame* frame = TopDartFrame(); |
| 1574 ASSERT(frame != NULL); |
| 1575 const Function& func = frame->function(); |
| 1576 if (!IsDebuggable(func)) { |
| 1577 return; |
| 1578 } |
| 1579 |
| 1580 if (FLAG_verbose_debug) { |
| 1581 OS::Print(">>> single step break at %s:%"Pd" (func %s token %"Pd")\n", |
| 1582 String::Handle(frame->SourceUrl()).ToCString(), |
| 1583 frame->LineNumber(), |
| 1584 String::Handle(frame->QualifiedFunctionName()).ToCString(), |
| 1585 frame->TokenPos()); |
| 1586 } |
| 1587 |
| 1588 stack_trace_ = CollectStackTrace(); |
| 1589 SignalPausedEvent(frame); |
| 1590 |
| 1591 RemoveInternalBreakpoints(); |
| 1592 if (resume_action_ == kStepOver) { |
| 1593 InstrumentForStepping(func); |
| 1594 } else if (resume_action_ == kStepOut) { |
| 1595 if (stack_trace_->Length() > 1) { |
| 1596 ActivationFrame* caller_frame = stack_trace_->ActivationFrameAt(1); |
| 1597 InstrumentForStepping(caller_frame->function()); |
| 1598 } |
| 1599 } |
| 1600 stack_trace_ = NULL; |
| 1601 } |
| 1602 |
| 1603 |
1509 void Debugger::SignalBpReached() { | 1604 void Debugger::SignalBpReached() { |
1510 // We ignore this breakpoint when the VM is executing code invoked | 1605 // We ignore this breakpoint when the VM is executing code invoked |
1511 // by the debugger to evaluate variables values, or when we see a nested | 1606 // by the debugger to evaluate variables values, or when we see a nested |
1512 // breakpoint or exception event. | 1607 // breakpoint or exception event. |
1513 if (ignore_breakpoints_ || (stack_trace_ != NULL)) { | 1608 if (ignore_breakpoints_ || in_event_notification_) { |
1514 return; | 1609 return; |
1515 } | 1610 } |
1516 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1611 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1517 ASSERT(stack_trace->Length() > 0); | 1612 ASSERT(stack_trace->Length() > 0); |
1518 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); | 1613 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); |
1519 ASSERT(top_frame != NULL); | 1614 ASSERT(top_frame != NULL); |
1520 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); | 1615 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); |
1521 ASSERT(bpt != NULL); | 1616 ASSERT(bpt != NULL); |
| 1617 |
| 1618 bool report_bp = true; |
| 1619 if (bpt->IsInternal() && !IsDebuggable(top_frame->function())) { |
| 1620 report_bp = false; |
| 1621 } |
1522 if (FLAG_verbose_debug) { | 1622 if (FLAG_verbose_debug) { |
1523 OS::Print(">>> hit %s breakpoint at %s:%"Pd" " | 1623 OS::Print(">>> %s %s breakpoint at %s:%"Pd" " |
1524 "(token %"Pd") (address %#"Px")\n", | 1624 "(token %"Pd") (address %#"Px")\n", |
| 1625 report_bp ? "hit" : "ignore", |
1525 bpt->IsInternal() ? "internal" : "user", | 1626 bpt->IsInternal() ? "internal" : "user", |
1526 String::Handle(bpt->SourceUrl()).ToCString(), | 1627 String::Handle(bpt->SourceUrl()).ToCString(), |
1527 bpt->LineNumber(), | 1628 bpt->LineNumber(), |
1528 bpt->token_pos(), | 1629 bpt->token_pos(), |
1529 top_frame->pc()); | 1630 top_frame->pc()); |
1530 } | 1631 } |
1531 | 1632 |
1532 resume_action_ = kContinue; | 1633 if (report_bp && (event_handler_ != NULL)) { |
1533 if (event_handler_ != NULL) { | |
1534 ASSERT(stack_trace_ == NULL); | |
1535 ASSERT(obj_cache_ == NULL); | |
1536 obj_cache_ = new RemoteObjectCache(64); | |
1537 stack_trace_ = stack_trace; | 1634 stack_trace_ = stack_trace; |
1538 DebuggerEvent event; | 1635 SignalPausedEvent(top_frame); |
1539 event.type = kBreakpointReached; | |
1540 ASSERT(stack_trace->Length() > 0); | |
1541 event.top_frame = stack_trace->ActivationFrameAt(0); | |
1542 (*event_handler_)(&event); | |
1543 stack_trace_ = NULL; | 1636 stack_trace_ = NULL; |
1544 obj_cache_ = NULL; // Remote object cache is zone allocated. | |
1545 } | 1637 } |
1546 | 1638 |
1547 Function& currently_instrumented_func = Function::Handle(); | |
1548 if (bpt->IsInternal()) { | |
1549 currently_instrumented_func = bpt->function(); | |
1550 } | |
1551 Function& func_to_instrument = Function::Handle(); | 1639 Function& func_to_instrument = Function::Handle(); |
1552 if (resume_action_ == kContinue) { | 1640 if (resume_action_ == kStepOver) { |
1553 // Nothing to do here, any potential instrumentation will be removed | |
1554 // below. | |
1555 } else if (resume_action_ == kStepOver) { | |
1556 func_to_instrument = bpt->function(); | |
1557 if (bpt->breakpoint_kind_ == PcDescriptors::kReturn) { | 1641 if (bpt->breakpoint_kind_ == PcDescriptors::kReturn) { |
1558 // If we are at the function return, do a StepOut action. | 1642 // Step over return is converted into a single step so we break at |
1559 if (stack_trace->Length() > 1) { | 1643 // the caller. |
1560 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); | 1644 SetSingleStep(); |
1561 func_to_instrument = caller_frame->function().raw(); | 1645 } else { |
1562 } | 1646 func_to_instrument = bpt->function(); |
1563 } | 1647 } |
1564 } else if (resume_action_ == kStepInto) { | 1648 } else if (resume_action_ == kStepOut) { |
1565 // If the call target is not debuggable, we treat StepInto like | |
1566 // a StepOver, that is we instrument the current function. | |
1567 if (bpt->breakpoint_kind_ == PcDescriptors::kIcCall) { | |
1568 func_to_instrument = bpt->function(); | |
1569 ICData& ic_data = ICData::Handle(); | |
1570 const Code& code = | |
1571 Code::Handle(Function::Handle(bpt->function_).unoptimized_code()); | |
1572 CodePatcher::GetInstanceCallAt(bpt->pc_, code, &ic_data); | |
1573 ArgumentsDescriptor | |
1574 args_descriptor(Array::Handle(ic_data.arguments_descriptor())); | |
1575 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); | |
1576 intptr_t num_args = args_descriptor.Count(); | |
1577 Instance& receiver = | |
1578 Instance::Handle(top_frame->GetInstanceCallReceiver(num_args)); | |
1579 Code& target_code = | |
1580 Code::Handle(ResolveCompileInstanceCallTarget(receiver, ic_data)); | |
1581 if (!target_code.IsNull()) { | |
1582 Function& callee = Function::Handle(target_code.function()); | |
1583 if (IsDebuggable(callee)) { | |
1584 func_to_instrument = callee.raw(); | |
1585 } | |
1586 } | |
1587 } else if (bpt->breakpoint_kind_ == PcDescriptors::kUnoptStaticCall) { | |
1588 func_to_instrument = bpt->function(); | |
1589 const Code& code = Code::Handle(func_to_instrument.CurrentCode()); | |
1590 ASSERT(!code.is_optimized()); | |
1591 const Function& callee = Function::Handle( | |
1592 CodePatcher::GetUnoptimizedStaticCallAt(bpt->pc_, code, NULL)); | |
1593 ASSERT(!callee.IsNull()); | |
1594 if (IsDebuggable(callee)) { | |
1595 func_to_instrument = callee.raw(); | |
1596 } | |
1597 } else if (bpt->breakpoint_kind_ == PcDescriptors::kClosureCall) { | |
1598 func_to_instrument = bpt->function(); | |
1599 const Code& code = Code::Handle(func_to_instrument.CurrentCode()); | |
1600 ArgumentsDescriptor args_desc(Array::Handle( | |
1601 CodePatcher::GetClosureArgDescAt(bpt->pc_, code))); | |
1602 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); | |
1603 const Object& receiver = | |
1604 Object::Handle(top_frame->GetClosureObject(args_desc.Count())); | |
1605 if (!receiver.IsNull()) { | |
1606 // Verify that the class of receiver is a closure class | |
1607 // by checking that signature_function() is not null. | |
1608 const Class& receiver_class = Class::Handle(receiver.clazz()); | |
1609 if (receiver_class.IsSignatureClass()) { | |
1610 Function& closure_func = | |
1611 Function::Handle(Closure::function(Instance::Cast(receiver))); | |
1612 if (IsDebuggable(closure_func)) { | |
1613 func_to_instrument = closure_func.raw(); | |
1614 } | |
1615 } | |
1616 // If the receiver is not a closure, then the runtime will attempt | |
1617 // to invoke the "call" method on the object if one exists. | |
1618 // TODO(hausner): find call method and intrument it for stepping. | |
1619 } | |
1620 } else if (bpt->breakpoint_kind_ == PcDescriptors::kRuntimeCall) { | |
1621 // This is just a call to the runtime, not Dart code. Stepping | |
1622 // into not possible, just treat like StepOver. | |
1623 func_to_instrument = bpt->function(); | |
1624 } else { | |
1625 ASSERT(bpt->breakpoint_kind_ == PcDescriptors::kReturn); | |
1626 // Treat like stepping out to caller. | |
1627 if (stack_trace->Length() > 1) { | |
1628 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); | |
1629 func_to_instrument = caller_frame->function().raw(); | |
1630 } | |
1631 } | |
1632 } else { | |
1633 ASSERT(resume_action_ == kStepOut); | |
1634 // Set stepping breakpoints in the caller. | |
1635 if (stack_trace->Length() > 1) { | 1649 if (stack_trace->Length() > 1) { |
1636 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); | 1650 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); |
1637 func_to_instrument = caller_frame->function().raw(); | 1651 func_to_instrument = caller_frame->function().raw(); |
1638 } | 1652 } |
| 1653 } else { |
| 1654 ASSERT((resume_action_ == kContinue) || (resume_action_ == kSingleStep)); |
| 1655 // Nothing to do here. Any potential instrumentation will be removed |
| 1656 // below. Single stepping is handled by the single step callback. |
1639 } | 1657 } |
1640 | 1658 |
1641 if (func_to_instrument.IsNull() || | 1659 if (func_to_instrument.IsNull() || |
1642 (func_to_instrument.raw() != currently_instrumented_func.raw())) { | 1660 (func_to_instrument.raw() != bpt->function())) { |
1643 RemoveInternalBreakpoints(); // *bpt is now invalid. | 1661 RemoveInternalBreakpoints(); // *bpt is now invalid. |
1644 if (!func_to_instrument.IsNull()) { | 1662 if (!func_to_instrument.IsNull()) { |
1645 InstrumentForStepping(func_to_instrument); | 1663 InstrumentForStepping(func_to_instrument); |
1646 } | 1664 } |
1647 } | 1665 } |
1648 } | 1666 } |
1649 | 1667 |
1650 | 1668 |
1651 void Debugger::Initialize(Isolate* isolate) { | 1669 void Debugger::Initialize(Isolate* isolate) { |
1652 if (initialized_) { | 1670 if (initialized_) { |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 } | 1855 } |
1838 | 1856 |
1839 | 1857 |
1840 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1858 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
1841 ASSERT(bpt->next() == NULL); | 1859 ASSERT(bpt->next() == NULL); |
1842 bpt->set_next(code_breakpoints_); | 1860 bpt->set_next(code_breakpoints_); |
1843 code_breakpoints_ = bpt; | 1861 code_breakpoints_ = bpt; |
1844 } | 1862 } |
1845 | 1863 |
1846 } // namespace dart | 1864 } // namespace dart |
OLD | NEW |