Revision: 3634
Author: [email protected]
Date: Mon Jan 18 07:48:41 2010
Log: Implement issue 549 Make V8 call DebugMessageDispatchHandler with Locker locked

Review URL: http://codereview.chromium.org/505025
http://code.google.com/p/v8/source/detail?r=3634

Modified:
 /branches/bleeding_edge/include/v8-debug.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/debug.cc
 /branches/bleeding_edge/src/debug.h

=======================================
--- /branches/bleeding_edge/include/v8-debug.h  Fri Jan 15 13:14:56 2010
+++ /branches/bleeding_edge/include/v8-debug.h  Mon Jan 18 07:48:41 2010
@@ -224,9 +224,11 @@
* 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.
=======================================
--- /branches/bleeding_edge/src/api.cc  Fri Jan 15 13:14:56 2010
+++ /branches/bleeding_edge/src/api.cc  Mon Jan 18 07:48:41 2010
@@ -3669,7 +3669,6 @@
 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::SetDebugMessageDispatchHandler(
-    DebugMessageDispatchHandler handler) {
+    DebugMessageDispatchHandler handler, bool provide_locker) {
   EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
   ENTER_V8;
-  i::Debugger::SetDebugMessageDispatchHandler(handler);
+  i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
 }


=======================================
--- /branches/bleeding_edge/src/debug.cc        Fri Jan 15 14:40:57 2010
+++ /branches/bleeding_edge/src/debug.cc        Mon Jan 18 07:48:41 2010
@@ -1761,8 +1761,10 @@
 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::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 @@
     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();
   }
 }

@@ -2522,6 +2538,19 @@
   if (agent_ != NULL)
     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,
@@ -2742,6 +2771,45 @@
   ScopedLock sl(lock_);
   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

=======================================
--- /branches/bleeding_edge/src/debug.h Fri Jan 15 14:40:57 2010
+++ /branches/bleeding_edge/src/debug.h Mon Jan 18 07:48:41 2010
@@ -559,6 +559,9 @@
 };


+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 @@
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 @@
   // 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 @@
   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 @@
   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

-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to