Index: src/debug.cc |
diff --git a/src/debug.cc b/src/debug.cc |
index 34ba3949e90acefd5651f772cbb3ce524d4a33ce..fb7e3370422308face20da263ab40b829d617000 100644 |
--- a/src/debug.cc |
+++ b/src/debug.cc |
@@ -40,6 +40,7 @@ |
#include "global-handles.h" |
#include "ic.h" |
#include "ic-inl.h" |
+#include "isolate-inl.h" |
#include "list.h" |
#include "messages.h" |
#include "natives.h" |
@@ -2937,6 +2938,94 @@ void Debugger::CallMessageDispatchHandler() { |
} |
+EnterDebugger::EnterDebugger() |
+ : isolate_(Isolate::Current()), |
+ prev_(isolate_->debug()->debugger_entry()), |
+ it_(isolate_), |
+ has_js_frames_(!it_.done()), |
+ save_(isolate_) { |
+ Debug* debug = isolate_->debug(); |
+ 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); |
+ |
+ // Store the previous break id and frame id. |
+ break_id_ = debug->break_id(); |
+ break_frame_id_ = debug->break_frame_id(); |
+ |
+ // Create the new break info. If there is no JavaScript frames there is no |
+ // break frame id. |
+ if (has_js_frames_) { |
+ debug->NewBreak(it_.frame()->id()); |
+ } else { |
+ debug->NewBreak(StackFrame::NO_ID); |
+ } |
+ |
+ // Make sure that debugger is loaded and enter the debugger context. |
+ load_failed_ = !debug->Load(); |
+ if (!load_failed_) { |
+ // NOTE the member variable save which saves the previous context before |
+ // this change. |
+ isolate_->set_context(*debug->debug_context()); |
+ } |
+} |
+ |
+ |
+EnterDebugger::~EnterDebugger() { |
+ ASSERT(Isolate::Current() == isolate_); |
+ Debug* debug = isolate_->debug(); |
+ |
+ // Restore to the previous break state. |
+ debug->SetBreak(break_frame_id_, break_id_); |
+ |
+ // 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 (!isolate_->has_pending_exception()) { |
+ // Try to avoid any pending debug break breaking in the clear mirror |
+ // cache JavaScript code. |
+ if (isolate_->stack_guard()->IsDebugBreak()) { |
+ debug->set_interrupts_pending(DEBUGBREAK); |
+ isolate_->stack_guard()->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); |
+ isolate_->stack_guard()->Preempt(); |
+ } |
+ if (debug->is_interrupt_pending(DEBUGBREAK)) { |
+ debug->clear_interrupt_pending(DEBUGBREAK); |
+ isolate_->stack_guard()->DebugBreak(); |
+ } |
+ |
+ // If there are commands in the queue when leaving the debugger request |
+ // that these commands are processed. |
+ if (isolate_->debugger()->HasCommands()) { |
+ isolate_->stack_guard()->DebugCommand(); |
+ } |
+ |
+ // If leaving the debugger with the debugger no longer active unload it. |
+ if (!isolate_->debugger()->IsDebuggerActive()) { |
+ isolate_->debugger()->UnloadDebugger(); |
+ } |
+ } |
+ |
+ // Leaving this debugger entry. |
+ debug->set_debugger_entry(prev_); |
+} |
+ |
+ |
MessageImpl MessageImpl::NewEvent(DebugEvent event, |
bool running, |
Handle<JSObject> exec_state, |