Commit 5d60fa7a authored by peter.rybin@gmail.com's avatar peter.rybin@gmail.com

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
parent 8707b362
......@@ -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.
......
......@@ -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);
}
......
......@@ -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<const uint16_t> 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<JSObject> 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
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment