Commit f56701f3 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Clean up Debugger::NotifyMessageHandler.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/276433004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21210 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3976ebef
......@@ -149,11 +149,6 @@ class V8_EXPORT Debug {
*/
typedef void (*MessageHandler2)(const Message& message);
/**
* Debug host dispatch callback function.
*/
typedef void (*HostDispatchHandler)();
/**
* Callback function for the host to ensure debug messages are processed.
*/
......@@ -162,10 +157,6 @@ class V8_EXPORT Debug {
static bool SetDebugEventListener2(EventCallback2 that,
Handle<Value> data = Handle<Value>());
// Set a JavaScript debug event listener.
static bool SetDebugEventListener(v8::Handle<v8::Object> that,
Handle<Value> data = Handle<Value>());
// Schedule a debugger break to happen when JavaScript code is run
// in the given isolate.
static void DebugBreak(Isolate* isolate);
......@@ -193,10 +184,6 @@ class V8_EXPORT Debug {
const uint16_t* command, int length,
ClientData* client_data = NULL);
// Dispatch interface.
static void SetHostDispatchHandler(HostDispatchHandler handler,
int period = 100);
/**
* Register a callback function to be called when a debug message has been
* received and is ready to be processed. For the debug messages to be
......
......@@ -6805,17 +6805,6 @@ bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
}
bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
Handle<Value> data) {
i::Isolate* isolate = i::Isolate::Current();
ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
ENTER_V8(isolate);
isolate->debugger()->SetEventListener(Utils::OpenHandle(*that),
Utils::OpenHandle(*data, true));
return true;
}
void Debug::DebugBreak(Isolate* isolate) {
reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
}
......@@ -6851,16 +6840,6 @@ void Debug::SendCommand(Isolate* isolate,
}
void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
int period) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler");
ENTER_V8(isolate);
isolate->debugger()->SetHostDispatchHandler(
handler, i::TimeDelta::FromMilliseconds(period));
}
void Debug::SetDebugMessageDispatchHandler(
DebugMessageDispatchHandler handler, bool provide_locker) {
i::Isolate* isolate = i::Isolate::Current();
......
......@@ -49,18 +49,6 @@ Debug::~Debug() {
}
static void PrintLn(v8::Local<v8::Value> value) {
v8::Local<v8::String> s = value->ToString();
ScopedVector<char> data(s->Utf8Length() + 1);
if (data.start() == NULL) {
V8::FatalProcessOutOfMemory("PrintLn");
return;
}
s->WriteUtf8(data.start());
PrintF("%s\n", data.start());
}
static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
// Isolate::context() may have been NULL when "script collected" event
......@@ -2674,10 +2662,8 @@ Debugger::Debugger(Isolate* isolate)
force_debugger_active_(false),
message_handler_(NULL),
debugger_unload_pending_(false),
host_dispatch_handler_(NULL),
debug_message_dispatch_handler_(NULL),
message_dispatch_helper_thread_(NULL),
host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
agent_(NULL),
command_queue_(isolate->logger(), kQueueInitialSize),
command_received_(0),
......@@ -3067,7 +3053,6 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
bool auto_continue) {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
HandleScope scope(isolate_);
if (!isolate_->debug()->Load()) return;
......@@ -3121,45 +3106,24 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
return;
}
v8::TryCatch try_catch;
// DebugCommandProcessor goes here.
v8::Local<v8::Object> cmd_processor;
{
v8::Local<v8::Object> api_exec_state =
v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
v8::Local<v8::String> fun_name = v8::String::NewFromUtf8(
isolate, "debugCommandProcessor");
v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { running };
cmd_processor = v8::Local<v8::Object>::Cast(
fun->Call(api_exec_state, kArgc, argv));
if (try_catch.HasCaught()) {
PrintLn(try_catch.Exception());
return;
}
}
bool running = auto_continue;
Handle<Object> cmd_processor_ctor = Object::GetProperty(
isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
Handle<Object> cmd_processor = Execution::Call(
isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
Object::GetProperty(
isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
Handle<Object> is_running = Object::GetProperty(
isolate_, cmd_processor, "isRunning").ToHandleChecked();
// Process requests from the debugger.
while (true) {
do {
// Wait for new command in the queue.
if (Debugger::host_dispatch_handler_) {
// In case there is a host dispatch - do periodic dispatches.
if (!command_received_.WaitFor(host_dispatch_period_)) {
// Timout expired, do the dispatch.
Debugger::host_dispatch_handler_();
continue;
}
} else {
// In case there is no host dispatch - just wait.
command_received_.Wait();
}
command_received_.Wait();
// Get the command from the queue.
CommandMessage command = command_queue_.Get();
......@@ -3171,69 +3135,50 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
return;
}
// Invoke JavaScript to process the debug request.
v8::Local<v8::String> fun_name;
v8::Local<v8::Function> fun;
v8::Local<v8::Value> request;
v8::TryCatch try_catch;
fun_name = v8::String::NewFromUtf8(isolate, "processDebugRequest");
fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
request = v8::String::NewFromTwoByte(isolate, command.text().start(),
v8::String::kNormalString,
command.text().length());
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { request };
v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
// Get the response.
v8::Local<v8::String> response;
if (!try_catch.HasCaught()) {
// Get response string.
if (!response_val->IsUndefined()) {
response = v8::Local<v8::String>::Cast(response_val);
Vector<const uc16> command_text(
const_cast<const uc16*>(command.text().start()),
command.text().length());
Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
command_text).ToHandleChecked();
Handle<Object> request_args[] = { request_text };
Handle<Object> exception;
Handle<Object> answer_value;
Handle<String> answer;
MaybeHandle<Object> maybe_result = Execution::TryCall(
process_debug_request, cmd_processor, 1, request_args, &exception);
if (maybe_result.ToHandle(&answer_value)) {
if (answer_value->IsUndefined()) {
answer = isolate_->factory()->empty_string();
} else {
response = v8::String::NewFromUtf8(isolate, "");
answer = Handle<String>::cast(answer_value);
}
// Log the JSON request/response.
if (FLAG_trace_debug_json) {
PrintLn(request);
PrintLn(response);
PrintF("%s\n", request_text->ToCString().get());
PrintF("%s\n", answer->ToCString().get());
}
// Get the running state.
fun_name = v8::String::NewFromUtf8(isolate, "isRunning");
fun = v8::Local<v8::Function>::Cast(cmd_processor->Get(fun_name));
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { response };
v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
if (!try_catch.HasCaught()) {
running = running_val->ToBoolean()->Value();
}
Handle<Object> is_running_args[] = { answer };
maybe_result = Execution::Call(
isolate_, is_running, cmd_processor, 1, is_running_args);
running = maybe_result.ToHandleChecked()->IsTrue();
} else {
// In case of failure the result text is the exception text.
response = try_catch.Exception()->ToString();
answer = Handle<String>::cast(
Execution::ToString(isolate_, exception).ToHandleChecked());
}
// Return the result.
MessageImpl message = MessageImpl::NewResponse(
event,
running,
Handle<JSObject>::cast(exec_state),
Handle<JSObject>::cast(event_data),
Handle<String>(Utils::OpenHandle(*response)),
command.client_data());
event, running, exec_state, event_data, answer, command.client_data());
InvokeMessageHandler(message);
command.Dispose();
// Return from debug event processing if either the VM is put into the
// running state (through a continue command) or auto continue is active
// and there are no more commands queued.
if (running && !HasCommands()) {
return;
}
}
} while (!running || HasCommands());
}
......@@ -3301,13 +3246,6 @@ void Debugger::ListenersChanged() {
}
void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
TimeDelta period) {
host_dispatch_handler_ = handler;
host_dispatch_period_ = period;
}
void Debugger::SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
......
......@@ -783,8 +783,6 @@ class Debugger {
bool auto_continue);
void SetEventListener(Handle<Object> callback, Handle<Object> data);
void SetMessageHandler(v8::Debug::MessageHandler2 handler);
void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
TimeDelta period);
void SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler,
bool provide_locker);
......@@ -890,11 +888,10 @@ class Debugger {
bool force_debugger_active_; // Activate debugger without event listeners.
v8::Debug::MessageHandler2 message_handler_;
bool debugger_unload_pending_; // Was message handler cleared?
v8::Debug::HostDispatchHandler host_dispatch_handler_;
Mutex dispatch_handler_access_; // Mutex guarding dispatch handler.
v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
MessageDispatchHelperThread* message_dispatch_helper_thread_;
TimeDelta host_dispatch_period_;
DebuggerAgent* agent_;
......
......@@ -5788,108 +5788,6 @@ TEST(DebuggerClearMessageHandlerWhileActive) {
}
/* Test DebuggerHostDispatch */
/* In this test, the debugger waits for a command on a breakpoint
* and is dispatching host commands while in the infinite loop.
*/
class HostDispatchV8Thread : public v8::internal::Thread {
public:
HostDispatchV8Thread() : Thread("HostDispatchV8Thread") { }
void Run();
};
class HostDispatchDebuggerThread : public v8::internal::Thread {
public:
HostDispatchDebuggerThread() : Thread("HostDispatchDebuggerThread") { }
void Run();
};
Barriers* host_dispatch_barriers;
static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
static char print_buffer[1000];
v8::String::Value json(message.GetJSON());
Utf16ToAscii(*json, json.length(), print_buffer);
}
static void HostDispatchDispatchHandler() {
host_dispatch_barriers->semaphore_1.Signal();
}
void HostDispatchV8Thread::Run() {
const char* source_1 = "var y_global = 3;\n"
"function cat( new_value ) {\n"
" var x = new_value;\n"
" y_global = 4;\n"
" x = 3 * x + 1;\n"
" y_global = 5;\n"
" return x;\n"
"}\n"
"\n";
const char* source_2 = "cat(17);\n";
v8::Isolate::Scope isolate_scope(CcTest::isolate());
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
// Set up message and host dispatch handlers.
v8::Debug::SetMessageHandler2(HostDispatchMessageHandler);
v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */);
CompileRun(source_1);
host_dispatch_barriers->barrier_1.Wait();
host_dispatch_barriers->barrier_2.Wait();
CompileRun(source_2);
}
void HostDispatchDebuggerThread::Run() {
const int kBufSize = 1000;
uint16_t buffer[kBufSize];
const char* command_1 = "{\"seq\":101,"
"\"type\":\"request\","
"\"command\":\"setbreakpoint\","
"\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
const char* command_2 = "{\"seq\":102,"
"\"type\":\"request\","
"\"command\":\"continue\"}";
v8::Isolate* isolate = CcTest::isolate();
// v8 thread initializes, runs source_1
host_dispatch_barriers->barrier_1.Wait();
// 1: Set breakpoint in cat().
v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer));
host_dispatch_barriers->barrier_2.Wait();
// v8 thread starts compiling source_2.
// Break happens, to run queued commands and host dispatches.
// Wait for host dispatch to be processed.
host_dispatch_barriers->semaphore_1.Wait();
// 2: Continue evaluation
v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer));
}
TEST(DebuggerHostDispatch) {
HostDispatchDebuggerThread host_dispatch_debugger_thread;
HostDispatchV8Thread host_dispatch_v8_thread;
// Create a V8 environment
Barriers stack_allocated_host_dispatch_barriers;
host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
host_dispatch_v8_thread.Start();
host_dispatch_debugger_thread.Start();
host_dispatch_v8_thread.Join();
host_dispatch_debugger_thread.Join();
}
/* Test DebugMessageDispatch */
/* In this test, the V8 thread waits for a message from the debug thread.
* The DebugMessageDispatchHandler is executed from the debugger thread
......
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