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