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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 | 288 |
289 | 289 |
290 void ActivationFrame::GetVarDescriptors() { | 290 void ActivationFrame::GetVarDescriptors() { |
291 if (var_descriptors_.IsNull()) { | 291 if (var_descriptors_.IsNull()) { |
292 var_descriptors_ = code().var_descriptors(); | 292 var_descriptors_ = code().var_descriptors(); |
293 ASSERT(!var_descriptors_.IsNull()); | 293 ASSERT(!var_descriptors_.IsNull()); |
294 } | 294 } |
295 } | 295 } |
296 | 296 |
297 | 297 |
| 298 bool ActivationFrame::IsDebuggable() const { |
| 299 return Debugger::IsDebuggable(function()); |
| 300 } |
| 301 |
| 302 |
298 // Calculate the context level at the current token index of the frame. | 303 // Calculate the context level at the current token index of the frame. |
299 intptr_t ActivationFrame::ContextLevel() { | 304 intptr_t ActivationFrame::ContextLevel() { |
300 if (context_level_ < 0 && !ctx_.IsNull()) { | 305 if (context_level_ < 0 && !ctx_.IsNull()) { |
301 ASSERT(!code_.is_optimized()); | 306 ASSERT(!code_.is_optimized()); |
302 context_level_ = 0; | 307 context_level_ = 0; |
303 intptr_t pc_desc_idx = PcDescIndex(); | 308 intptr_t pc_desc_idx = PcDescIndex(); |
304 // TODO(hausner): What to do if there is no descriptor entry | 309 // TODO(hausner): What to do if there is no descriptor entry |
305 // for the code position of the frame? For now say we are at context | 310 // for the code position of the frame? For now say we are at context |
306 // level 0. | 311 // level 0. |
307 if (pc_desc_idx < 0) { | 312 if (pc_desc_idx < 0) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 return Context::null(); | 375 return Context::null(); |
371 } | 376 } |
372 | 377 |
373 | 378 |
374 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( | 379 ActivationFrame* DebuggerStackTrace::GetHandlerFrame( |
375 const Instance& exc_obj) const { | 380 const Instance& exc_obj) const { |
376 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); | 381 ExceptionHandlers& handlers = ExceptionHandlers::Handle(); |
377 Array& handled_types = Array::Handle(); | 382 Array& handled_types = Array::Handle(); |
378 AbstractType& type = Type::Handle(); | 383 AbstractType& type = Type::Handle(); |
379 const TypeArguments& no_instantiator = TypeArguments::Handle(); | 384 const TypeArguments& no_instantiator = TypeArguments::Handle(); |
380 for (int frame_index = 0; frame_index < Length(); frame_index++) { | 385 for (int frame_index = 0; frame_index < UnfilteredLength(); frame_index++) { |
381 ActivationFrame* frame = trace_[frame_index]; | 386 ActivationFrame* frame = UnfilteredFrameAt(frame_index); |
382 intptr_t try_index = frame->TryIndex(); | 387 intptr_t try_index = frame->TryIndex(); |
383 if (try_index < 0) continue; | 388 if (try_index < 0) continue; |
384 handlers = frame->code().exception_handlers(); | 389 handlers = frame->code().exception_handlers(); |
385 ASSERT(!handlers.IsNull()); | 390 ASSERT(!handlers.IsNull()); |
386 intptr_t num_handlers_checked = 0; | 391 intptr_t num_handlers_checked = 0; |
387 while (try_index >= 0) { | 392 while (try_index >= 0) { |
388 // Detect circles in the exception handler data. | 393 // Detect circles in the exception handler data. |
389 num_handlers_checked++; | 394 num_handlers_checked++; |
390 ASSERT(num_handlers_checked <= handlers.Length()); | 395 ASSERT(num_handlers_checked <= handlers.Length()); |
391 handled_types = handlers.GetHandledTypes(try_index); | 396 handled_types = handlers.GetHandledTypes(try_index); |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line); | 578 OS::SNPrint(NULL, 0, kFormat, func_name, url.ToCString(), line); |
574 len++; // String terminator. | 579 len++; // String terminator. |
575 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 580 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
576 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); | 581 OS::SNPrint(chars, len, kFormat, func_name, url.ToCString(), line); |
577 return chars; | 582 return chars; |
578 } | 583 } |
579 | 584 |
580 | 585 |
581 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { | 586 void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { |
582 trace_.Add(frame); | 587 trace_.Add(frame); |
| 588 if (frame->IsDebuggable()) { |
| 589 user_trace_.Add(frame); |
| 590 } |
583 } | 591 } |
584 | 592 |
585 | 593 |
586 static bool IsSafePoint(PcDescriptors::Kind kind) { | 594 static bool IsSafePoint(PcDescriptors::Kind kind) { |
587 return ((kind == PcDescriptors::kIcCall) || | 595 return ((kind == PcDescriptors::kIcCall) || |
588 (kind == PcDescriptors::kOptStaticCall) || | 596 (kind == PcDescriptors::kOptStaticCall) || |
589 (kind == PcDescriptors::kUnoptStaticCall) || | 597 (kind == PcDescriptors::kUnoptStaticCall) || |
590 (kind == PcDescriptors::kClosureCall) || | 598 (kind == PcDescriptors::kClosureCall) || |
591 (kind == PcDescriptors::kReturn) || | 599 (kind == PcDescriptors::kReturn) || |
592 (kind == PcDescriptors::kRuntimeCall)); | 600 (kind == PcDescriptors::kRuntimeCall)); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
970 } | 978 } |
971 } | 979 } |
972 if (optimized_frame_found || code.is_optimized()) { | 980 if (optimized_frame_found || code.is_optimized()) { |
973 // Set context to null, to avoid returning bad context variable values. | 981 // Set context to null, to avoid returning bad context variable values. |
974 activation->SetContext(Context::Handle()); | 982 activation->SetContext(Context::Handle()); |
975 optimized_frame_found = true; | 983 optimized_frame_found = true; |
976 } else { | 984 } else { |
977 ASSERT(!ctx.IsNull()); | 985 ASSERT(!ctx.IsNull()); |
978 activation->SetContext(ctx); | 986 activation->SetContext(ctx); |
979 } | 987 } |
980 // Check if frame is a debuggable function. | 988 stack_trace->AddActivation(activation); |
981 if (IsDebuggable(activation->function())) { | |
982 stack_trace->AddActivation(activation); | |
983 } | |
984 callee_activation = activation; | 989 callee_activation = activation; |
985 // Get caller's context if this function saved it on entry. | 990 // Get caller's context if this function saved it on entry. |
986 ctx = activation->GetSavedEntryContext(ctx); | 991 ctx = activation->GetSavedEntryContext(ctx); |
987 } else if (frame->IsEntryFrame()) { | 992 } else if (frame->IsEntryFrame()) { |
988 ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext(); | 993 ctx = reinterpret_cast<EntryFrame*>(frame)->SavedContext(); |
989 callee_activation = NULL; | 994 callee_activation = NULL; |
990 } | 995 } |
991 } | 996 } |
992 return stack_trace; | 997 return stack_trace; |
993 } | 998 } |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 } | 1601 } |
1597 | 1602 |
1598 stack_trace_ = CollectStackTrace(); | 1603 stack_trace_ = CollectStackTrace(); |
1599 SignalPausedEvent(frame); | 1604 SignalPausedEvent(frame); |
1600 | 1605 |
1601 RemoveInternalBreakpoints(); | 1606 RemoveInternalBreakpoints(); |
1602 if (resume_action_ == kStepOver) { | 1607 if (resume_action_ == kStepOver) { |
1603 InstrumentForStepping(func); | 1608 InstrumentForStepping(func); |
1604 } else if (resume_action_ == kStepOut) { | 1609 } else if (resume_action_ == kStepOut) { |
1605 if (stack_trace_->Length() > 1) { | 1610 if (stack_trace_->Length() > 1) { |
1606 ActivationFrame* caller_frame = stack_trace_->ActivationFrameAt(1); | 1611 ActivationFrame* caller_frame = stack_trace_->FrameAt(1); |
1607 InstrumentForStepping(caller_frame->function()); | 1612 InstrumentForStepping(caller_frame->function()); |
1608 } | 1613 } |
1609 } | 1614 } |
1610 stack_trace_ = NULL; | 1615 stack_trace_ = NULL; |
1611 } | 1616 } |
1612 | 1617 |
1613 | 1618 |
1614 void Debugger::SignalBpReached() { | 1619 void Debugger::SignalBpReached() { |
1615 // We ignore this breakpoint when the VM is executing code invoked | 1620 // We ignore this breakpoint when the VM is executing code invoked |
1616 // by the debugger to evaluate variables values, or when we see a nested | 1621 // by the debugger to evaluate variables values, or when we see a nested |
1617 // breakpoint or exception event. | 1622 // breakpoint or exception event. |
1618 if (ignore_breakpoints_ || in_event_notification_) { | 1623 if (ignore_breakpoints_ || in_event_notification_) { |
1619 return; | 1624 return; |
1620 } | 1625 } |
1621 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1626 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
1622 ASSERT(stack_trace->Length() > 0); | 1627 ASSERT(stack_trace->UnfilteredLength() > 0); |
1623 ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0); | 1628 ActivationFrame* top_frame = stack_trace->UnfilteredFrameAt(0); |
1624 ASSERT(top_frame != NULL); | 1629 ASSERT(top_frame != NULL); |
1625 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); | 1630 CodeBreakpoint* bpt = GetCodeBreakpoint(top_frame->pc()); |
1626 ASSERT(bpt != NULL); | 1631 ASSERT(bpt != NULL); |
1627 | 1632 |
1628 bool report_bp = true; | 1633 bool report_bp = true; |
1629 if (bpt->IsInternal() && !IsDebuggable(top_frame->function())) { | 1634 if (bpt->IsInternal() && !IsDebuggable(top_frame->function())) { |
1630 report_bp = false; | 1635 report_bp = false; |
1631 } | 1636 } |
1632 if (FLAG_verbose_debug) { | 1637 if (FLAG_verbose_debug) { |
1633 OS::Print(">>> %s %s breakpoint at %s:%" Pd " " | 1638 OS::Print(">>> %s %s breakpoint at %s:%" Pd " " |
(...skipping 16 matching lines...) Expand all Loading... |
1650 if (resume_action_ == kStepOver) { | 1655 if (resume_action_ == kStepOver) { |
1651 if (bpt->breakpoint_kind_ == PcDescriptors::kReturn) { | 1656 if (bpt->breakpoint_kind_ == PcDescriptors::kReturn) { |
1652 // Step over return is converted into a single step so we break at | 1657 // Step over return is converted into a single step so we break at |
1653 // the caller. | 1658 // the caller. |
1654 SetSingleStep(); | 1659 SetSingleStep(); |
1655 } else { | 1660 } else { |
1656 func_to_instrument = bpt->function(); | 1661 func_to_instrument = bpt->function(); |
1657 } | 1662 } |
1658 } else if (resume_action_ == kStepOut) { | 1663 } else if (resume_action_ == kStepOut) { |
1659 if (stack_trace->Length() > 1) { | 1664 if (stack_trace->Length() > 1) { |
1660 ActivationFrame* caller_frame = stack_trace->ActivationFrameAt(1); | 1665 ActivationFrame* caller_frame = stack_trace->FrameAt(1); |
1661 func_to_instrument = caller_frame->function().raw(); | 1666 func_to_instrument = caller_frame->function().raw(); |
1662 } | 1667 } |
1663 } else { | 1668 } else { |
1664 ASSERT((resume_action_ == kContinue) || (resume_action_ == kSingleStep)); | 1669 ASSERT((resume_action_ == kContinue) || (resume_action_ == kSingleStep)); |
1665 // Nothing to do here. Any potential instrumentation will be removed | 1670 // Nothing to do here. Any potential instrumentation will be removed |
1666 // below. Single stepping is handled by the single step callback. | 1671 // below. Single stepping is handled by the single step callback. |
1667 } | 1672 } |
1668 | 1673 |
1669 if (func_to_instrument.IsNull() || | 1674 if (func_to_instrument.IsNull() || |
1670 (func_to_instrument.raw() != bpt->function())) { | 1675 (func_to_instrument.raw() != bpt->function())) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 } | 1870 } |
1866 | 1871 |
1867 | 1872 |
1868 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 1873 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
1869 ASSERT(bpt->next() == NULL); | 1874 ASSERT(bpt->next() == NULL); |
1870 bpt->set_next(code_breakpoints_); | 1875 bpt->set_next(code_breakpoints_); |
1871 code_breakpoints_ = bpt; | 1876 code_breakpoints_ = bpt; |
1872 } | 1877 } |
1873 | 1878 |
1874 } // namespace dart | 1879 } // namespace dart |
OLD | NEW |