Index: src/debug/debug.h |
diff --git a/src/debug/debug.h b/src/debug/debug.h |
index 88fd6ecc8d6cc5f12b8f81ebcac6daacc60ce002..8d2f8d5974d9db3e8f6d32c09dca7a72beb88c66 100644 |
--- a/src/debug/debug.h |
+++ b/src/debug/debug.h |
@@ -240,6 +240,47 @@ class DebugInfoListNode { |
DebugInfoListNode* next_; |
}; |
+// Message delivered to the message handler callback. This is either a debugger |
+// event or the response to a command. |
+class MessageImpl : public v8::Debug::Message { |
+ public: |
+ // Create a message object for a debug event. |
+ static MessageImpl NewEvent(DebugEvent event, bool running, |
+ Handle<JSObject> exec_state, |
+ Handle<JSObject> event_data); |
+ |
+ // Create a message object for the response to a debug command. |
+ static MessageImpl NewResponse(DebugEvent event, bool running, |
+ Handle<JSObject> exec_state, |
+ Handle<JSObject> event_data, |
+ Handle<String> response_json, |
+ v8::Debug::ClientData* client_data); |
+ |
+ // Implementation of interface v8::Debug::Message. |
+ virtual bool IsEvent() const; |
+ virtual bool IsResponse() const; |
+ virtual DebugEvent GetEvent() const; |
+ virtual bool WillStartRunning() const; |
+ virtual v8::Local<v8::Object> GetExecutionState() const; |
+ virtual v8::Local<v8::Object> GetEventData() const; |
+ virtual v8::Local<v8::String> GetJSON() const; |
+ virtual v8::Local<v8::Context> GetEventContext() const; |
+ virtual v8::Debug::ClientData* GetClientData() const; |
+ virtual v8::Isolate* GetIsolate() const; |
+ |
+ private: |
+ MessageImpl(bool is_event, DebugEvent event, bool running, |
+ Handle<JSObject> exec_state, Handle<JSObject> event_data, |
+ Handle<String> response_json, v8::Debug::ClientData* client_data); |
+ |
+ bool is_event_; // Does this message represent a debug event? |
+ DebugEvent event_; // Debug event causing the break. |
+ bool running_; // Will the VM start running after this event? |
+ Handle<JSObject> exec_state_; // Current execution state. |
+ Handle<JSObject> event_data_; // Data associated with the event. |
+ Handle<String> response_json_; // Response JSON if message holds a response. |
+ v8::Debug::ClientData* client_data_; // Client data passed with the request. |
+}; |
// Details of the debug event delivered to the debug event listener. |
class EventDetailsImpl : public v8::DebugInterface::EventDetails { |
@@ -266,6 +307,67 @@ class EventDetailsImpl : public v8::DebugInterface::EventDetails { |
v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. |
}; |
+// Message send by user to v8 debugger or debugger output message. |
+// In addition to command text it may contain a pointer to some user data |
+// which are expected to be passed along with the command reponse to message |
+// handler. |
+class CommandMessage { |
+ public: |
+ static CommandMessage New(const Vector<uint16_t>& command, |
+ v8::Debug::ClientData* data); |
+ CommandMessage(); |
+ |
+ // Deletes user data and disposes of the text. |
+ void Dispose(); |
+ Vector<uint16_t> text() const { return text_; } |
+ v8::Debug::ClientData* client_data() const { return client_data_; } |
+ |
+ private: |
+ CommandMessage(const Vector<uint16_t>& text, v8::Debug::ClientData* data); |
+ |
+ Vector<uint16_t> text_; |
+ v8::Debug::ClientData* client_data_; |
+}; |
+ |
+// A Queue of CommandMessage objects. A thread-safe version is |
+// LockingCommandMessageQueue, based on this class. |
+class CommandMessageQueue BASE_EMBEDDED { |
+ public: |
+ explicit CommandMessageQueue(int size); |
+ ~CommandMessageQueue(); |
+ bool IsEmpty() const { return start_ == end_; } |
+ CommandMessage Get(); |
+ void Put(const CommandMessage& message); |
+ void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). |
+ |
+ private: |
+ // Doubles the size of the message queue, and copies the messages. |
+ void Expand(); |
+ |
+ CommandMessage* messages_; |
+ int start_; |
+ int end_; |
+ int size_; // The size of the queue buffer. Queue can hold size-1 messages. |
+}; |
+ |
+// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage |
+// messages. The message data is not managed by LockingCommandMessageQueue. |
+// Pointers to the data are passed in and out. Implemented by adding a |
+// Mutex to CommandMessageQueue. Includes logging of all puts and gets. |
+class LockingCommandMessageQueue BASE_EMBEDDED { |
+ public: |
+ LockingCommandMessageQueue(Logger* logger, int size); |
+ bool IsEmpty() const; |
+ CommandMessage Get(); |
+ void Put(const CommandMessage& message); |
+ void Clear(); |
+ |
+ private: |
+ Logger* logger_; |
+ CommandMessageQueue queue_; |
+ mutable base::Mutex mutex_; |
+ DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); |
+}; |
class DebugFeatureTracker { |
public: |
@@ -299,11 +401,12 @@ class DebugFeatureTracker { |
class Debug { |
public: |
// Debug event triggers. |
- void OnDebugBreak(Handle<Object> break_points_hit); |
+ void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); |
void OnThrow(Handle<Object> exception); |
void OnPromiseReject(Handle<Object> promise, Handle<Object> value); |
void OnCompileError(Handle<Script> script); |
+ void OnBeforeCompile(Handle<Script> script); |
void OnAfterCompile(Handle<Script> script); |
void OnAsyncTaskEvent(Handle<String> type, Handle<Object> id, |
Handle<String> name); |
@@ -311,11 +414,13 @@ class Debug { |
// API facing. |
void SetEventListener(Handle<Object> callback, Handle<Object> data); |
void SetMessageHandler(v8::Debug::MessageHandler handler); |
+ void EnqueueCommandMessage(Vector<const uint16_t> command, |
+ v8::Debug::ClientData* client_data = NULL); |
MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, |
Handle<Object> data); |
Handle<Context> GetDebugContext(); |
void HandleDebugBreak(); |
- void ProcessDebugMessages(); |
+ void ProcessDebugMessages(bool debug_command_only); |
// Internal logic |
bool Load(); |
@@ -454,6 +559,7 @@ class Debug { |
} |
// Check whether there are commands in the command queue. |
+ inline bool has_commands() const { return !command_queue_.IsEmpty(); } |
inline bool ignore_events() const { return is_suppressed_ || !is_active_; } |
inline bool break_disabled() const { |
return break_disabled_ || in_debug_event_listener_; |
@@ -491,7 +597,11 @@ class Debug { |
Handle<Object> event_data, |
v8::Debug::ClientData* client_data); |
void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); |
- void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data); |
+ void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data, |
+ bool auto_continue); |
+ void NotifyMessageHandler(v8::DebugEvent event, Handle<JSObject> exec_state, |
+ Handle<JSObject> event_data, bool auto_continue); |
+ void InvokeMessageHandler(MessageImpl message); |
// Find the closest source position for a break point for a given position. |
int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, |
@@ -534,6 +644,10 @@ class Debug { |
v8::Debug::MessageHandler message_handler_; |
+ static const int kQueueInitialSize = 4; |
+ base::Semaphore command_received_; // Signaled for each command received. |
+ LockingCommandMessageQueue command_queue_; |
+ |
bool is_active_; |
bool is_suppressed_; |
bool live_edit_enabled_; |