Author: [email protected]
Date: Thu Feb 19 06:02:42 2009
New Revision: 1318

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:
Add host callback for debug break.

Add the ability to have the host embedding V8 receive a callback in the V8  
thread while V8 is processing a debug callback. When V8 is processing a  
debug callback the thread where V8 is executing is sitting in a tight loop  
processing debug commands until the continue command has been executed. In  
some embedding situations it is beneficial to be able to call back into the  
embedding host from the thread where V8 is sitting. The might have  
functions which needs to be called to complement the JavaScript debugging.

Using the uint16_t array to pass a void* is a temporary hack.
Review URL: http://codereview.chromium.org/20491

Modified: branches/bleeding_edge/include/v8-debug.h
==============================================================================
--- branches/bleeding_edge/include/v8-debug.h   (original)
+++ branches/bleeding_edge/include/v8-debug.h   Thu Feb 19 06:02:42 2009
@@ -99,12 +99,23 @@
   *
   * \param message the debug message
   * \param length length of the message
+ * \param data the data value passed when registering the message handler
   * A DebugMessageHandler does not take posession of the message string,
   * and must not rely on the data persisting after the handler returns.
   */
  typedef void (*DebugMessageHandler)(const uint16_t* message, int length,
                                      void* data);

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

  class EXPORT Debug {
   public:
@@ -122,6 +133,11 @@
    // Message based interface. The message protocol is JSON.
    static void SetMessageHandler(DebugMessageHandler handler, void* data =  
NULL);
    static void SendCommand(const uint16_t* command, int length);
+
+  // Dispatch interface.
+  static void SetHostDispatchHandler(DebugHostDispatchHandler handler,
+                                     void* data = NULL);
+  static void SendHostDispatch(void* dispatch);

   /**
    * 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   Thu Feb 19 06:02:42 2009
@@ -2924,6 +2924,19 @@
  }


+void Debug::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                   void* data) {
+  EnsureInitialized("v8::Debug::SetHostDispatchHandler");
+  i::Debugger::SetHostDispatchHandler(handler, data);
+}
+
+
+void Debug::SendHostDispatch(void* dispatch) {
+  if (!i::V8::HasBeenSetup()) return;
+  i::Debugger::ProcessHostDispatch(dispatch);
+}
+
+
  Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
                            v8::Handle<v8::Value> data) {
    if (!i::V8::HasBeenSetup()) return Handle<Value>();

Modified: branches/bleeding_edge/src/debug.cc
==============================================================================
--- branches/bleeding_edge/src/debug.cc (original)
+++ branches/bleeding_edge/src/debug.cc Thu Feb 19 06:02:42 2009
@@ -1351,8 +1351,10 @@
  bool Debugger::compiling_natives_ = false;
  bool Debugger::is_loading_debugger_ = false;
  DebugMessageThread* Debugger::message_thread_ = NULL;
-v8::DebugMessageHandler Debugger::debug_message_handler_ = NULL;
-void* Debugger::debug_message_handler_data_ = NULL;
+v8::DebugMessageHandler Debugger::message_handler_ = NULL;
+void* Debugger::message_handler_data_ = NULL;
+v8::DebugHostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
+void* Debugger::host_dispatch_handler_data_ = NULL;


  Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
@@ -1709,8 +1711,8 @@


  void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void*  
data) {
-  debug_message_handler_ = handler;
-  debug_message_handler_data_ = data;
+  message_handler_ = handler;
+  message_handler_data_ = data;
    if (!message_thread_) {
      message_thread_ = new DebugMessageThread();
      message_thread_->Start();
@@ -1719,14 +1721,20 @@
  }


+void Debugger::SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                      void* data) {
+  host_dispatch_handler_ = handler;
+  host_dispatch_handler_data_ = data;
+}
+
+
  // Posts an output message from the debugger to the debug_message_handler
  // callback.  This callback is part of the public API.  Messages are
  // kept internally as Vector<uint16_t> strings, which are allocated in  
various
  // places and deallocated by the calling function sometime after this call.
  void Debugger::SendMessage(Vector< uint16_t> message) {
-  if (debug_message_handler_ != NULL) {
-    debug_message_handler_(message.start(), message.length(),
-                           debug_message_handler_data_);
+  if (message_handler_ != NULL) {
+    message_handler_(message.start(), message.length(),  
message_handler_data_);
    }
  }

@@ -1740,9 +1748,16 @@
  }


+void Debugger::ProcessHostDispatch(void* dispatch) {
+  if (message_thread_ != NULL) {
+    message_thread_->ProcessHostDispatch(dispatch);
+  }
+}
+
+
  void Debugger::UpdateActiveDebugger() {
    set_debugger_active((message_thread_ != NULL &&
-                       debug_message_handler_ != NULL) ||
+                       message_handler_ != NULL) ||
                         !event_listener_.is_null());
    if (!debugger_active() && message_thread_) {
      message_thread_->OnDebuggerInactive();
@@ -1914,6 +1929,16 @@
        return;
      }

+    // Check if the command is a host dispatch.
+    if (command[0] == 0) {
+      if (Debugger::host_dispatch_handler_) {
+        int32_t dispatch = (command[1] << 16) | command[2];
+        Debugger::host_dispatch_handler_(reinterpret_cast<void*>(dispatch),
+                                          
Debugger::host_dispatch_handler_data_);
+      }
+      continue;
+    }
+
      // Invoke the JavaScript to process the debug request.
      v8::Local<v8::String> fun_name;
      v8::Local<v8::Function> fun;
@@ -1987,6 +2012,18 @@
    Vector<uint16_t> command_copy = command.Clone();
    Logger::DebugTag("Put command on command_queue.");
    command_queue_.Put(command_copy);
+  command_received_->Signal();
+}
+
+
+// Puts a host dispatch comming from the public API on the queue.
+void DebugMessageThread::ProcessHostDispatch(void* dispatch) {
+  uint16_t hack[3];
+  hack[0] = 0;
+  hack[1] = reinterpret_cast<uint32_t>(dispatch) >> 16;
+  hack[2] = reinterpret_cast<uint32_t>(dispatch) & 0xFFFF;
+  Logger::DebugTag("Put dispatch on command_queue.");
+  command_queue_.Put(Vector<uint16_t>(hack, 3).Clone());
    command_received_->Signal();
  }


Modified: branches/bleeding_edge/src/debug.h
==============================================================================
--- branches/bleeding_edge/src/debug.h  (original)
+++ branches/bleeding_edge/src/debug.h  Thu Feb 19 06:02:42 2009
@@ -381,8 +381,11 @@
                                  Handle<Object> event_data);
    static void SetEventListener(Handle<Object> callback, Handle<Object>  
data);
    static void SetMessageHandler(v8::DebugMessageHandler handler, void*  
data);
+  static void SetHostDispatchHandler(v8::DebugHostDispatchHandler handler,
+                                     void* data);
    static void SendMessage(Vector<uint16_t> message);
    static void ProcessCommand(Vector<const uint16_t> command);
+  static void ProcessHostDispatch(void* dispatch);
    static void UpdateActiveDebugger();
    static Handle<Object> Call(Handle<JSFunction> fun,
                               Handle<Object> data,
@@ -411,8 +414,12 @@
    static bool compiling_natives_;  // Are we compiling natives?
    static bool is_loading_debugger_;  // Are we loading the debugger?
    static DebugMessageThread* message_thread_;
-  static v8::DebugMessageHandler debug_message_handler_;
-  static void* debug_message_handler_data_;
+  static v8::DebugMessageHandler message_handler_;
+  static void* message_handler_data_;
+  static v8::DebugHostDispatchHandler host_dispatch_handler_;
+  static void* host_dispatch_handler_data_;
+
+ friend class DebugMessageThread;
  };


@@ -481,6 +488,7 @@
    // by the API client thread.  This is where the API client hands off
    // processing of the command to the DebugMessageThread thread.
    void ProcessCommand(Vector<uint16_t> command);
+  void ProcessHostDispatch(void* dispatch);
    void OnDebuggerInactive();

    // Main function of DebugMessageThread thread.

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    Thu Feb 19 06:02:42  
2009
@@ -3660,3 +3660,40 @@
    v8::Debug::SetDebugEventListener(NULL);
    CheckDebuggerUnloaded(true);
  }
+
+
+int host_dispatch_hit_count = 0;
+static void HostDispatchHandlerHitCount(void* dispatch, void *data) {
+  CHECK_EQ(dispatch, &HostDispatchHandlerHitCount);
+  CHECK_EQ(data, &HostDispatchHandlerHitCount);
+  host_dispatch_hit_count++;
+}
+
+
+// Test that clearing the debug event listener actually clears all break  
points
+// and related information.
+TEST(DebuggerHostDispatch) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* command_continue =
+    "{\"seq\":106,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+
+  // Setup message and host dispatch handlers.
+  v8::Debug::SetMessageHandler(DummyMessageHandler);
+  v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount,
+                                    &HostDispatchHandlerHitCount);
+
+  // Fill a host dispatch and a continue command on the command queue  
before
+  // generating a debug break.
+  v8::Debug::SendHostDispatch(&HostDispatchHandlerHitCount);
+  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  CompileRun("debugger");
+
+  // The host dispatch callback should be called.
+  CHECK_EQ(1, host_dispatch_hit_count);
+}
\ No newline at end of file

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

Reply via email to