Revision: 3623
Author: [email protected]
Date: Fri Jan 15 13:14:56 2010
Log: Implement issue 554 Add "ProcessDebuggerRequests" call to Debug Agent API

Review URL: http://codereview.chromium.org/549057
http://code.google.com/p/v8/source/detail?r=3623

Modified:
 /branches/bleeding_edge/include/v8-debug.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/execution.cc
 /branches/bleeding_edge/src/execution.h
 /branches/bleeding_edge/test/cctest/test-debug.cc

=======================================
--- /branches/bleeding_edge/include/v8-debug.h  Fri Dec 18 12:30:29 2009
+++ /branches/bleeding_edge/include/v8-debug.h  Fri Jan 15 13:14:56 2010
@@ -263,6 +263,43 @@
   */
   static bool EnableAgent(const char* name, int port,
                           bool wait_for_connection = false);
+
+  /**
+   * Makes V8 process all pending debug messages.
+   *
+ * From V8 point of view all debug messages come asynchronously (e.g. from
+   * remote debugger) but they all must be handled synchronously: V8 cannot
+   * do 2 things at one time so normal script execution must be interrupted
+   * for a while.
+   *
+   * Generally when message arrives V8 may be in one of 3 states:
+ * 1. V8 is running script; V8 will automatically interrupt and process all
+   * pending messages (however auto_break flag should be enabled);
+   * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated
+   * to reading and processing debug messages;
+ * 3. V8 is not running at all or has called some long-working C++ function; + * by default it means that processing of all debug message will be deferred + * until V8 gets control again; however, embedding application may improve
+   * this by manually calling this method.
+   *
+ * It makes sense to call this method whenever a new debug message arrived and + * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler
+   * should help with the former condition.
+   *
+ * Technically this method in many senses is equivalent to executing empty
+   * script:
+   * 1. It does nothing except for processing all pending debug messages.
+ * 2. It should be invoked with the same precautions and from the same context
+   * as V8 script would be invoked from, because:
+   *   a. with "evaluate" command it can do whatever normal script can do,
+   *   including all native calls;
+   *   b. no other thread should call V8 while this method is running
+   *   (v8::Locker may be used here).
+   *
+   * "Evaluate" debug command behavior currently is not specified in scope
+   * of this method.
+   */
+  static void ProcessDebugMessages();
 };


=======================================
--- /branches/bleeding_edge/src/api.cc  Fri Dec 18 12:30:29 2009
+++ /branches/bleeding_edge/src/api.cc  Fri Jan 15 13:14:56 2010
@@ -3744,6 +3744,11 @@
bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
   return i::Debugger::StartAgent(name, port, wait_for_connection);
 }
+
+void Debug::ProcessDebugMessages() {
+  i::Execution::ProcessDebugMesssages(true);
+}
+
 #endif  // ENABLE_DEBUGGER_SUPPORT

 namespace internal {
=======================================
--- /branches/bleeding_edge/src/execution.cc    Mon Dec 21 02:24:11 2009
+++ /branches/bleeding_edge/src/execution.cc    Fri Jan 15 13:14:56 2010
@@ -638,24 +638,32 @@
   bool debug_command_only =
       StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();

-  // Clear the debug request flags.
+  // Clear the debug break request flag.
   StackGuard::Continue(DEBUGBREAK);
+
+  ProcessDebugMesssages(debug_command_only);
+
+  // Return to continue execution.
+  return Heap::undefined_value();
+}
+
+void Execution::ProcessDebugMesssages(bool debug_command_only) {
+  // Clear the debug command request flag.
   StackGuard::Continue(DEBUGCOMMAND);

   HandleScope scope;
   // Enter the debugger. Just continue if we fail to enter the debugger.
   EnterDebugger debugger;
   if (debugger.FailedToEnter()) {
-    return Heap::undefined_value();
+    return;
   }

// Notify the debug event listeners. Indicate auto continue if the break was
   // a debug command break.
   Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
-
-  // Return to continue execution.
-  return Heap::undefined_value();
-}
+}
+
+
 #endif

 Object* Execution::HandleStackGuardInterrupt() {
=======================================
--- /branches/bleeding_edge/src/execution.h     Thu Nov  5 05:59:40 2009
+++ /branches/bleeding_edge/src/execution.h     Fri Jan 15 13:14:56 2010
@@ -122,6 +122,7 @@
                                           Handle<Object> is_global);
 #ifdef ENABLE_DEBUGGER_SUPPORT
   static Object* DebugBreakHelper();
+  static void ProcessDebugMesssages(bool debug_command_only);
 #endif

   // If the stack guard is triggered, but it is not an actual
=======================================
--- /branches/bleeding_edge/test/cctest/test-debug.cc Tue Dec 15 01:34:00 2009 +++ /branches/bleeding_edge/test/cctest/test-debug.cc Fri Jan 15 13:14:56 2010
@@ -5653,6 +5653,51 @@
   v8::Debug::SetMessageHandler2(NULL);
   CheckDebuggerUnloaded();
 }
+
+
+static int counting_message_handler_counter;
+
+static void CountingMessageHandler(const v8::Debug::Message& message) {
+  counting_message_handler_counter++;
+}
+
+// Test that debug messages get processed when ProcessDebugMessages is called.
+TEST(ProcessDebugMessages) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  counting_message_handler_counter = 0;
+
+  v8::Debug::SetMessageHandler2(CountingMessageHandler);
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* scripts_command =
+    "{\"seq\":0,"
+     "\"type\":\"request\","
+     "\"command\":\"scripts\"}";
+
+  // Send scripts command.
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+
+  CHECK_EQ(0, counting_message_handler_counter);
+  v8::Debug::ProcessDebugMessages();
+  // At least one message should come
+  CHECK_GE(counting_message_handler_counter, 1);
+
+  counting_message_handler_counter = 0;
+
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(scripts_command, buffer));
+  CHECK_EQ(0, counting_message_handler_counter);
+  v8::Debug::ProcessDebugMessages();
+  // At least two messages should come
+  CHECK_GE(counting_message_handler_counter, 2);
+
+  // Get rid of the debug message handler.
+  v8::Debug::SetMessageHandler2(NULL);
+  CheckDebuggerUnloaded();
+}


 TEST(GetMirror) {
-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to