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 #ifndef VM_DEBUGGER_H_ | 5 #ifndef VM_DEBUGGER_H_ |
6 #define VM_DEBUGGER_H_ | 6 #define VM_DEBUGGER_H_ |
7 | 7 |
8 #include "include/dart_tools_api.h" | 8 #include "include/dart_tools_api.h" |
9 | 9 |
10 #include "vm/object.h" | 10 #include "vm/object.h" |
11 #include "vm/port.h" | 11 #include "vm/port.h" |
| 12 #include "vm/service_event.h" |
12 | 13 |
13 namespace dart { | 14 namespace dart { |
14 | 15 |
15 class CodeBreakpoint; | 16 class CodeBreakpoint; |
16 class Isolate; | 17 class Isolate; |
17 class JSONArray; | 18 class JSONArray; |
18 class JSONStream; | 19 class JSONStream; |
19 class ObjectPointerVisitor; | 20 class ObjectPointerVisitor; |
20 class RemoteObjectCache; | 21 class RemoteObjectCache; |
21 class BreakpointLocation; | 22 class BreakpointLocation; |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 | 363 |
363 private: | 364 private: |
364 void AddActivation(ActivationFrame* frame); | 365 void AddActivation(ActivationFrame* frame); |
365 ZoneGrowableArray<ActivationFrame*> trace_; | 366 ZoneGrowableArray<ActivationFrame*> trace_; |
366 | 367 |
367 friend class Debugger; | 368 friend class Debugger; |
368 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace); | 369 DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace); |
369 }; | 370 }; |
370 | 371 |
371 | 372 |
372 class DebuggerEvent { | |
373 public: | |
374 enum EventType { | |
375 kBreakpointReached = 1, | |
376 kBreakpointResolved = 2, | |
377 kExceptionThrown = 3, | |
378 kIsolateCreated = 4, | |
379 kIsolateShutdown = 5, | |
380 kIsolateInterrupted = 6, | |
381 }; | |
382 | |
383 explicit DebuggerEvent(Isolate* isolate, EventType event_type) | |
384 : isolate_(isolate), | |
385 type_(event_type), | |
386 top_frame_(NULL), | |
387 breakpoint_(NULL), | |
388 exception_(NULL), | |
389 async_continuation_(NULL), | |
390 at_async_jump_(false), | |
391 timestamp_(-1) {} | |
392 | |
393 Isolate* isolate() const { return isolate_; } | |
394 | |
395 EventType type() const { return type_; } | |
396 | |
397 bool IsPauseEvent() const { | |
398 return (type_ == kBreakpointReached || | |
399 type_ == kIsolateInterrupted || | |
400 type_ == kExceptionThrown); | |
401 } | |
402 | |
403 ActivationFrame* top_frame() const { | |
404 ASSERT(IsPauseEvent()); | |
405 return top_frame_; | |
406 } | |
407 void set_top_frame(ActivationFrame* frame) { | |
408 ASSERT(IsPauseEvent()); | |
409 top_frame_ = frame; | |
410 } | |
411 | |
412 Breakpoint* breakpoint() const { | |
413 ASSERT(type_ == kBreakpointReached || type_ == kBreakpointResolved); | |
414 return breakpoint_; | |
415 } | |
416 void set_breakpoint(Breakpoint* bpt) { | |
417 ASSERT(type_ == kBreakpointReached || type_ == kBreakpointResolved); | |
418 breakpoint_ = bpt; | |
419 } | |
420 | |
421 const Object* exception() const { | |
422 ASSERT(type_ == kExceptionThrown); | |
423 return exception_; | |
424 } | |
425 void set_exception(const Object* exception) { | |
426 ASSERT(type_ == kExceptionThrown); | |
427 exception_ = exception; | |
428 } | |
429 | |
430 const Object* async_continuation() const { | |
431 ASSERT(type_ == kBreakpointReached); | |
432 return async_continuation_; | |
433 } | |
434 void set_async_continuation(const Object* closure) { | |
435 ASSERT(type_ == kBreakpointReached); | |
436 async_continuation_ = closure; | |
437 } | |
438 | |
439 bool at_async_jump() const { | |
440 return at_async_jump_; | |
441 } | |
442 void set_at_async_jump(bool value) { | |
443 at_async_jump_ = value; | |
444 } | |
445 | |
446 Dart_Port isolate_id() const { | |
447 return isolate_->main_port(); | |
448 } | |
449 | |
450 void UpdateTimestamp(); | |
451 | |
452 int64_t timestamp() const { | |
453 return timestamp_; | |
454 } | |
455 | |
456 private: | |
457 Isolate* isolate_; | |
458 EventType type_; | |
459 ActivationFrame* top_frame_; | |
460 Breakpoint* breakpoint_; | |
461 const Object* exception_; | |
462 const Object* async_continuation_; | |
463 bool at_async_jump_; | |
464 int64_t timestamp_; | |
465 }; | |
466 | |
467 | |
468 class Debugger { | 373 class Debugger { |
469 public: | 374 public: |
470 typedef void EventHandler(DebuggerEvent* event); | 375 typedef void EventHandler(ServiceEvent* event); |
471 | 376 |
472 Debugger(); | 377 Debugger(); |
473 ~Debugger(); | 378 ~Debugger(); |
474 | 379 |
475 void Initialize(Isolate* isolate); | 380 void Initialize(Isolate* isolate); |
476 void NotifyIsolateCreated(); | 381 void NotifyIsolateCreated(); |
477 void Shutdown(); | 382 void Shutdown(); |
478 | 383 |
479 void NotifyCompilation(const Function& func); | 384 void NotifyCompilation(const Function& func); |
480 void NotifyDoneLoading(); | 385 void NotifyDoneLoading(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 // Put the isolate into single stepping mode when Dart code next runs. | 423 // Put the isolate into single stepping mode when Dart code next runs. |
519 // | 424 // |
520 // This is used by the vm service to allow the user to step while | 425 // This is used by the vm service to allow the user to step while |
521 // paused at isolate start. | 426 // paused at isolate start. |
522 void EnterSingleStepMode(); | 427 void EnterSingleStepMode(); |
523 | 428 |
524 // Indicates why the debugger is currently paused. If the debugger | 429 // Indicates why the debugger is currently paused. If the debugger |
525 // is not paused, this returns NULL. Note that the debugger can be | 430 // is not paused, this returns NULL. Note that the debugger can be |
526 // paused for breakpoints, isolate interruption, and (sometimes) | 431 // paused for breakpoints, isolate interruption, and (sometimes) |
527 // exceptions. | 432 // exceptions. |
528 const DebuggerEvent* PauseEvent() const { return pause_event_; } | 433 const ServiceEvent* PauseEvent() const { return pause_event_; } |
529 | 434 |
530 void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info); | 435 void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info); |
531 Dart_ExceptionPauseInfo GetExceptionPauseInfo() const; | 436 Dart_ExceptionPauseInfo GetExceptionPauseInfo() const; |
532 | 437 |
533 void VisitObjectPointers(ObjectPointerVisitor* visitor); | 438 void VisitObjectPointers(ObjectPointerVisitor* visitor); |
534 | 439 |
535 // Called from Runtime when a breakpoint in Dart code is reached. | 440 // Called from Runtime when a breakpoint in Dart code is reached. |
536 void BreakpointCallback(); | 441 void BreakpointCallback(); |
537 | 442 |
538 // Returns true if there is at least one breakpoint set in func or code. | 443 // Returns true if there is at least one breakpoint set in func or code. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 | 478 |
574 // Utility functions. | 479 // Utility functions. |
575 static const char* QualifiedFunctionName(const Function& func); | 480 static const char* QualifiedFunctionName(const Function& func); |
576 | 481 |
577 RawObject* GetInstanceField(const Class& cls, | 482 RawObject* GetInstanceField(const Class& cls, |
578 const String& field_name, | 483 const String& field_name, |
579 const Instance& object); | 484 const Instance& object); |
580 RawObject* GetStaticField(const Class& cls, | 485 RawObject* GetStaticField(const Class& cls, |
581 const String& field_name); | 486 const String& field_name); |
582 | 487 |
583 RawError* SignalBpReached(); | 488 // Pause execution for a breakpoint. Called from generated code. |
584 RawError* DebuggerStepCallback(); | 489 RawError* PauseBreakpoint(); |
585 RawError* SignalIsolateInterrupted(); | |
586 | 490 |
587 void BreakHere(const String& msg); | 491 // Pause execution due to stepping. Called from generated code. |
| 492 RawError* PauseStepping(); |
588 | 493 |
589 void SignalExceptionThrown(const Instance& exc); | 494 // Pause execution due to isolate interrupt. |
590 void SignalIsolateEvent(DebuggerEvent::EventType type); | 495 RawError* PauseInterrupted(); |
| 496 |
| 497 // Pause execution due to an uncaught exception. |
| 498 void PauseException(const Instance& exc); |
| 499 |
| 500 // Pause execution due to a call to the debugger() function from |
| 501 // Dart. |
| 502 void PauseDeveloper(const String& msg); |
591 | 503 |
592 RawCode* GetPatchedStubAddress(uword breakpoint_address); | 504 RawCode* GetPatchedStubAddress(uword breakpoint_address); |
593 | 505 |
594 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const; | 506 void PrintBreakpointsToJSONArray(JSONArray* jsarr) const; |
595 void PrintSettingsToJSONObject(JSONObject* jsobj) const; | 507 void PrintSettingsToJSONObject(JSONObject* jsobj) const; |
596 | 508 |
597 static bool IsDebuggable(const Function& func); | 509 static bool IsDebuggable(const Function& func); |
598 | 510 |
599 intptr_t limitBreakpointId() { return next_id_; } | 511 intptr_t limitBreakpointId() { return next_id_; } |
600 | 512 |
601 private: | 513 private: |
602 enum ResumeAction { | 514 enum ResumeAction { |
603 kContinue, | 515 kContinue, |
604 kStepOver, | 516 kStepOver, |
605 kStepOut, | 517 kStepOut, |
606 kSingleStep | 518 kSingleStep |
607 }; | 519 }; |
608 | 520 |
609 static bool HasAnyEventHandler(); | 521 bool NeedsIsolateEvents(); |
610 static bool HasDebugEventHandler(); | 522 bool NeedsDebugEvents(); |
611 void InvokeEventHandler(DebuggerEvent* event); | 523 void InvokeEventHandler(ServiceEvent* event); |
| 524 |
| 525 void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt); |
| 526 |
612 bool IsAtAsyncJump(ActivationFrame* top_frame); | 527 bool IsAtAsyncJump(ActivationFrame* top_frame); |
613 void FindCompiledFunctions(const Script& script, | 528 void FindCompiledFunctions(const Script& script, |
614 TokenPosition start_pos, | 529 TokenPosition start_pos, |
615 TokenPosition end_pos, | 530 TokenPosition end_pos, |
616 GrowableObjectArray* function_list); | 531 GrowableObjectArray* function_list); |
617 RawFunction* FindBestFit(const Script& script, TokenPosition token_pos); | 532 RawFunction* FindBestFit(const Script& script, TokenPosition token_pos); |
618 RawFunction* FindInnermostClosure(const Function& function, | 533 RawFunction* FindInnermostClosure(const Function& function, |
619 TokenPosition token_pos); | 534 TokenPosition token_pos); |
620 TokenPosition ResolveBreakpointPos(const Function& func, | 535 TokenPosition ResolveBreakpointPos(const Function& func, |
621 TokenPosition requested_token_pos, | 536 TokenPosition requested_token_pos, |
(...skipping 26 matching lines...) Expand all Loading... |
648 static ActivationFrame* CollectDartFrame(Isolate* isolate, | 563 static ActivationFrame* CollectDartFrame(Isolate* isolate, |
649 uword pc, | 564 uword pc, |
650 StackFrame* frame, | 565 StackFrame* frame, |
651 const Code& code, | 566 const Code& code, |
652 const Array& deopt_frame, | 567 const Array& deopt_frame, |
653 intptr_t deopt_frame_offset); | 568 intptr_t deopt_frame_offset); |
654 static RawArray* DeoptimizeToArray(Thread* thread, | 569 static RawArray* DeoptimizeToArray(Thread* thread, |
655 StackFrame* frame, | 570 StackFrame* frame, |
656 const Code& code); | 571 const Code& code); |
657 static DebuggerStackTrace* CollectStackTrace(); | 572 static DebuggerStackTrace* CollectStackTrace(); |
658 void SignalBpResolved(Breakpoint *bpt); | |
659 void SignalPausedEvent(ActivationFrame* top_frame, | 573 void SignalPausedEvent(ActivationFrame* top_frame, |
660 Breakpoint* bpt); | 574 Breakpoint* bpt); |
661 | 575 |
662 intptr_t nextId() { return next_id_++; } | 576 intptr_t nextId() { return next_id_++; } |
663 | 577 |
664 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace, | 578 bool ShouldPauseOnException(DebuggerStackTrace* stack_trace, |
665 const Instance& exc); | 579 const Instance& exc); |
666 | 580 |
667 void CollectLibraryFields(const GrowableObjectArray& field_list, | 581 void CollectLibraryFields(const GrowableObjectArray& field_list, |
668 const Library& lib, | 582 const Library& lib, |
669 const String& prefix, | 583 const String& prefix, |
670 bool include_private_fields); | 584 bool include_private_fields); |
671 | 585 |
672 // Handles any events which pause vm execution. Breakpoints, | 586 // Handles any events which pause vm execution. Breakpoints, |
673 // interrupts, etc. | 587 // interrupts, etc. |
674 void Pause(DebuggerEvent* event); | 588 void Pause(ServiceEvent* event); |
675 | 589 |
676 void HandleSteppingRequest(DebuggerStackTrace* stack_trace, | 590 void HandleSteppingRequest(DebuggerStackTrace* stack_trace, |
677 bool skip_next_step = false); | 591 bool skip_next_step = false); |
678 | 592 |
679 Isolate* isolate_; | 593 Isolate* isolate_; |
680 Dart_Port isolate_id_; // A unique ID for the isolate in the debugger. | 594 Dart_Port isolate_id_; // A unique ID for the isolate in the debugger. |
681 bool initialized_; | 595 bool initialized_; |
682 bool creation_message_sent_; // The creation message has been sent. | |
683 | 596 |
684 // ID number generator. | 597 // ID number generator. |
685 intptr_t next_id_; | 598 intptr_t next_id_; |
686 | 599 |
687 BreakpointLocation* latent_locations_; | 600 BreakpointLocation* latent_locations_; |
688 BreakpointLocation* breakpoint_locations_; | 601 BreakpointLocation* breakpoint_locations_; |
689 CodeBreakpoint* code_breakpoints_; | 602 CodeBreakpoint* code_breakpoints_; |
690 | 603 |
691 // Tells debugger what to do when resuming execution after a breakpoint. | 604 // Tells debugger what to do when resuming execution after a breakpoint. |
692 ResumeAction resume_action_; | 605 ResumeAction resume_action_; |
693 | 606 |
694 // Do not call back to breakpoint handler if this flag is set. | 607 // Do not call back to breakpoint handler if this flag is set. |
695 // Effectively this means ignoring breakpoints. Set when Dart code may | 608 // Effectively this means ignoring breakpoints. Set when Dart code may |
696 // be run as a side effect of getting values of fields. | 609 // be run as a side effect of getting values of fields. |
697 bool ignore_breakpoints_; | 610 bool ignore_breakpoints_; |
698 | 611 |
699 // Indicates why the debugger is currently paused. If the debugger | 612 // Indicates why the debugger is currently paused. If the debugger |
700 // is not paused, this is NULL. Note that the debugger can be | 613 // is not paused, this is NULL. Note that the debugger can be |
701 // paused for breakpoints, isolate interruption, and (sometimes) | 614 // paused for breakpoints, isolate interruption, and (sometimes) |
702 // exceptions. | 615 // exceptions. |
703 DebuggerEvent* pause_event_; | 616 ServiceEvent* pause_event_; |
704 | 617 |
705 // An id -> object map. Valid only while IsPaused(). | 618 // An id -> object map. Valid only while IsPaused(). |
706 RemoteObjectCache* obj_cache_; | 619 RemoteObjectCache* obj_cache_; |
707 | 620 |
708 // Current stack trace. Valid only while IsPaused(). | 621 // Current stack trace. Valid only while IsPaused(). |
709 DebuggerStackTrace* stack_trace_; | 622 DebuggerStackTrace* stack_trace_; |
710 | 623 |
711 // When stepping through code, only pause the program if the top | 624 // When stepping through code, only pause the program if the top |
712 // frame corresponds to this fp value, or if the top frame is | 625 // frame corresponds to this fp value, or if the top frame is |
713 // lower on the stack. | 626 // lower on the stack. |
(...skipping 15 matching lines...) Expand all Loading... |
729 | 642 |
730 friend class Isolate; | 643 friend class Isolate; |
731 friend class BreakpointLocation; | 644 friend class BreakpointLocation; |
732 DISALLOW_COPY_AND_ASSIGN(Debugger); | 645 DISALLOW_COPY_AND_ASSIGN(Debugger); |
733 }; | 646 }; |
734 | 647 |
735 | 648 |
736 } // namespace dart | 649 } // namespace dart |
737 | 650 |
738 #endif // VM_DEBUGGER_H_ | 651 #endif // VM_DEBUGGER_H_ |
OLD | NEW |