Author: [email protected]
Date: Wed Apr 22 07:16:50 2009
New Revision: 1773

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

Log:
DevTools: Add support for eventless host message dispatching.

Review URL: http://codereview.chromium.org/87026

Modified: branches/bleeding_edge/include/v8-debug.h
==============================================================================
--- branches/bleeding_edge/include/v8-debug.h   (original)
+++ branches/bleeding_edge/include/v8-debug.h   Wed Apr 22 07:16:50 2009
@@ -124,12 +124,8 @@

    /**
     * Debug host dispatch callback function.
-   *
-   * \param dispatch the dispatch value
-   * \param data the data value passed when registering the dispatch  
handler
     */
-  typedef void (*HostDispatchHandler)(ClientData* dispatch);
-
+  typedef void (*HostDispatchHandler)();

    // Set a C debug event listener.
    static bool SetDebugEventListener(EventCallback that,
@@ -149,8 +145,8 @@
                            ClientData* client_data = NULL);

    // Dispatch interface.
-  static void SetHostDispatchHandler(HostDispatchHandler handler);
-  static void SendHostDispatch(ClientData* dispatch);
+  static void SetHostDispatchHandler(HostDispatchHandler handler,
+                                     int period = 100);

   /**
    * Run a JavaScript function in the debugger.

Modified: branches/bleeding_edge/src/api.cc
==============================================================================
--- branches/bleeding_edge/src/api.cc   (original)
+++ branches/bleeding_edge/src/api.cc   Wed Apr 22 07:16:50 2009
@@ -3276,16 +3276,11 @@
  }


-void Debug::SetHostDispatchHandler(HostDispatchHandler handler) {
+void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
+                                   int period) {
    EnsureInitialized("v8::Debug::SetHostDispatchHandler");
    ENTER_V8;
-  i::Debugger::SetHostDispatchHandler(handler);
-}
-
-
-void Debug::SendHostDispatch(ClientData* dispatch) {
-  if (!i::V8::HasBeenSetup()) return;
-  i::Debugger::ProcessHostDispatch(dispatch);
+  i::Debugger::SetHostDispatchHandler(handler, period);
  }



Modified: branches/bleeding_edge/src/debug.cc
==============================================================================
--- branches/bleeding_edge/src/debug.cc (original)
+++ branches/bleeding_edge/src/debug.cc Wed Apr 22 07:16:50 2009
@@ -1424,6 +1424,7 @@
  v8::Debug::MessageHandler Debugger::message_handler_ = NULL;
  bool Debugger::message_handler_cleared_ = false;
  v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
+int Debugger::host_dispatch_micros_ = 100 * 1000;
  DebuggerAgent* Debugger::agent_ = NULL;
  LockingMessageQueue Debugger::command_queue_(kQueueInitialSize);
  LockingMessageQueue Debugger::message_queue_(kQueueInitialSize);
@@ -1827,7 +1828,17 @@
    // Process requests from the debugger.
    while (true) {
      // Wait for new command in the queue.
-    command_received_->Wait();
+    if (Debugger::host_dispatch_handler_) {
+      // In case there is a host dispatch - do periodic dispatches.
+      if (!command_received_->Wait(host_dispatch_micros_)) {
+        // Timout expired, do the dispatch.
+        Debugger::host_dispatch_handler_();
+        continue;
+      }
+    } else {
+      // In case there is no host dispatch - just wait.
+      command_received_->Wait();
+    }

      // The debug command interrupt flag might have been set when the  
command was
      // added.
@@ -1842,19 +1853,6 @@
        return;
      }

-    // Check if the command is a host dispatch.
-    if (command.IsHostDispatch()) {
-      if (Debugger::host_dispatch_handler_) {
-        Debugger::host_dispatch_handler_(command.client_data());
-        // Delete the dispatch.
-        command.Dispose();
-      }
-      if (auto_continue && !HasCommands()) {
-        return;
-      }
-      continue;
-    }
-
      // Invoke JavaScript to process the debug request.
      v8::Local<v8::String> fun_name;
      v8::Local<v8::Function> fun;
@@ -1971,8 +1969,10 @@
  }


-void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler  
handler) {
+void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler  
handler,
+                                      int period) {
    host_dispatch_handler_ = handler;
+  host_dispatch_micros_ = period * 1000;
  }


@@ -2067,19 +2067,6 @@
  }


-void Debugger::ProcessHostDispatch(v8::Debug::ClientData* dispatch) {
-  // Puts a host dispatch comming from the public API on the queue.
-  Logger::DebugTag("Put dispatch on command_queue.");
-  command_queue_.Put(Message::NewHostDispatch(dispatch));
-  command_received_->Signal();
-
-  // Set the debug command break flag to have the host dispatch processed.
-  if (!Debug::InDebugger()) {
-    StackGuard::DebugCommand();
-  }
-}
-
-
  bool Debugger::IsDebuggerActive() {
    ScopedLock with(debugger_access_);

@@ -2168,17 +2155,14 @@


  Message::Message() : text_(Vector<uint16_t>::empty()),
-                     client_data_(NULL),
-                     is_host_dispatch_(false) {
+                     client_data_(NULL) {
  }


  Message::Message(const Vector<uint16_t>& text,
-                 v8::Debug::ClientData* data,
-                 bool is_host_dispatch)
+                 v8::Debug::ClientData* data)
      : text_(text),
-      client_data_(data),
-      is_host_dispatch_(is_host_dispatch) {
+      client_data_(data) {
  }


@@ -2193,19 +2177,9 @@
  }


-bool Message::IsHostDispatch() const {
-  return is_host_dispatch_;
-}
-
-
  Message Message::NewCommand(const Vector<uint16_t>& command,
                              v8::Debug::ClientData* data) {
-  return Message(command.Clone(), data, false);
-}
-
-
-Message Message::NewHostDispatch(v8::Debug::ClientData* dispatch) {
-  return Message(Vector<uint16_t>::empty(), dispatch, true);
+  return Message(command.Clone(), data);
  }


@@ -2217,7 +2191,7 @@
      text = Vector<uint16_t>::New(output->Length());
      output->Write(text.start(), 0, output->Length());
    }
-  return Message(text, data, false);
+  return Message(text, data);
  }



Modified: branches/bleeding_edge/src/debug.h
==============================================================================
--- branches/bleeding_edge/src/debug.h  (original)
+++ branches/bleeding_edge/src/debug.h  Wed Apr 22 07:16:50 2009
@@ -409,7 +409,6 @@
   public:
    static Message NewCommand(const Vector<uint16_t>& command,
                              v8::Debug::ClientData* data);
-  static Message NewHostDispatch(v8::Debug::ClientData* dispatch);
    static Message NewOutput(v8::Handle<v8::String> output,
                             v8::Debug::ClientData* data);
    static Message NewEmptyMessage();
@@ -418,17 +417,14 @@

    // Deletes user data and disposes of the text.
    void Dispose();
-  bool IsHostDispatch() const;
    Vector<uint16_t> text() const { return text_; }
    v8::Debug::ClientData* client_data() const { return client_data_; }
   private:
    Message(const Vector<uint16_t>& text,
-          v8::Debug::ClientData* data,
-          bool is_host_dispatch);
+          v8::Debug::ClientData* data);

    Vector<uint16_t> text_;
    v8::Debug::ClientData* client_data_;
-  bool is_host_dispatch_;
  };

  // A Queue of Vector<uint16_t> objects.  A thread-safe version is
@@ -510,7 +506,8 @@
    static void SetMessageHandler(v8::Debug::MessageHandler handler,
                                  bool message_handler_thread);
    static void TearDown();
-  static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler  
handler);
+  static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler  
handler,
+                                     int period);

    // Invoke the message handler function.
    static void InvokeMessageHandler(Message message);
@@ -529,7 +526,6 @@
    // Check whether there are commands in the command queue.
    static bool HasCommands();

-  static void ProcessHostDispatch(v8::Debug::ClientData* dispatch);
    static Handle<Object> Call(Handle<JSFunction> fun,
                               Handle<Object> data,
                               bool* pending_exception);
@@ -576,6 +572,7 @@
    static v8::Debug::MessageHandler message_handler_;
    static bool message_handler_cleared_;  // Was message handler cleared?
    static v8::Debug::HostDispatchHandler host_dispatch_handler_;
+  static int host_dispatch_micros_;

    static DebuggerAgent* agent_;


Modified: branches/bleeding_edge/test/cctest/test-debug.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-debug.cc    (original)
+++ branches/bleeding_edge/test/cctest/test-debug.cc    Wed Apr 22 07:16:50  
2009
@@ -3564,13 +3564,17 @@
                                    new TestClientData()));
      queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
                                    new TestClientData()));
-    queue.Put(Message::NewHostDispatch(new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
      ASSERT_EQ(0, TestClientData::destructor_call_counter);
      queue.Get().Dispose();
      ASSERT_EQ(1, TestClientData::destructor_call_counter);
-    queue.Put(Message::NewHostDispatch(new TestClientData()));
-    queue.Put(Message::NewHostDispatch(new TestClientData()));
-    queue.Put(Message::NewHostDispatch(new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
+    queue.Put(Message::NewCommand(Vector<uint16_t>::empty(),
+                                  new TestClientData()));
      queue.Put(Message::NewOutput(v8::Handle<v8::String>(),
                                   new TestClientData()));
      queue.Put(Message::NewEmptyMessage());
@@ -4219,53 +4223,107 @@
  }


-int host_dispatch_hit_count = 0;
-static void HostDispatchHandlerHitCount(v8::Debug::ClientData* dispatch) {
-  host_dispatch_hit_count++;
+/* 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:
+  void Run();
+};
+
+class HostDispatchDebuggerThread : public v8::internal::Thread {
+ public:
+  void Run();
+};
+
+Barriers* host_dispatch_barriers;
+
+static void HostDispatchMessageHandler(const uint16_t* message,
+                                       int length,
+                                       v8::Debug::ClientData* client_data)  
{
+  static char print_buffer[1000];
+  Utf16ToAscii(message, length, print_buffer);
+  printf("%s\n", print_buffer);
+  fflush(stdout);
  }


-// Test that clearing the debug event listener actually clears all break  
points
-// and related information.
-TEST(DebuggerHostDispatch) {
-  i::FLAG_debugger_auto_break = true;
+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::HandleScope scope;
    DebugLocalContext env;

-  const int kBufferSize = 1000;
-  uint16_t buffer[kBufferSize];
-  const char* command_continue =
-    "{\"seq\":0,"
-     "\"type\":\"request\","
-     "\"command\":\"continue\"}";
+  // Setup message and host dispatch handlers.
+  v8::Debug::SetMessageHandler(HostDispatchMessageHandler);
+  v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms  
*/);

-  // Create an empty function to call for processing debug commands
-  v8::Local<v8::Function> empty =
-      CompileFunction(&env, "function empty(){}", "empty");
+  CompileRun(source_1);
+  host_dispatch_barriers->barrier_1.Wait();
+  host_dispatch_barriers->barrier_2.Wait();
+  CompileRun(source_2);
+}

-  // Setup message and host dispatch handlers.
-  v8::Debug::SetMessageHandler(DummyMessageHandler);
-  v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount);

-  // Send a host dispatch by itself.
-  v8::Debug::SendHostDispatch(NULL);
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate  
debugger.
-  CHECK_EQ(1, host_dispatch_hit_count);
+void HostDispatchDebuggerThread::Run() {
+  const int kBufSize = 1000;
+  uint16_t buffer[kBufSize];

-  // Fill a host dispatch and a continue command on the command queue.
-  v8::Debug::SendHostDispatch(NULL);
-  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate  
debugger.
+  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\"}";

-  // Fill a continue command and a host dispatch on the command queue.
-  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
-  v8::Debug::SendHostDispatch(NULL);
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate  
debugger.
-  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate  
debugger.
+  // v8 thread initializes, runs source_1
+  host_dispatch_barriers->barrier_1.Wait();
+  // 1: Set breakpoint in cat().
+  v8::Debug::SendCommand(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(buffer, AsciiToUtf16(command_2, buffer));
+}
+
+HostDispatchDebuggerThread host_dispatch_debugger_thread;
+HostDispatchV8Thread host_dispatch_v8_thread;
+
+
+TEST(DebuggerHostDispatch) {
+  i::FLAG_debugger_auto_break = true;
+
+  // Create a V8 environment
+  Barriers stack_allocated_host_dispatch_barriers;
+  stack_allocated_host_dispatch_barriers.Initialize();
+  host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
+
+  host_dispatch_v8_thread.Start();
+  host_dispatch_debugger_thread.Start();

-  // All the host dispatch callback should be called.
-  CHECK_EQ(3, host_dispatch_hit_count);
+  host_dispatch_v8_thread.Join();
+  host_dispatch_debugger_thread.Join();
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to