Removed the implicit call to DebugBreak when receiving debugger commands

while V8 is running.

A debugger using the V8 message based interface now needs to control the
call to DebugBreak in order for the messages send to be processed. Commands can
still be send when V8 is not in a break, but they will not be processed until
there is a break. The response "request queued" when queuing up messages have
been removed. This gets rid of a non JSON message being used.

Modified the threaded debugger tests to call DebugBreak instead of relying
on it occouring automatically.

This change will not be committed until the outstanding Chrome change
http://chrome-reviews.prom.corp.google.com/2072 (which updates Chrome to control
the DebugBreak call) have been reviewed and committed.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@47 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@gmail.com 2008-08-29 12:04:25 +00:00
parent 480a093f54
commit 6d4d692ec7
4 changed files with 6 additions and 138 deletions

View File

@ -366,24 +366,6 @@ function ProcessDebugRequest(exec_state, request, stopping) {
} }
// Helper function to check whether the JSON request is a plain break request.
// This is used form the runtime handling of pending debug requests. If one of
// the pending requests is a plain break execution should be broken after
// processing the pending break requests.
function IsPlainBreakRequest(json_request) {
try {
// Convert the JSON string to an object.
request = %CompileString('(' + json_request + ')', false)();
// Check for break command without arguments.
return request.command && request.command == "break" && !request.arguments;
} catch (e) {
// If there is a exception parsing the JSON request just return false.
return false;
}
}
Debug.addListener = function(listener, opt_data) { Debug.addListener = function(listener, opt_data) {
if (!IS_FUNCTION(listener)) throw new Error('Parameters have wrong types.'); if (!IS_FUNCTION(listener)) throw new Error('Parameters have wrong types.');
%AddDebugEventListener(listener, opt_data); %AddDebugEventListener(listener, opt_data);

View File

@ -1423,28 +1423,6 @@ Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
} }
bool Debugger::IsPlainBreakRequest(Handle<Object> request) {
// Get the function IsPlainBreakRequest (defined in debug.js).
Handle<JSFunction> process_debug_request =
Handle<JSFunction>(JSFunction::cast(
Debug::debug_context()->global()->GetProperty(
*Factory::LookupAsciiSymbol("IsPlainBreakRequest"))));
// Call ProcessDebugRequest expect String result.
bool caught_exception;
const int argc = 1;
Object** argv[argc] = { request.location() };
Handle<Object> result = Execution::TryCall(process_debug_request,
Factory::undefined_value(),
argc, argv,
&caught_exception);
if (caught_exception) {
return false;
}
return *result == Heap::true_value();
}
void Debugger::OnException(Handle<Object> exception, bool uncaught) { void Debugger::OnException(Handle<Object> exception, bool uncaught) {
HandleScope scope; HandleScope scope;
@ -1785,21 +1763,6 @@ void DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
} }
// Compare a two byte string to an null terminated ASCII string.
bool DebugMessageThread::TwoByteEqualsAscii(Vector<uint16_t> two_byte,
const char* ascii) {
for (int i = 0; i < two_byte.length(); i++) {
if (ascii[i] == '\0') {
return false;
}
if (two_byte[i] != static_cast<uint16_t>(ascii[i])) {
return false;
}
}
return ascii[two_byte.length()] == '\0';
}
void DebugMessageThread::Run() { void DebugMessageThread::Run() {
// Sends debug events to an installed debugger message callback. // Sends debug events to an installed debugger message callback.
while (true) { while (true) {
@ -1858,60 +1821,6 @@ void DebugMessageThread::DebugEvent(v8::DebugEvent event,
return; return;
} }
// First process all pending commands in the queue. During this processing
// each message is checked to see if it is a plain break command. If there is
// a plain break request in the queue or if the queue is empty a break event
// is sent to the debugger.
bool plain_break = false;
if (command_queue_.IsEmpty()) {
plain_break = true;
} else {
// Drain queue.
while (!command_queue_.IsEmpty()) {
command_received_->Wait();
Logger::DebugTag("Get command from command_queue, in drain queue loop.");
Vector<uint16_t> command = command_queue_.Get();
// Support for sending a break command as just "break" instead of an
// actual JSON break command.
// If break is made into a separate API call, function
// TwoByteEqualsASCII can be removed.
if (TwoByteEqualsAscii(command, "break")) {
plain_break = true;
continue;
}
// Get the command as a string object.
Handle<String> command_string;
if (!command.is_empty()) {
command_string = Factory::NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(
command.start()),
command.length()));
} else {
command_string = Handle<String>();
}
// Process the request.
Handle<String> message_string = Debugger::ProcessRequest(exec_state,
command_string,
false);
// Convert text result to UTF-16 string and send it.
v8::String::Value val(Utils::ToLocal(message_string));
Vector<uint16_t> message(reinterpret_cast<uint16_t*>(*val),
message_string->length());
SendMessage(message);
// Check whether one of the commands is a plain break request.
if (!plain_break) {
plain_break = Debugger::IsPlainBreakRequest(message_string);
}
}
}
// If this break event is not to go to the debugger just return.
if (!plain_break) return;
// Notify the debugger that a debug event has occoured. // Notify the debugger that a debug event has occoured.
host_running_ = false; host_running_ = false;
SetEventJSONFromEvent(event_data); SetEventJSONFromEvent(event_data);
@ -1998,13 +1907,6 @@ void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) {
Vector<uint16_t> command_copy = command.Clone(); Vector<uint16_t> command_copy = command.Clone();
Logger::DebugTag("Put command on command_queue."); Logger::DebugTag("Put command on command_queue.");
command_queue_.Put(command_copy); command_queue_.Put(command_copy);
// If not in a break schedule a break and send the "request queued" response.
if (host_running_) {
v8::Debug::DebugBreak();
uint16_t buffer[14] = {'r', 'e', 'q', 'u', 'e', 's', 't', ' ',
'q', 'u', 'e', 'u', 'e', 'd'};
SendMessage(Vector<uint16_t>(buffer, 14));
}
command_received_->Signal(); command_received_->Signal();
} }

View File

@ -346,8 +346,6 @@ class Debugger {
static Handle<String> ProcessRequest(Handle<Object> exec_state, static Handle<String> ProcessRequest(Handle<Object> exec_state,
Handle<Object> request, Handle<Object> request,
bool stopped); bool stopped);
static bool IsPlainBreakRequest(Handle<Object> request);
static void OnDebugBreak(Handle<Object> break_points_hit); static void OnDebugBreak(Handle<Object> break_points_hit);
static void OnException(Handle<Object> exception, bool uncaught); static void OnException(Handle<Object> exception, bool uncaught);
static void OnBeforeCompile(Handle<Script> script); static void OnBeforeCompile(Handle<Script> script);

View File

@ -2776,11 +2776,6 @@ class MessageQueueDebuggerThread : public v8::internal::Thread {
static void MessageHandler(const uint16_t* message, int length, void *data) { static void MessageHandler(const uint16_t* message, int length, void *data) {
static char print_buffer[1000]; static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer); Utf16ToAscii(message, length, print_buffer);
if (!strncmp(print_buffer, "request queued", 15)) {
// Ignore "request queued" messages before blocking message queue,
// by bumping semaphore to let them through.
message_queue_barriers.semaphore_1->Signal();
}
if (IsBreakEventMessage(print_buffer)) { if (IsBreakEventMessage(print_buffer)) {
// Lets test script wait until break occurs to send commands. // Lets test script wait until break occurs to send commands.
// Signals when a break is reported. // Signals when a break is reported.
@ -2878,6 +2873,7 @@ TEST(MessageQueues) {
CompileRun(source_1); CompileRun(source_1);
message_queue_barriers.barrier_1.Wait(); message_queue_barriers.barrier_1.Wait();
message_queue_barriers.barrier_2.Wait(); message_queue_barriers.barrier_2.Wait();
v8::Debug::DebugBreak();
CompileRun(source_2); CompileRun(source_2);
message_queue_barriers.barrier_3.Wait(); message_queue_barriers.barrier_3.Wait();
CompileRun(source_3); CompileRun(source_3);
@ -2909,9 +2905,6 @@ static void ThreadedMessageHandler(const uint16_t* message, int length,
void *data) { void *data) {
static char print_buffer[1000]; static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer); Utf16ToAscii(message, length, print_buffer);
if (!strncmp(print_buffer, "request queued", 15)) {
return;
}
if (IsBreakEventMessage(print_buffer)) { if (IsBreakEventMessage(print_buffer)) {
threaded_debugging_barriers.barrier_2.Wait(); threaded_debugging_barriers.barrier_2.Wait();
} }
@ -2950,22 +2943,19 @@ void DebuggerThread::Run() {
const int kBufSize = 1000; const int kBufSize = 1000;
uint16_t buffer[kBufSize]; uint16_t buffer[kBufSize];
const char* command_1 = "{\"seq\":101," const char* command_1 = "{\"seq\":102,"
"\"type\":\"request\","
"\"command\":\"break\"}";
const char* command_2 = "{\"seq\":102,"
"\"type\":\"request\"," "\"type\":\"request\","
"\"command\":\"evaluate\"," "\"command\":\"evaluate\","
"\"arguments\":{\"expression\":\"bar(false)\"}}"; "\"arguments\":{\"expression\":\"bar(false)\"}}";
const char* command_3 = "{\"seq\":103," const char* command_2 = "{\"seq\":103,"
"\"type\":\"request\"," "\"type\":\"request\","
"\"command\":\"continue\"}"; "\"command\":\"continue\"}";
threaded_debugging_barriers.barrier_1.Wait(); threaded_debugging_barriers.barrier_1.Wait();
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer)); v8::Debug::DebugBreak();
threaded_debugging_barriers.barrier_2.Wait(); threaded_debugging_barriers.barrier_2.Wait();
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer)); v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer));
} }
DebuggerThread debugger_thread; DebuggerThread debugger_thread;
@ -3010,11 +3000,6 @@ static void BreakpointsMessageHandler(const uint16_t* message,
void *data) { void *data) {
static char print_buffer[1000]; static char print_buffer[1000];
Utf16ToAscii(message, length, print_buffer); Utf16ToAscii(message, length, print_buffer);
if (!strncmp(print_buffer, "request queued", 15)) {
printf("%s\n", print_buffer);
fflush(stdout);
return;
}
printf("%s\n", print_buffer); printf("%s\n", print_buffer);
fflush(stdout); fflush(stdout);
@ -3098,6 +3083,7 @@ void BreakpointsDebuggerThread::Run() {
// v8 thread initializes, runs source_1 // v8 thread initializes, runs source_1
breakpoints_barriers->barrier_1.Wait(); breakpoints_barriers->barrier_1.Wait();
// 1:Set breakpoint in cat(). // 1:Set breakpoint in cat().
v8::Debug::DebugBreak();
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer)); v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
// 2:Set breakpoint in dog() // 2:Set breakpoint in dog()
v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer)); v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));