| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 static Address step_in_fp() { return thread_local_.step_into_fp_; } | 275 static Address step_in_fp() { return thread_local_.step_into_fp_; } |
| 276 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } | 276 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } |
| 277 | 277 |
| 278 static EnterDebugger* debugger_entry() { | 278 static EnterDebugger* debugger_entry() { |
| 279 return thread_local_.debugger_entry_; | 279 return thread_local_.debugger_entry_; |
| 280 } | 280 } |
| 281 static void set_debugger_entry(EnterDebugger* entry) { | 281 static void set_debugger_entry(EnterDebugger* entry) { |
| 282 thread_local_.debugger_entry_ = entry; | 282 thread_local_.debugger_entry_ = entry; |
| 283 } | 283 } |
| 284 | 284 |
| 285 static bool preemption_pending() { | 285 // Check whether any of the specified interrupts are pending. |
| 286 return thread_local_.preemption_pending_; | 286 static bool is_interrupt_pending(InterruptFlag what) { |
| 287 return (thread_local_.pending_interrupts_ & what) != 0; |
| 287 } | 288 } |
| 288 static void set_preemption_pending(bool preemption_pending) { | 289 |
| 289 thread_local_.preemption_pending_ = preemption_pending; | 290 // Set specified interrupts as pending. |
| 291 static void set_interrupts_pending(InterruptFlag what) { |
| 292 thread_local_.pending_interrupts_ |= what; |
| 293 } |
| 294 |
| 295 // Clear specified interrupts from pending. |
| 296 static void clear_interrupt_pending(InterruptFlag what) { |
| 297 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); |
| 290 } | 298 } |
| 291 | 299 |
| 292 // Getter and setter for the disable break state. | 300 // Getter and setter for the disable break state. |
| 293 static bool disable_break() { return disable_break_; } | 301 static bool disable_break() { return disable_break_; } |
| 294 static void set_disable_break(bool disable_break) { | 302 static void set_disable_break(bool disable_break) { |
| 295 disable_break_ = disable_break; | 303 disable_break_ = disable_break; |
| 296 } | 304 } |
| 297 | 305 |
| 298 // Getters for the current exception break state. | 306 // Getters for the current exception break state. |
| 299 static bool break_on_exception() { return break_on_exception_; } | 307 static bool break_on_exception() { return break_on_exception_; } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 | 432 |
| 425 // Frame pointer for frame from which step in was performed. | 433 // Frame pointer for frame from which step in was performed. |
| 426 Address step_into_fp_; | 434 Address step_into_fp_; |
| 427 | 435 |
| 428 // Storage location for jump when exiting debug break calls. | 436 // Storage location for jump when exiting debug break calls. |
| 429 Address after_break_target_; | 437 Address after_break_target_; |
| 430 | 438 |
| 431 // Top debugger entry. | 439 // Top debugger entry. |
| 432 EnterDebugger* debugger_entry_; | 440 EnterDebugger* debugger_entry_; |
| 433 | 441 |
| 434 // Preemption happened while debugging. | 442 // Pending interrupts scheduled while debugging. |
| 435 bool preemption_pending_; | 443 int pending_interrupts_; |
| 436 }; | 444 }; |
| 437 | 445 |
| 438 // Storage location for registers when handling debug break calls | 446 // Storage location for registers when handling debug break calls |
| 439 static JSCallerSavedBuffer registers_; | 447 static JSCallerSavedBuffer registers_; |
| 440 static ThreadLocal thread_local_; | 448 static ThreadLocal thread_local_; |
| 441 static void ThreadInit(); | 449 static void ThreadInit(); |
| 442 | 450 |
| 443 // Code object for debug break return entry code. | 451 // Code object for debug break return entry code. |
| 444 static Code* debug_break_return_entry_; | 452 static Code* debug_break_return_entry_; |
| 445 | 453 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 | 680 |
| 673 // This class is used for entering the debugger. Create an instance in the stack | 681 // This class is used for entering the debugger. Create an instance in the stack |
| 674 // to enter the debugger. This will set the current break state, make sure the | 682 // to enter the debugger. This will set the current break state, make sure the |
| 675 // debugger is loaded and switch to the debugger context. If the debugger for | 683 // debugger is loaded and switch to the debugger context. If the debugger for |
| 676 // some reason could not be entered FailedToEnter will return true. | 684 // some reason could not be entered FailedToEnter will return true. |
| 677 class EnterDebugger BASE_EMBEDDED { | 685 class EnterDebugger BASE_EMBEDDED { |
| 678 public: | 686 public: |
| 679 EnterDebugger() | 687 EnterDebugger() |
| 680 : prev_(Debug::debugger_entry()), | 688 : prev_(Debug::debugger_entry()), |
| 681 has_js_frames_(!it_.done()) { | 689 has_js_frames_(!it_.done()) { |
| 682 ASSERT(prev_ == NULL ? !Debug::preemption_pending() : true); | 690 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT)); |
| 691 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK)); |
| 683 | 692 |
| 684 // Link recursive debugger entry. | 693 // Link recursive debugger entry. |
| 685 Debug::set_debugger_entry(this); | 694 Debug::set_debugger_entry(this); |
| 686 | 695 |
| 687 // Store the previous break id and frame id. | 696 // Store the previous break id and frame id. |
| 688 break_id_ = Debug::break_id(); | 697 break_id_ = Debug::break_id(); |
| 689 break_frame_id_ = Debug::break_frame_id(); | 698 break_frame_id_ = Debug::break_frame_id(); |
| 690 | 699 |
| 691 // Create the new break info. If there is no JavaScript frames there is no | 700 // Create the new break info. If there is no JavaScript frames there is no |
| 692 // break frame id. | 701 // break frame id. |
| 693 if (has_js_frames_) { | 702 if (has_js_frames_) { |
| 694 Debug::NewBreak(it_.frame()->id()); | 703 Debug::NewBreak(it_.frame()->id()); |
| 695 } else { | 704 } else { |
| 696 Debug::NewBreak(StackFrame::NO_ID); | 705 Debug::NewBreak(StackFrame::NO_ID); |
| 697 } | 706 } |
| 698 | 707 |
| 699 // Make sure that debugger is loaded and enter the debugger context. | 708 // Make sure that debugger is loaded and enter the debugger context. |
| 700 load_failed_ = !Debug::Load(); | 709 load_failed_ = !Debug::Load(); |
| 701 if (!load_failed_) { | 710 if (!load_failed_) { |
| 702 // NOTE the member variable save which saves the previous context before | 711 // NOTE the member variable save which saves the previous context before |
| 703 // this change. | 712 // this change. |
| 704 Top::set_context(*Debug::debug_context()); | 713 Top::set_context(*Debug::debug_context()); |
| 705 } | 714 } |
| 706 } | 715 } |
| 707 | 716 |
| 708 ~EnterDebugger() { | 717 ~EnterDebugger() { |
| 709 // Restore to the previous break state. | 718 // Restore to the previous break state. |
| 710 Debug::SetBreak(break_frame_id_, break_id_); | 719 Debug::SetBreak(break_frame_id_, break_id_); |
| 711 | 720 |
| 712 // Request preemption when leaving the last debugger entry and a preemption | 721 // Check for leaving the debugger. |
| 713 // had been recorded while debugging. This is to avoid starvation in some | |
| 714 // debugging scenarios. | |
| 715 if (prev_ == NULL && Debug::preemption_pending()) { | |
| 716 StackGuard::Preempt(); | |
| 717 Debug::set_preemption_pending(false); | |
| 718 } | |
| 719 | |
| 720 // If there are commands in the queue when leaving the debugger request that | |
| 721 // these commands are processed. | |
| 722 if (prev_ == NULL && Debugger::HasCommands()) { | |
| 723 StackGuard::DebugCommand(); | |
| 724 } | |
| 725 | |
| 726 if (prev_ == NULL) { | 722 if (prev_ == NULL) { |
| 727 // Clear mirror cache when leaving the debugger. Skip this if there is a | 723 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 728 // pending exception as clearing the mirror cache calls back into | 724 // pending exception as clearing the mirror cache calls back into |
| 729 // JavaScript. This can happen if the v8::Debug::Call is used in which | 725 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 730 // case the exception should end up in the calling code. | 726 // case the exception should end up in the calling code. |
| 731 if (!Top::has_pending_exception()) { | 727 if (!Top::has_pending_exception()) { |
| 728 // Try to avoid any pending debug break breaking in the clear mirror |
| 729 // cache JavaScript code. |
| 730 if (StackGuard::IsDebugBreak()) { |
| 731 Debug::set_interrupts_pending(DEBUGBREAK); |
| 732 StackGuard::Continue(DEBUGBREAK); |
| 733 } |
| 732 Debug::ClearMirrorCache(); | 734 Debug::ClearMirrorCache(); |
| 733 } | 735 } |
| 736 |
| 737 // Request preemption and debug break when leaving the last debugger entry |
| 738 // if any of these where recorded while debugging. |
| 739 if (Debug::is_interrupt_pending(PREEMPT)) { |
| 740 // This re-scheduling of preemption is to avoid starvation in some |
| 741 // debugging scenarios. |
| 742 Debug::clear_interrupt_pending(PREEMPT); |
| 743 StackGuard::Preempt(); |
| 744 } |
| 745 if (Debug::is_interrupt_pending(DEBUGBREAK)) { |
| 746 Debug::clear_interrupt_pending(DEBUGBREAK); |
| 747 StackGuard::DebugBreak(); |
| 748 } |
| 749 |
| 750 // If there are commands in the queue when leaving the debugger request |
| 751 // that these commands are processed. |
| 752 if (Debugger::HasCommands()) { |
| 753 StackGuard::DebugCommand(); |
| 754 } |
| 755 |
| 734 // If leaving the debugger with the debugger no longer active unload it. | 756 // If leaving the debugger with the debugger no longer active unload it. |
| 735 if (!Debugger::IsDebuggerActive()) { | 757 if (!Debugger::IsDebuggerActive()) { |
| 736 Debugger::UnloadDebugger(); | 758 Debugger::UnloadDebugger(); |
| 737 } | 759 } |
| 738 } | 760 } |
| 739 | 761 |
| 740 // Leaving this debugger entry. | 762 // Leaving this debugger entry. |
| 741 Debug::set_debugger_entry(prev_); | 763 Debug::set_debugger_entry(prev_); |
| 742 } | 764 } |
| 743 | 765 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 Debug::AddressId id_; | 841 Debug::AddressId id_; |
| 820 int reg_; | 842 int reg_; |
| 821 }; | 843 }; |
| 822 | 844 |
| 823 | 845 |
| 824 } } // namespace v8::internal | 846 } } // namespace v8::internal |
| 825 | 847 |
| 826 #endif // ENABLE_DEBUGGER_SUPPORT | 848 #endif // ENABLE_DEBUGGER_SUPPORT |
| 827 | 849 |
| 828 #endif // V8_DEBUG_H_ | 850 #endif // V8_DEBUG_H_ |
| OLD | NEW |