1. Send 'afterCompile' event to the debug message handler.2. Process messages from...
authoryurys@chromium.org <yurys@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 27 Apr 2009 12:38:20 +0000 (12:38 +0000)
committeryurys@chromium.org <yurys@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 27 Apr 2009 12:38:20 +0000 (12:38 +0000)
Review URL: http://codereview.chromium.org/100034

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1801 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/debug-delay.js
src/debug.cc
test/cctest/test-debug.cc

index 961f304..4a8663b 100644 (file)
@@ -977,6 +977,7 @@ CompileEvent.prototype.script = function() {
 
 CompileEvent.prototype.toJSONProtocol = function() {
   var o = new ProtocolMessage();
+  o.running = true;
   if (this.before_) {
     o.event = "beforeCompile";
   } else {
index 239a373..441a38e 100644 (file)
@@ -1612,7 +1612,7 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
   }
 
   // Process debug event
-  ProcessDebugEvent(v8::BeforeCompile, event_data, false);
+  ProcessDebugEvent(v8::BeforeCompile, event_data, true);
 }
 
 
@@ -1673,7 +1673,7 @@ void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
     return;
   }
   // Process debug event
-  ProcessDebugEvent(v8::AfterCompile, event_data, false);
+  ProcessDebugEvent(v8::AfterCompile, event_data, true);
 }
 
 
@@ -1698,7 +1698,7 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
     return;
   }
   // Process debug event.
-  ProcessDebugEvent(v8::NewFunction, event_data, false);
+  ProcessDebugEvent(v8::NewFunction, event_data, true);
 }
 
 
@@ -1776,17 +1776,18 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
   if (!Debug::Load()) return;
 
   // Process the individual events.
-  bool interactive = false;
+  bool sendEventMessage = false;
   switch (event) {
     case v8::Break:
-      interactive = true;  // Break event is always interactive
+      sendEventMessage = !auto_continue;
       break;
     case v8::Exception:
-      interactive = true;  // Exception event is always interactive
+      sendEventMessage = true;
       break;
     case v8::BeforeCompile:
       break;
     case v8::AfterCompile:
+      sendEventMessage = true;
       break;
     case v8::NewFunction:
       break;
@@ -1794,8 +1795,20 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
       UNREACHABLE();
   }
 
-  // Done if not interactive.
-  if (!interactive) return;
+  // The debug command interrupt flag might have been set when the command was
+  // added. It should be enough to clear the flag only once while we are in the
+  // debugger.
+  ASSERT(Debug::InDebugger());
+  StackGuard::Continue(DEBUGCOMMAND);
+
+  // Notify the debugger that a debug event has occurred unless auto continue is
+  // active in which case no event is send.
+  if (sendEventMessage) {
+    InvokeMessageHandlerWithEvent(event_data);
+  }
+  if (auto_continue && !HasCommands()) {
+    return;
+  }
 
   // Get the DebugCommandProcessor.
   v8::Local<v8::Object> api_exec_state =
@@ -1812,16 +1825,6 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
     return;
   }
 
-  // Notify the debugger that a debug event has occurred unless auto continue is
-  // active in which case no event is send.
-  if (!auto_continue) {
-    bool success = InvokeMessageHandlerWithEvent(event_data);
-    if (!success) {
-      // If failed to notify debugger just continue running.
-      return;
-    }
-  }
-
   // Process requests from the debugger.
   while (true) {
     // Wait for new command in the queue.
@@ -1837,10 +1840,6 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
       command_received_->Wait();
     }
 
-    // The debug command interrupt flag might have been set when the command was
-    // added.
-    StackGuard::Continue(DEBUGCOMMAND);
-
     // Get the command from the queue.
     CommandMessage command = command_queue_.Get();
     Logger::DebugTag("Got request from command queue, in interactive loop.");
index ca2d49e..20eaffd 100644 (file)
@@ -3436,6 +3436,7 @@ static void MessageHandler(const uint16_t* message, int length,
     // Signals when a break is reported.
     message_queue_barriers.semaphore_2->Signal();
   }
+
   // Allow message handler to block on a semaphore, to test queueing of
   // messages while blocked.
   message_queue_barriers.semaphore_1->Wait();
@@ -3474,6 +3475,7 @@ void MessageQueueDebuggerThread::Run() {
 
   /* Interleaved sequence of actions by the two threads:*/
   // Main thread compiles and runs source_1
+  message_queue_barriers.semaphore_1->Signal();
   message_queue_barriers.barrier_1.Wait();
   // Post 6 commands, filling the command queue and making it expand.
   // These calls return immediately, but the commands stay on the queue
@@ -3487,22 +3489,39 @@ void MessageQueueDebuggerThread::Run() {
   v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
   message_queue_barriers.barrier_2.Wait();
   // Main thread compiles and runs source_2.
-  // Queued commands are executed at the start of compilation of source_2.
-  message_queue_barriers.barrier_3.Wait();
-  // Free the message handler to process all the messages from the queue.
-  for (int i = 0; i < 20 ; ++i) {
+  // Queued commands are executed at the start of compilation of source_2(
+  // beforeCompile event).
+  // Free the message handler to process all the messages from the queue. 7
+  // messages are expected: 2 afterCompile events and 5 responses.
+  // All the commands added so far will fail to execute as long as call stack
+  // is empty on beforeCompile event.
+  for (int i = 0; i < 6 ; ++i) {
     message_queue_barriers.semaphore_1->Signal();
   }
+  message_queue_barriers.barrier_3.Wait();
   // Main thread compiles and runs source_3.
+  // Don't stop in the afterCompile handler.
+  message_queue_barriers.semaphore_1->Signal();
   // source_3 includes a debugger statement, which causes a break event.
   // Wait on break event from hitting "debugger" statement
   message_queue_barriers.semaphore_2->Wait();
   // These should execute after the "debugger" statement in source_2
+  v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_1, buffer_1));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_2, buffer_2));
+  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
   v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_single_step, buffer_2));
+  // Run after 2 break events, 4 responses.
+  for (int i = 0; i < 6 ; ++i) {
+    message_queue_barriers.semaphore_1->Signal();
+  }
   // Wait on break event after a single step executes.
   message_queue_barriers.semaphore_2->Wait();
   v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_2, buffer_1));
   v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_continue, buffer_2));
+  // Run after 2 responses.
+  for (int i = 0; i < 2 ; ++i) {
+    message_queue_barriers.semaphore_1->Signal();
+  }
   // Main thread continues running source_3 to end, waits for this thread.
 }
 
@@ -3610,7 +3629,7 @@ TEST(SendClientDataToHandler) {
   TestClientData::ResetCounters();
   handled_client_data_instances_count = 0;
   v8::Debug::SetMessageHandler(MessageHandlerCountingClientData);
-  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5; debugger;";
+  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
   const int kBufferSize = 1000;
   uint16_t buffer[kBufferSize];
   const char* command_1 =
@@ -3635,8 +3654,9 @@ TEST(SendClientDataToHandler) {
                          new TestClientData());
   v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer),
                          new TestClientData());
-  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  // All the messages will be processed on beforeCompile event.
   CompileRun(source_1);
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
   CHECK_EQ(3, TestClientData::constructor_call_counter);
   CHECK_EQ(TestClientData::constructor_call_counter,
            handled_client_data_instances_count);