| 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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 desc_indices_(8), | 251 desc_indices_(8), |
| 252 pc_desc_(PcDescriptors::ZoneHandle()) { | 252 pc_desc_(PcDescriptors::ZoneHandle()) { |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 void DebuggerEvent::UpdateTimestamp() { | 256 void DebuggerEvent::UpdateTimestamp() { |
| 257 timestamp_ = OS::GetCurrentTimeMillis(); | 257 timestamp_ = OS::GetCurrentTimeMillis(); |
| 258 } | 258 } |
| 259 | 259 |
| 260 | 260 |
| 261 bool Debugger::HasEventHandler() { | 261 bool Debugger::HasAnyEventHandler() { |
| 262 return ((event_handler_ != NULL) || | 262 return ((event_handler_ != NULL) || |
| 263 Service::isolate_stream.enabled() || | 263 Service::isolate_stream.enabled() || |
| 264 Service::debug_stream.enabled()); | 264 Service::debug_stream.enabled()); |
| 265 } | 265 } |
| 266 | 266 |
| 267 | 267 |
| 268 bool Debugger::HasDebugEventHandler() { |
| 269 return ((event_handler_ != NULL) || |
| 270 Service::debug_stream.enabled()); |
| 271 } |
| 272 |
| 273 |
| 268 static bool ServiceNeedsDebuggerEvent(DebuggerEvent::EventType type) { | 274 static bool ServiceNeedsDebuggerEvent(DebuggerEvent::EventType type) { |
| 269 switch (type) { | 275 switch (type) { |
| 270 case DebuggerEvent::kBreakpointResolved: | 276 case DebuggerEvent::kBreakpointResolved: |
| 271 // kBreakpointResolved events are handled differently in the vm | 277 // kBreakpointResolved events are handled differently in the vm |
| 272 // service, so suppress them here. | 278 // service, so suppress them here. |
| 273 return false; | 279 return false; |
| 274 | 280 |
| 275 case DebuggerEvent::kBreakpointReached: | 281 case DebuggerEvent::kBreakpointReached: |
| 276 case DebuggerEvent::kExceptionThrown: | 282 case DebuggerEvent::kExceptionThrown: |
| 277 case DebuggerEvent::kIsolateInterrupted: | 283 case DebuggerEvent::kIsolateInterrupted: |
| 278 return Service::debug_stream.enabled(); | 284 return Service::debug_stream.enabled(); |
| 279 | 285 |
| 280 case DebuggerEvent::kIsolateCreated: | 286 case DebuggerEvent::kIsolateCreated: |
| 281 case DebuggerEvent::kIsolateShutdown: | 287 case DebuggerEvent::kIsolateShutdown: |
| 282 return Service::isolate_stream.enabled(); | 288 return Service::isolate_stream.enabled(); |
| 283 | 289 |
| 284 default: | 290 default: |
| 285 UNREACHABLE(); | 291 UNREACHABLE(); |
| 286 return false; | 292 return false; |
| 287 } | 293 } |
| 288 } | 294 } |
| 289 | 295 |
| 290 | 296 |
| 291 void Debugger::InvokeEventHandler(DebuggerEvent* event) { | 297 void Debugger::InvokeEventHandler(DebuggerEvent* event) { |
| 292 ASSERT(HasEventHandler()); | |
| 293 | |
| 294 // Give the event to the Service first, as the debugger event handler | 298 // Give the event to the Service first, as the debugger event handler |
| 295 // may go into a message loop and the Service will not. | 299 // may go into a message loop and the Service will not. |
| 296 // | 300 // |
| 297 // kBreakpointResolved events are handled differently in the vm | 301 // kBreakpointResolved events are handled differently in the vm |
| 298 // service, so suppress them here. | 302 // service, so suppress them here. |
| 299 if (ServiceNeedsDebuggerEvent(event->type())) { | 303 if (ServiceNeedsDebuggerEvent(event->type())) { |
| 300 ServiceEvent service_event(event); | 304 ServiceEvent service_event(event); |
| 301 Service::HandleEvent(&service_event); | 305 Service::HandleEvent(&service_event); |
| 302 } | 306 } |
| 303 | 307 |
| 304 if (FLAG_steal_breakpoints && event->IsPauseEvent()) { | 308 if ((FLAG_steal_breakpoints || (event_handler_ == NULL)) && |
| 309 event->IsPauseEvent()) { |
| 305 // We allow the embedder's default breakpoint handler to be overridden. | 310 // We allow the embedder's default breakpoint handler to be overridden. |
| 306 isolate_->PauseEventHandler(); | 311 isolate_->PauseEventHandler(); |
| 307 } else if (event_handler_ != NULL) { | 312 } else if (event_handler_ != NULL) { |
| 308 (*event_handler_)(event); | 313 (*event_handler_)(event); |
| 309 } | 314 } |
| 310 | 315 |
| 311 if (ServiceNeedsDebuggerEvent(event->type()) && event->IsPauseEvent()) { | 316 if (ServiceNeedsDebuggerEvent(event->type()) && event->IsPauseEvent()) { |
| 312 // If we were paused, notify the service that we have resumed. | 317 // If we were paused, notify the service that we have resumed. |
| 313 const Error& error = | 318 const Error& error = |
| 314 Error::Handle(isolate_->object_store()->sticky_error()); | 319 Error::Handle(isolate_->object_store()->sticky_error()); |
| 315 ASSERT(error.IsNull() || error.IsUnwindError()); | 320 ASSERT(error.IsNull() || error.IsUnwindError()); |
| 316 | 321 |
| 317 // Only send a resume event when the isolate is not unwinding. | 322 // Only send a resume event when the isolate is not unwinding. |
| 318 if (!error.IsUnwindError()) { | 323 if (!error.IsUnwindError()) { |
| 319 ServiceEvent service_event(event->isolate(), ServiceEvent::kResume); | 324 ServiceEvent service_event(event->isolate(), ServiceEvent::kResume); |
| 320 service_event.set_top_frame(event->top_frame()); | 325 service_event.set_top_frame(event->top_frame()); |
| 321 Service::HandleEvent(&service_event); | 326 Service::HandleEvent(&service_event); |
| 322 } | 327 } |
| 323 } | 328 } |
| 324 } | 329 } |
| 325 | 330 |
| 326 | 331 |
| 327 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { | 332 void Debugger::SignalIsolateEvent(DebuggerEvent::EventType type) { |
| 328 if (HasEventHandler()) { | 333 if (HasAnyEventHandler()) { |
| 329 DebuggerEvent event(isolate_, type); | 334 DebuggerEvent event(isolate_, type); |
| 330 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); | 335 ASSERT(event.isolate_id() != ILLEGAL_ISOLATE_ID); |
| 331 if (type == DebuggerEvent::kIsolateInterrupted) { | 336 if (type == DebuggerEvent::kIsolateInterrupted) { |
| 332 DebuggerStackTrace* trace = CollectStackTrace(); | 337 DebuggerStackTrace* trace = CollectStackTrace(); |
| 333 if (trace->Length() > 0) { | 338 if (trace->Length() > 0) { |
| 334 event.set_top_frame(trace->FrameAt(0)); | 339 event.set_top_frame(trace->FrameAt(0)); |
| 335 } | 340 } |
| 336 ASSERT(stack_trace_ == NULL); | 341 ASSERT(stack_trace_ == NULL); |
| 337 stack_trace_ = trace; | 342 stack_trace_ = trace; |
| 338 resume_action_ = kContinue; | 343 resume_action_ = kContinue; |
| 339 Pause(&event); | 344 Pause(&event); |
| 340 HandleSteppingRequest(trace); | 345 HandleSteppingRequest(trace); |
| 341 stack_trace_ = NULL; | 346 stack_trace_ = NULL; |
| 342 } else { | 347 } else { |
| 343 InvokeEventHandler(&event); | 348 InvokeEventHandler(&event); |
| 344 } | 349 } |
| 345 } | 350 } |
| 346 } | 351 } |
| 347 | 352 |
| 348 | 353 |
| 349 RawError* Debugger::SignalIsolateInterrupted() { | 354 RawError* Debugger::SignalIsolateInterrupted() { |
| 350 if (HasEventHandler()) { | 355 if (HasDebugEventHandler()) { |
| 351 SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); | 356 SignalIsolateEvent(DebuggerEvent::kIsolateInterrupted); |
| 352 } | 357 } |
| 353 Dart_IsolateInterruptCallback callback = isolate_->InterruptCallback(); | |
| 354 if (callback != NULL) { | |
| 355 if (!(*callback)()) { | |
| 356 if (FLAG_trace_isolates) { | |
| 357 OS::Print("[!] Embedder api: terminating isolate:\n" | |
| 358 "\tisolate: %s\n", isolate_->name()); | |
| 359 } | |
| 360 const String& msg = | |
| 361 String::Handle(String::New("isolate terminated by embedder")); | |
| 362 return UnwindError::New(msg); | |
| 363 } | |
| 364 } | |
| 365 | 358 |
| 366 // If any error occurred while in the debug message loop, return it here. | 359 // If any error occurred while in the debug message loop, return it here. |
| 367 const Error& error = | 360 const Error& error = |
| 368 Error::Handle(isolate_->object_store()->sticky_error()); | 361 Error::Handle(isolate_->object_store()->sticky_error()); |
| 369 ASSERT(error.IsNull() || error.IsUnwindError()); | 362 ASSERT(error.IsNull() || error.IsUnwindError()); |
| 370 isolate_->object_store()->clear_sticky_error(); | 363 isolate_->object_store()->clear_sticky_error(); |
| 371 return error.raw(); | 364 return error.raw(); |
| 372 } | 365 } |
| 373 | 366 |
| 374 | 367 |
| (...skipping 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 function ^= closures.At(pos); | 1397 function ^= closures.At(pos); |
| 1405 ASSERT(!function.IsNull()); | 1398 ASSERT(!function.IsNull()); |
| 1406 if (function.HasOptimizedCode()) { | 1399 if (function.HasOptimizedCode()) { |
| 1407 function.SwitchToUnoptimizedCode(); | 1400 function.SwitchToUnoptimizedCode(); |
| 1408 } | 1401 } |
| 1409 } | 1402 } |
| 1410 } | 1403 } |
| 1411 | 1404 |
| 1412 | 1405 |
| 1413 void Debugger::SignalBpResolved(Breakpoint* bpt) { | 1406 void Debugger::SignalBpResolved(Breakpoint* bpt) { |
| 1414 if (HasEventHandler() && !bpt->IsSingleShot()) { | 1407 if (HasDebugEventHandler() && !bpt->IsSingleShot()) { |
| 1415 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); | 1408 DebuggerEvent event(isolate_, DebuggerEvent::kBreakpointResolved); |
| 1416 event.set_breakpoint(bpt); | 1409 event.set_breakpoint(bpt); |
| 1417 InvokeEventHandler(&event); | 1410 InvokeEventHandler(&event); |
| 1418 } | 1411 } |
| 1419 } | 1412 } |
| 1420 | 1413 |
| 1421 | 1414 |
| 1422 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, | 1415 ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate, |
| 1423 uword pc, | 1416 uword pc, |
| 1424 StackFrame* frame, | 1417 StackFrame* frame, |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 } | 1618 } |
| 1626 | 1619 |
| 1627 | 1620 |
| 1628 void Debugger::SignalExceptionThrown(const Instance& exc) { | 1621 void Debugger::SignalExceptionThrown(const Instance& exc) { |
| 1629 // We ignore this exception event when the VM is executing code invoked | 1622 // We ignore this exception event when the VM is executing code invoked |
| 1630 // by the debugger to evaluate variables values, when we see a nested | 1623 // by the debugger to evaluate variables values, when we see a nested |
| 1631 // breakpoint or exception event, or if the debugger is not | 1624 // breakpoint or exception event, or if the debugger is not |
| 1632 // interested in exception events. | 1625 // interested in exception events. |
| 1633 if (ignore_breakpoints_ || | 1626 if (ignore_breakpoints_ || |
| 1634 IsPaused() || | 1627 IsPaused() || |
| 1635 (!HasEventHandler()) || | 1628 (!HasDebugEventHandler()) || |
| 1636 (exc_pause_info_ == kNoPauseOnExceptions)) { | 1629 (exc_pause_info_ == kNoPauseOnExceptions)) { |
| 1637 return; | 1630 return; |
| 1638 } | 1631 } |
| 1639 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 1632 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 1640 if (!ShouldPauseOnException(stack_trace, exc)) { | 1633 if (!ShouldPauseOnException(stack_trace, exc)) { |
| 1641 return; | 1634 return; |
| 1642 } | 1635 } |
| 1643 DebuggerEvent event(isolate_, DebuggerEvent::kExceptionThrown); | 1636 DebuggerEvent event(isolate_, DebuggerEvent::kExceptionThrown); |
| 1644 event.set_exception(&exc); | 1637 event.set_exception(&exc); |
| 1645 ASSERT(stack_trace->Length() > 0); | 1638 ASSERT(stack_trace->Length() > 0); |
| (...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2609 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { | 2602 (iter.CurrentLiteral() == Symbols::YieldKw().raw()))) { |
| 2610 event.set_at_async_jump(true); | 2603 event.set_at_async_jump(true); |
| 2611 } | 2604 } |
| 2612 } | 2605 } |
| 2613 Pause(&event); | 2606 Pause(&event); |
| 2614 } | 2607 } |
| 2615 | 2608 |
| 2616 | 2609 |
| 2617 RawError* Debugger::DebuggerStepCallback() { | 2610 RawError* Debugger::DebuggerStepCallback() { |
| 2618 ASSERT(isolate_->single_step()); | 2611 ASSERT(isolate_->single_step()); |
| 2619 // We can't get here unless the debugger event handler enabled | |
| 2620 // single stepping. | |
| 2621 ASSERT(HasEventHandler()); | |
| 2622 // Don't pause recursively. | 2612 // Don't pause recursively. |
| 2623 if (IsPaused()) { | 2613 if (IsPaused()) { |
| 2624 return Error::null(); | 2614 return Error::null(); |
| 2625 } | 2615 } |
| 2626 | 2616 |
| 2627 // Check whether we are in a Dart function that the user is | 2617 // Check whether we are in a Dart function that the user is |
| 2628 // interested in. If we saved the frame pointer of a stack frame | 2618 // interested in. If we saved the frame pointer of a stack frame |
| 2629 // the user is interested in, we ignore the single step if we are | 2619 // the user is interested in, we ignore the single step if we are |
| 2630 // in a callee of that frame. Note that we assume that the stack | 2620 // in a callee of that frame. Note that we assume that the stack |
| 2631 // grows towards lower addresses. | 2621 // grows towards lower addresses. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2679 Error::Handle(isolate_->object_store()->sticky_error()); | 2669 Error::Handle(isolate_->object_store()->sticky_error()); |
| 2680 isolate_->object_store()->clear_sticky_error(); | 2670 isolate_->object_store()->clear_sticky_error(); |
| 2681 return error.raw(); | 2671 return error.raw(); |
| 2682 } | 2672 } |
| 2683 | 2673 |
| 2684 | 2674 |
| 2685 RawError* Debugger::SignalBpReached() { | 2675 RawError* Debugger::SignalBpReached() { |
| 2686 // We ignore this breakpoint when the VM is executing code invoked | 2676 // We ignore this breakpoint when the VM is executing code invoked |
| 2687 // by the debugger to evaluate variables values, or when we see a nested | 2677 // by the debugger to evaluate variables values, or when we see a nested |
| 2688 // breakpoint or exception event. | 2678 // breakpoint or exception event. |
| 2689 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2679 if (ignore_breakpoints_ || IsPaused()) { |
| 2690 return Error::null(); | 2680 return Error::null(); |
| 2691 } | 2681 } |
| 2692 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2682 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 2693 ASSERT(stack_trace->Length() > 0); | 2683 ASSERT(stack_trace->Length() > 0); |
| 2694 ActivationFrame* top_frame = stack_trace->FrameAt(0); | 2684 ActivationFrame* top_frame = stack_trace->FrameAt(0); |
| 2695 ASSERT(top_frame != NULL); | 2685 ASSERT(top_frame != NULL); |
| 2696 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); | 2686 CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc()); |
| 2697 ASSERT(cbpt != NULL); | 2687 ASSERT(cbpt != NULL); |
| 2698 | 2688 |
| 2699 BreakpointLocation* bpt_location = cbpt->bpt_location_; | 2689 BreakpointLocation* bpt_location = cbpt->bpt_location_; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2768 Error::Handle(isolate_->object_store()->sticky_error()); | 2758 Error::Handle(isolate_->object_store()->sticky_error()); |
| 2769 isolate_->object_store()->clear_sticky_error(); | 2759 isolate_->object_store()->clear_sticky_error(); |
| 2770 return error.raw(); | 2760 return error.raw(); |
| 2771 } | 2761 } |
| 2772 | 2762 |
| 2773 | 2763 |
| 2774 void Debugger::BreakHere(const String& msg) { | 2764 void Debugger::BreakHere(const String& msg) { |
| 2775 // We ignore this breakpoint when the VM is executing code invoked | 2765 // We ignore this breakpoint when the VM is executing code invoked |
| 2776 // by the debugger to evaluate variables values, or when we see a nested | 2766 // by the debugger to evaluate variables values, or when we see a nested |
| 2777 // breakpoint or exception event. | 2767 // breakpoint or exception event. |
| 2778 if (ignore_breakpoints_ || IsPaused() || !HasEventHandler()) { | 2768 if (ignore_breakpoints_ || IsPaused()) { |
| 2779 return; | 2769 return; |
| 2780 } | 2770 } |
| 2781 | 2771 |
| 2772 if (!HasDebugEventHandler()) { |
| 2773 OS::Print("Hit debugger!"); |
| 2774 } |
| 2775 |
| 2782 DebuggerStackTrace* stack_trace = CollectStackTrace(); | 2776 DebuggerStackTrace* stack_trace = CollectStackTrace(); |
| 2783 ASSERT(stack_trace->Length() > 0); | 2777 ASSERT(stack_trace->Length() > 0); |
| 2784 ASSERT(stack_trace_ == NULL); | 2778 ASSERT(stack_trace_ == NULL); |
| 2785 stack_trace_ = stack_trace; | 2779 stack_trace_ = stack_trace; |
| 2786 | 2780 |
| 2787 // TODO(johnmccutchan): Send |msg| to Observatory. | 2781 // TODO(johnmccutchan): Send |msg| to Observatory. |
| 2788 | 2782 |
| 2789 // We are in the native call to Debugger_breakHere or Debugger_breakHereIf, | 2783 // We are in the native call to Debugger_breakHere or Debugger_breakHereIf, |
| 2790 // the developer gets a better experience by not seeing this call. To | 2784 // the developer gets a better experience by not seeing this call. To |
| 2791 // accomplish this, we continue execution until the call exits (step out). | 2785 // accomplish this, we continue execution until the call exits (step out). |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3248 } | 3242 } |
| 3249 | 3243 |
| 3250 | 3244 |
| 3251 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { | 3245 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { |
| 3252 ASSERT(bpt->next() == NULL); | 3246 ASSERT(bpt->next() == NULL); |
| 3253 bpt->set_next(code_breakpoints_); | 3247 bpt->set_next(code_breakpoints_); |
| 3254 code_breakpoints_ = bpt; | 3248 code_breakpoints_ = bpt; |
| 3255 } | 3249 } |
| 3256 | 3250 |
| 3257 } // namespace dart | 3251 } // namespace dart |
| OLD | NEW |