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
This commit is contained in:
parent
3976ebef93
commit
f56701f30c
@ -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
|
||||
|
21
src/api.cc
21
src/api.cc
@ -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();
|
||||
|
138
src/debug.cc
138
src/debug.cc
@ -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));
|
||||
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);
|
||||
|
||||
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);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user