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 |