| Index: src/debug.cc
|
| ===================================================================
|
| --- src/debug.cc (revision 1647)
|
| +++ src/debug.cc (working copy)
|
| @@ -607,9 +607,6 @@
|
| return;
|
| }
|
|
|
| - // Get rid of all break points and related information.
|
| - ClearAllBreakPoints();
|
| -
|
| // Clear debugger context global handle.
|
| GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
|
| debug_context_ = Handle<Context>();
|
| @@ -1369,13 +1366,15 @@
|
| }
|
|
|
|
|
| +Mutex* Debugger::debugger_access_ = OS::CreateMutex();
|
| Handle<Object> Debugger::event_listener_ = Handle<Object>();
|
| Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
|
| -bool Debugger::debugger_active_ = false;
|
| bool Debugger::compiling_natives_ = false;
|
| bool Debugger::is_loading_debugger_ = false;
|
| +bool Debugger::never_unload_debugger_ = false;
|
| DebugMessageThread* Debugger::message_thread_ = NULL;
|
| v8::DebugMessageHandler Debugger::message_handler_ = NULL;
|
| +bool Debugger::message_handler_cleared_ = false;
|
| void* Debugger::message_handler_data_ = NULL;
|
| v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
|
| void* Debugger::host_dispatch_handler_data_ = NULL;
|
| @@ -1581,7 +1580,7 @@
|
| if (compiling_natives()) return;
|
|
|
| // No more to do if not debugging.
|
| - if (!debugger_active()) return;
|
| + if (!IsDebuggerActive()) return;
|
|
|
| // Store whether in debugger before entering debugger.
|
| bool in_debugger = Debug::InDebugger();
|
| @@ -1710,6 +1709,20 @@
|
| }
|
|
|
|
|
| +void Debugger::UnloadDebugger() {
|
| + // Make sure that there are no breakpoints left.
|
| + Debug::ClearAllBreakPoints();
|
| +
|
| + // Unload the debugger if feasible.
|
| + if (!never_unload_debugger_) {
|
| + Debug::Unload();
|
| + }
|
| +
|
| + // Clear the flag indicating that the message handler was recently cleared.
|
| + message_handler_cleared_ = false;
|
| +}
|
| +
|
| +
|
| void Debugger::NotifyMessageHandler(v8::DebugEvent event,
|
| Handle<Object> exec_state,
|
| Handle<Object> event_data,
|
| @@ -1777,7 +1790,7 @@
|
| // Get the command from the queue.
|
| Vector<uint16_t> command = command_queue_.Get();
|
| Logger::DebugTag("Got request from command queue, in interactive loop.");
|
| - if (!Debugger::debugger_active()) {
|
| + if (!Debugger::IsDebuggerActive()) {
|
| return;
|
| }
|
|
|
| @@ -1880,19 +1893,34 @@
|
| event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
|
| }
|
|
|
| - UpdateActiveDebugger();
|
| + // Unload the debugger if event listener cleared.
|
| + if (callback->IsUndefined()) {
|
| + UnloadDebugger();
|
| + }
|
| }
|
|
|
|
|
| void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data,
|
| bool message_handler_thread) {
|
| + ScopedLock with(debugger_access_);
|
| +
|
| message_handler_ = handler;
|
| message_handler_data_ = data;
|
| - if (!message_thread_ && message_handler_thread) {
|
| - message_thread_ = new DebugMessageThread();
|
| - message_thread_->Start();
|
| + if (handler != NULL) {
|
| + if (!message_thread_ && message_handler_thread) {
|
| + message_thread_ = new DebugMessageThread();
|
| + message_thread_->Start();
|
| + }
|
| + } else {
|
| + // Indicate that the message handler was recently cleared.
|
| + message_handler_cleared_ = true;
|
| +
|
| + // Send an empty command to the debugger if in a break to make JavaScript
|
| + // run again if the debugger is closed.
|
| + if (Debug::InDebugger()) {
|
| + ProcessCommand(Vector<const uint16_t>::empty());
|
| + }
|
| }
|
| - UpdateActiveDebugger();
|
| }
|
|
|
|
|
| @@ -1908,6 +1936,8 @@
|
| // are allocated in various places and deallocated by the calling function
|
| // sometime after this call.
|
| void Debugger::InvokeMessageHandler(Vector<uint16_t> message) {
|
| + ScopedLock with(debugger_access_);
|
| +
|
| if (message_handler_ != NULL) {
|
| message_handler_(message.start(), message.length(), message_handler_data_);
|
| }
|
| @@ -1999,22 +2029,19 @@
|
| }
|
|
|
|
|
| -void Debugger::UpdateActiveDebugger() {
|
| - set_debugger_active(message_handler_ != NULL || !event_listener_.is_null());
|
| - if (!debugger_active() && message_thread_) {
|
| - // Send an empty command to the debugger if in a break to make JavaScript
|
| - // run again if the debugger is closed.
|
| - ProcessCommand(Vector<const uint16_t>::empty());
|
| - }
|
| - if (!debugger_active()) {
|
| - Debug::Unload();
|
| - }
|
| +bool Debugger::IsDebuggerActive() {
|
| + ScopedLock with(debugger_access_);
|
| +
|
| + return message_handler_ != NULL || !event_listener_.is_null();
|
| }
|
|
|
|
|
| Handle<Object> Debugger::Call(Handle<JSFunction> fun,
|
| Handle<Object> data,
|
| bool* pending_exception) {
|
| + // When calling functions in the debugger prevent it from beeing unloaded.
|
| + Debugger::never_unload_debugger_ = true;
|
| +
|
| // Enter the debugger.
|
| EnterDebugger debugger;
|
| if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) {
|
|
|