From 5d60fa7ac85e775dd03951ced422ff967e68afc5 Mon Sep 17 00:00:00 2001 From: "peter.rybin@gmail.com" Date: Mon, 18 Jan 2010 15:48:41 +0000 Subject: [PATCH] Implement issue 549 Make V8 call DebugMessageDispatchHandler with Locker locked Review URL: http://codereview.chromium.org/505025 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3634 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8-debug.h | 4 ++- src/api.cc | 5 ++-- src/debug.cc | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/debug.h | 31 ++++++++++++++++++++++- 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/include/v8-debug.h b/include/v8-debug.h index ff3182c..2e5fb3f 100644 --- a/include/v8-debug.h +++ b/include/v8-debug.h @@ -224,9 +224,11 @@ class EXPORT Debug { * be processed. Note that debug messages will only be processed if there is * a V8 break. This can happen automatically by using the option * --debugger-auto-break. + * \param provide_locker requires that V8 acquires v8::Locker for you before + * calling handler */ static void SetDebugMessageDispatchHandler( - DebugMessageDispatchHandler handler); + DebugMessageDispatchHandler handler, bool provide_locker = false); /** * Run a JavaScript function in the debugger. diff --git a/src/api.cc b/src/api.cc index 2546101..322c90f 100644 --- a/src/api.cc +++ b/src/api.cc @@ -3669,7 +3669,6 @@ void Debug::SetMessageHandler(v8::Debug::MessageHandler handler, void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) { EnsureInitialized("v8::Debug::SetMessageHandler"); ENTER_V8; - HandleScope scope; i::Debugger::SetMessageHandler(handler); } @@ -3691,10 +3690,10 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler, void Debug::SetDebugMessageDispatchHandler( - DebugMessageDispatchHandler handler) { + DebugMessageDispatchHandler handler, bool provide_locker) { EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler"); ENTER_V8; - i::Debugger::SetDebugMessageDispatchHandler(handler); + i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker); } diff --git a/src/debug.cc b/src/debug.cc index 9a02355..34b3a6d 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1761,8 +1761,10 @@ bool Debugger::never_unload_debugger_ = false; v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL; bool Debugger::debugger_unload_pending_ = false; v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; +Mutex* Debugger::dispatch_handler_access_ = OS::CreateMutex(); v8::Debug::DebugMessageDispatchHandler Debugger::debug_message_dispatch_handler_ = NULL; +MessageDispatchHelperThread* Debugger::message_dispatch_helper_thread_ = NULL; int Debugger::host_dispatch_micros_ = 100 * 1000; DebuggerAgent* Debugger::agent_ = NULL; LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize); @@ -2399,8 +2401,14 @@ void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, void Debugger::SetDebugMessageDispatchHandler( - v8::Debug::DebugMessageDispatchHandler handler) { + v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) { + ScopedLock with(dispatch_handler_access_); debug_message_dispatch_handler_ = handler; + + if (provide_locker && message_dispatch_helper_thread_ == NULL) { + message_dispatch_helper_thread_ = new MessageDispatchHelperThread; + message_dispatch_helper_thread_->Start(); + } } @@ -2435,8 +2443,16 @@ void Debugger::ProcessCommand(Vector command, StackGuard::DebugCommand(); } - if (Debugger::debug_message_dispatch_handler_ != NULL) { - Debugger::debug_message_dispatch_handler_(); + MessageDispatchHelperThread* dispatch_thread; + { + ScopedLock with(dispatch_handler_access_); + dispatch_thread = message_dispatch_helper_thread_; + } + + if (dispatch_thread == NULL) { + CallMessageDispatchHandler(); + } else { + dispatch_thread->Schedule(); } } @@ -2523,6 +2539,19 @@ void Debugger::WaitForAgent() { agent_->WaitUntilListening(); } + +void Debugger::CallMessageDispatchHandler() { + v8::Debug::DebugMessageDispatchHandler handler; + { + ScopedLock with(dispatch_handler_access_); + handler = Debugger::debug_message_dispatch_handler_; + } + if (handler != NULL) { + handler(); + } +} + + MessageImpl MessageImpl::NewEvent(DebugEvent event, bool running, Handle exec_state, @@ -2743,6 +2772,45 @@ void LockingCommandMessageQueue::Clear() { queue_.Clear(); } + +MessageDispatchHelperThread::MessageDispatchHelperThread() + : sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()), + already_signalled_(false) { +} + + +MessageDispatchHelperThread::~MessageDispatchHelperThread() { + delete mutex_; + delete sem_; +} + + +void MessageDispatchHelperThread::Schedule() { + { + ScopedLock lock(mutex_); + if (already_signalled_) { + return; + } + already_signalled_ = true; + } + sem_->Signal(); +} + + +void MessageDispatchHelperThread::Run() { + while (true) { + sem_->Wait(); + { + ScopedLock lock(mutex_); + already_signalled_ = false; + } + { + Locker locker; + Debugger::CallMessageDispatchHandler(); + } + } +} + #endif // ENABLE_DEBUGGER_SUPPORT } } // namespace v8::internal diff --git a/src/debug.h b/src/debug.h index fe9ff35..5ea2e52 100644 --- a/src/debug.h +++ b/src/debug.h @@ -559,6 +559,9 @@ class CommandMessageQueue BASE_EMBEDDED { }; +class MessageDispatchHelperThread; + + // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage // messages. The message data is not managed by LockingCommandMessageQueue. // Pointers to the data are passed in and out. Implemented by adding a @@ -619,7 +622,8 @@ class Debugger { static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, int period); static void SetDebugMessageDispatchHandler( - v8::Debug::DebugMessageDispatchHandler handler); + v8::Debug::DebugMessageDispatchHandler handler, + bool provide_locker); // Invoke the message handler function. static void InvokeMessageHandler(MessageImpl message); @@ -645,6 +649,8 @@ class Debugger { // Blocks until the agent has started listening for connections static void WaitForAgent(); + static void CallMessageDispatchHandler(); + // Unload the debugger if possible. Only called when no debugger is currently // active. static void UnloadDebugger(); @@ -683,7 +689,9 @@ class Debugger { static v8::Debug::MessageHandler2 message_handler_; static bool debugger_unload_pending_; // Was message handler cleared? static v8::Debug::HostDispatchHandler host_dispatch_handler_; + static Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; + static MessageDispatchHelperThread* message_dispatch_helper_thread_; static int host_dispatch_micros_; static DebuggerAgent* agent_; @@ -860,6 +868,27 @@ class Debug_Address { int reg_; }; +// The optional thread that Debug Agent may use to temporary call V8 to process +// pending debug requests if debuggee is not running V8 at the moment. +// Techincally it does not call V8 itself, rather it asks embedding program +// to do this via v8::Debug::HostDispatchHandler +class MessageDispatchHelperThread: public Thread { + public: + MessageDispatchHelperThread(); + ~MessageDispatchHelperThread(); + + void Schedule(); + + private: + void Run(); + + Semaphore* const sem_; + Mutex* const mutex_; + bool already_signalled_; + + DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); +}; + } } // namespace v8::internal -- 2.7.4