OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_DEBUG_DEBUG_H_ | 5 #ifndef V8_DEBUG_DEBUG_H_ |
6 #define V8_DEBUG_DEBUG_H_ | 6 #define V8_DEBUG_DEBUG_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/assembler.h" | 10 #include "src/assembler.h" |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 void Iterate(ObjectVisitor* v); | 507 void Iterate(ObjectVisitor* v); |
508 | 508 |
509 bool CheckExecutionState(int id) { | 509 bool CheckExecutionState(int id) { |
510 return CheckExecutionState() && break_id() == id; | 510 return CheckExecutionState() && break_id() == id; |
511 } | 511 } |
512 | 512 |
513 bool CheckExecutionState() { | 513 bool CheckExecutionState() { |
514 return is_active() && !debug_context().is_null() && break_id() != 0; | 514 return is_active() && !debug_context().is_null() && break_id() != 0; |
515 } | 515 } |
516 | 516 |
| 517 bool PerformSideEffectCheck(Handle<JSFunction> function); |
| 518 bool PerformSideEffectCheckForCallback(Address function); |
| 519 |
517 // Flags and states. | 520 // Flags and states. |
518 DebugScope* debugger_entry() { | 521 DebugScope* debugger_entry() { |
519 return reinterpret_cast<DebugScope*>( | 522 return reinterpret_cast<DebugScope*>( |
520 base::NoBarrier_Load(&thread_local_.current_debug_scope_)); | 523 base::NoBarrier_Load(&thread_local_.current_debug_scope_)); |
521 } | 524 } |
522 inline Handle<Context> debug_context() { return debug_context_; } | 525 inline Handle<Context> debug_context() { return debug_context_; } |
523 | 526 |
524 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } | 527 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } |
525 bool live_edit_enabled() const { | 528 bool live_edit_enabled() const { |
526 return FLAG_enable_liveedit && live_edit_enabled_; | 529 return FLAG_enable_liveedit && live_edit_enabled_; |
(...skipping 13 matching lines...) Expand all Loading... |
540 Handle<Object> return_value() { return thread_local_.return_value_; } | 543 Handle<Object> return_value() { return thread_local_.return_value_; } |
541 void set_return_value(Handle<Object> value) { | 544 void set_return_value(Handle<Object> value) { |
542 thread_local_.return_value_ = value; | 545 thread_local_.return_value_ = value; |
543 } | 546 } |
544 | 547 |
545 // Support for embedding into generated code. | 548 // Support for embedding into generated code. |
546 Address is_active_address() { | 549 Address is_active_address() { |
547 return reinterpret_cast<Address>(&is_active_); | 550 return reinterpret_cast<Address>(&is_active_); |
548 } | 551 } |
549 | 552 |
| 553 Address hook_on_function_call_address() { |
| 554 return reinterpret_cast<Address>(&hook_on_function_call_); |
| 555 } |
| 556 |
550 Address after_break_target_address() { | 557 Address after_break_target_address() { |
551 return reinterpret_cast<Address>(&after_break_target_); | 558 return reinterpret_cast<Address>(&after_break_target_); |
552 } | 559 } |
553 | 560 |
554 Address last_step_action_address() { | 561 Address last_step_action_address() { |
555 return reinterpret_cast<Address>(&thread_local_.last_step_action_); | 562 return reinterpret_cast<Address>(&thread_local_.last_step_action_); |
556 } | 563 } |
557 | 564 |
558 Address suspended_generator_address() { | 565 Address suspended_generator_address() { |
559 return reinterpret_cast<Address>(&thread_local_.suspended_generator_); | 566 return reinterpret_cast<Address>(&thread_local_.suspended_generator_); |
560 } | 567 } |
561 | 568 |
562 StepAction last_step_action() { return thread_local_.last_step_action_; } | 569 StepAction last_step_action() { return thread_local_.last_step_action_; } |
563 | 570 |
564 DebugFeatureTracker* feature_tracker() { return &feature_tracker_; } | 571 DebugFeatureTracker* feature_tracker() { return &feature_tracker_; } |
565 | 572 |
566 private: | 573 private: |
567 explicit Debug(Isolate* isolate); | 574 explicit Debug(Isolate* isolate); |
568 | 575 |
569 void UpdateState(); | 576 void UpdateState(); |
| 577 void UpdateHookOnFunctionCall(); |
570 void Unload(); | 578 void Unload(); |
571 void SetNextBreakId() { | 579 void SetNextBreakId() { |
572 thread_local_.break_id_ = ++thread_local_.break_count_; | 580 thread_local_.break_id_ = ++thread_local_.break_count_; |
573 } | 581 } |
574 | 582 |
575 // Check whether there are commands in the command queue. | 583 // Check whether there are commands in the command queue. |
576 inline bool has_commands() const { return !command_queue_.IsEmpty(); } | 584 inline bool has_commands() const { return !command_queue_.IsEmpty(); } |
577 inline bool ignore_events() const { return is_suppressed_ || !is_active_; } | 585 inline bool ignore_events() const { return is_suppressed_ || !is_active_; } |
578 inline bool break_disabled() const { | 586 inline bool break_disabled() const { |
579 return break_disabled_ || in_debug_event_listener_; | 587 return break_disabled_ || in_debug_event_listener_; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 Handle<Context> debug_context_; | 663 Handle<Context> debug_context_; |
656 Handle<Object> event_listener_; | 664 Handle<Object> event_listener_; |
657 Handle<Object> event_listener_data_; | 665 Handle<Object> event_listener_data_; |
658 | 666 |
659 v8::Debug::MessageHandler message_handler_; | 667 v8::Debug::MessageHandler message_handler_; |
660 | 668 |
661 static const int kQueueInitialSize = 4; | 669 static const int kQueueInitialSize = 4; |
662 base::Semaphore command_received_; // Signaled for each command received. | 670 base::Semaphore command_received_; // Signaled for each command received. |
663 LockingCommandMessageQueue command_queue_; | 671 LockingCommandMessageQueue command_queue_; |
664 | 672 |
| 673 // Debugger is active, i.e. there is a debug event listener attached. |
665 bool is_active_; | 674 bool is_active_; |
| 675 // Debugger needs to be notified on every new function call. |
| 676 // Used for stepping and read-only checks |
| 677 bool hook_on_function_call_; |
| 678 // Suppress debug events. |
666 bool is_suppressed_; | 679 bool is_suppressed_; |
| 680 // LiveEdit is enabled. |
667 bool live_edit_enabled_; | 681 bool live_edit_enabled_; |
| 682 // Do not trigger debug break events. |
668 bool break_disabled_; | 683 bool break_disabled_; |
| 684 // Do not break on break points. |
669 bool break_points_active_; | 685 bool break_points_active_; |
| 686 // Nested inside a debug event listener. |
670 bool in_debug_event_listener_; | 687 bool in_debug_event_listener_; |
| 688 // Trigger debug break events for all exceptions. |
671 bool break_on_exception_; | 689 bool break_on_exception_; |
| 690 // Trigger debug break events for uncaught exceptions. |
672 bool break_on_uncaught_exception_; | 691 bool break_on_uncaught_exception_; |
| 692 // Termination exception because side effect check has failed. |
| 693 bool side_effect_check_failed_; |
673 | 694 |
674 DebugInfoListNode* debug_info_list_; // List of active debug info objects. | 695 // List of active debug info objects. |
| 696 DebugInfoListNode* debug_info_list_; |
675 | 697 |
676 // Storage location for jump when exiting debug break calls. | 698 // Storage location for jump when exiting debug break calls. |
677 // Note that this address is not GC safe. It should be computed immediately | 699 // Note that this address is not GC safe. It should be computed immediately |
678 // before returning to the DebugBreakCallHelper. | 700 // before returning to the DebugBreakCallHelper. |
679 Address after_break_target_; | 701 Address after_break_target_; |
680 | 702 |
681 // Used to collect histogram data on debugger feature usage. | 703 // Used to collect histogram data on debugger feature usage. |
682 DebugFeatureTracker feature_tracker_; | 704 DebugFeatureTracker feature_tracker_; |
683 | 705 |
684 // Per-thread data. | 706 // Per-thread data. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
724 // Storage location for registers when handling debug break calls | 746 // Storage location for registers when handling debug break calls |
725 ThreadLocal thread_local_; | 747 ThreadLocal thread_local_; |
726 | 748 |
727 Isolate* isolate_; | 749 Isolate* isolate_; |
728 | 750 |
729 friend class Isolate; | 751 friend class Isolate; |
730 friend class DebugScope; | 752 friend class DebugScope; |
731 friend class DisableBreak; | 753 friend class DisableBreak; |
732 friend class LiveEdit; | 754 friend class LiveEdit; |
733 friend class SuppressDebug; | 755 friend class SuppressDebug; |
| 756 friend class NoSideEffectScope; |
734 | 757 |
735 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc | 758 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc |
736 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc | 759 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc |
737 | 760 |
738 DISALLOW_COPY_AND_ASSIGN(Debug); | 761 DISALLOW_COPY_AND_ASSIGN(Debug); |
739 }; | 762 }; |
740 | 763 |
741 | 764 |
742 // This scope is used to load and enter the debug context and create a new | 765 // This scope is used to load and enter the debug context and create a new |
743 // break state. Leaving the scope will restore the previous state. | 766 // break state. Leaving the scope will restore the previous state. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 debug_->is_suppressed_ = true; | 820 debug_->is_suppressed_ = true; |
798 } | 821 } |
799 ~SuppressDebug() { debug_->is_suppressed_ = old_state_; } | 822 ~SuppressDebug() { debug_->is_suppressed_ = old_state_; } |
800 | 823 |
801 private: | 824 private: |
802 Debug* debug_; | 825 Debug* debug_; |
803 bool old_state_; | 826 bool old_state_; |
804 DISALLOW_COPY_AND_ASSIGN(SuppressDebug); | 827 DISALLOW_COPY_AND_ASSIGN(SuppressDebug); |
805 }; | 828 }; |
806 | 829 |
| 830 class NoSideEffectScope { |
| 831 public: |
| 832 NoSideEffectScope(Isolate* isolate, bool disallow_side_effects) |
| 833 : isolate_(isolate), |
| 834 old_needs_side_effect_check_(isolate->needs_side_effect_check()) { |
| 835 isolate->set_needs_side_effect_check(old_needs_side_effect_check_ || |
| 836 disallow_side_effects); |
| 837 isolate->debug()->UpdateHookOnFunctionCall(); |
| 838 isolate->debug()->side_effect_check_failed_ = false; |
| 839 } |
| 840 ~NoSideEffectScope(); |
| 841 |
| 842 private: |
| 843 Isolate* isolate_; |
| 844 bool old_needs_side_effect_check_; |
| 845 DISALLOW_COPY_AND_ASSIGN(NoSideEffectScope); |
| 846 }; |
807 | 847 |
808 // Code generator routines. | 848 // Code generator routines. |
809 class DebugCodegen : public AllStatic { | 849 class DebugCodegen : public AllStatic { |
810 public: | 850 public: |
811 enum DebugBreakCallHelperMode { | 851 enum DebugBreakCallHelperMode { |
812 SAVE_RESULT_REGISTER, | 852 SAVE_RESULT_REGISTER, |
813 IGNORE_RESULT_REGISTER | 853 IGNORE_RESULT_REGISTER |
814 }; | 854 }; |
815 | 855 |
816 static void GenerateDebugBreakStub(MacroAssembler* masm, | 856 static void GenerateDebugBreakStub(MacroAssembler* masm, |
(...skipping 12 matching lines...) Expand all Loading... |
829 Handle<Code> code); | 869 Handle<Code> code); |
830 static bool DebugBreakSlotIsPatched(Address pc); | 870 static bool DebugBreakSlotIsPatched(Address pc); |
831 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); | 871 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); |
832 }; | 872 }; |
833 | 873 |
834 | 874 |
835 } // namespace internal | 875 } // namespace internal |
836 } // namespace v8 | 876 } // namespace v8 |
837 | 877 |
838 #endif // V8_DEBUG_DEBUG_H_ | 878 #endif // V8_DEBUG_DEBUG_H_ |
OLD | NEW |