Index: src/debug.h |
=================================================================== |
--- src/debug.h (revision 2070) |
+++ src/debug.h (working copy) |
@@ -282,13 +282,21 @@ |
thread_local_.debugger_entry_ = entry; |
} |
- static bool preemption_pending() { |
- return thread_local_.preemption_pending_; |
+ // Check whether any of the specified interrupts are pending. |
+ static bool is_interrupt_pending(InterruptFlag what) { |
+ return (thread_local_.pending_interrupts_ & what) != 0; |
} |
- static void set_preemption_pending(bool preemption_pending) { |
- thread_local_.preemption_pending_ = preemption_pending; |
+ |
+ // Set specified interrupts as pending. |
+ static void set_interrupts_pending(InterruptFlag what) { |
+ thread_local_.pending_interrupts_ |= what; |
} |
+ // Clear specified interrupts from pending. |
+ static void clear_interrupt_pending(InterruptFlag what) { |
+ thread_local_.pending_interrupts_ &= ~static_cast<int>(what); |
+ } |
+ |
// Getter and setter for the disable break state. |
static bool disable_break() { return disable_break_; } |
static void set_disable_break(bool disable_break) { |
@@ -431,8 +439,8 @@ |
// Top debugger entry. |
EnterDebugger* debugger_entry_; |
- // Preemption happened while debugging. |
- bool preemption_pending_; |
+ // Pending interrupts scheduled while debugging. |
+ int pending_interrupts_; |
}; |
// Storage location for registers when handling debug break calls |
@@ -679,7 +687,8 @@ |
EnterDebugger() |
: prev_(Debug::debugger_entry()), |
has_js_frames_(!it_.done()) { |
- ASSERT(prev_ == NULL ? !Debug::preemption_pending() : true); |
+ ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT)); |
+ ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK)); |
// Link recursive debugger entry. |
Debug::set_debugger_entry(this); |
@@ -709,28 +718,41 @@ |
// Restore to the previous break state. |
Debug::SetBreak(break_frame_id_, break_id_); |
- // Request preemption when leaving the last debugger entry and a preemption |
- // had been recorded while debugging. This is to avoid starvation in some |
- // debugging scenarios. |
- if (prev_ == NULL && Debug::preemption_pending()) { |
- StackGuard::Preempt(); |
- Debug::set_preemption_pending(false); |
- } |
- |
- // If there are commands in the queue when leaving the debugger request that |
- // these commands are processed. |
- if (prev_ == NULL && Debugger::HasCommands()) { |
- StackGuard::DebugCommand(); |
- } |
- |
+ // Check for leaving the debugger. |
if (prev_ == NULL) { |
// Clear mirror cache when leaving the debugger. Skip this if there is a |
// pending exception as clearing the mirror cache calls back into |
// JavaScript. This can happen if the v8::Debug::Call is used in which |
// case the exception should end up in the calling code. |
if (!Top::has_pending_exception()) { |
+ // Try to avoid any pending debug break breaking in the clear mirror |
+ // cache JavaScript code. |
+ if (StackGuard::IsDebugBreak()) { |
+ Debug::set_interrupts_pending(DEBUGBREAK); |
+ StackGuard::Continue(DEBUGBREAK); |
+ } |
Debug::ClearMirrorCache(); |
} |
+ |
+ // Request preemption and debug break when leaving the last debugger entry |
+ // if any of these where recorded while debugging. |
+ if (Debug::is_interrupt_pending(PREEMPT)) { |
+ // This re-scheduling of preemption is to avoid starvation in some |
+ // debugging scenarios. |
+ Debug::clear_interrupt_pending(PREEMPT); |
+ StackGuard::Preempt(); |
+ } |
+ if (Debug::is_interrupt_pending(DEBUGBREAK)) { |
+ Debug::clear_interrupt_pending(DEBUGBREAK); |
+ StackGuard::DebugBreak(); |
+ } |
+ |
+ // If there are commands in the queue when leaving the debugger request |
+ // that these commands are processed. |
+ if (Debugger::HasCommands()) { |
+ StackGuard::DebugCommand(); |
+ } |
+ |
// If leaving the debugger with the debugger no longer active unload it. |
if (!Debugger::IsDebuggerActive()) { |
Debugger::UnloadDebugger(); |