OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_DEBUG_DEBUG_H_ | 5 #ifndef V8_DEBUG_DEBUG_H_ |
6 #define V8_DEBUG_DEBUG_H_ | 6 #define V8_DEBUG_DEBUG_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/assembler.h" | 10 #include "src/assembler.h" |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); } | 237 Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); } |
238 | 238 |
239 private: | 239 private: |
240 // Global (weak) handle to the debug info object. | 240 // Global (weak) handle to the debug info object. |
241 DebugInfo** debug_info_; | 241 DebugInfo** debug_info_; |
242 | 242 |
243 // Next pointer for linked list. | 243 // Next pointer for linked list. |
244 DebugInfoListNode* next_; | 244 DebugInfoListNode* next_; |
245 }; | 245 }; |
246 | 246 |
| 247 // Message delivered to the message handler callback. This is either a debugger |
| 248 // event or the response to a command. |
| 249 class MessageImpl : public v8::Debug::Message { |
| 250 public: |
| 251 // Create a message object for a debug event. |
| 252 static MessageImpl NewEvent(DebugEvent event, bool running, |
| 253 Handle<JSObject> exec_state, |
| 254 Handle<JSObject> event_data); |
| 255 |
| 256 // Create a message object for the response to a debug command. |
| 257 static MessageImpl NewResponse(DebugEvent event, bool running, |
| 258 Handle<JSObject> exec_state, |
| 259 Handle<JSObject> event_data, |
| 260 Handle<String> response_json, |
| 261 v8::Debug::ClientData* client_data); |
| 262 |
| 263 // Implementation of interface v8::Debug::Message. |
| 264 virtual bool IsEvent() const; |
| 265 virtual bool IsResponse() const; |
| 266 virtual DebugEvent GetEvent() const; |
| 267 virtual bool WillStartRunning() const; |
| 268 virtual v8::Local<v8::Object> GetExecutionState() const; |
| 269 virtual v8::Local<v8::Object> GetEventData() const; |
| 270 virtual v8::Local<v8::String> GetJSON() const; |
| 271 virtual v8::Local<v8::Context> GetEventContext() const; |
| 272 virtual v8::Debug::ClientData* GetClientData() const; |
| 273 virtual v8::Isolate* GetIsolate() const; |
| 274 |
| 275 private: |
| 276 MessageImpl(bool is_event, DebugEvent event, bool running, |
| 277 Handle<JSObject> exec_state, Handle<JSObject> event_data, |
| 278 Handle<String> response_json, v8::Debug::ClientData* client_data); |
| 279 |
| 280 bool is_event_; // Does this message represent a debug event? |
| 281 DebugEvent event_; // Debug event causing the break. |
| 282 bool running_; // Will the VM start running after this event? |
| 283 Handle<JSObject> exec_state_; // Current execution state. |
| 284 Handle<JSObject> event_data_; // Data associated with the event. |
| 285 Handle<String> response_json_; // Response JSON if message holds a response. |
| 286 v8::Debug::ClientData* client_data_; // Client data passed with the request. |
| 287 }; |
| 288 |
247 // Details of the debug event delivered to the debug event listener. | 289 // Details of the debug event delivered to the debug event listener. |
248 class EventDetailsImpl : public v8::Debug::EventDetails { | 290 class EventDetailsImpl : public v8::Debug::EventDetails { |
249 public: | 291 public: |
250 EventDetailsImpl(DebugEvent event, Handle<JSObject> exec_state, | 292 EventDetailsImpl(DebugEvent event, |
251 Handle<JSObject> event_data, Handle<Object> callback_data); | 293 Handle<JSObject> exec_state, |
| 294 Handle<JSObject> event_data, |
| 295 Handle<Object> callback_data, |
| 296 v8::Debug::ClientData* client_data); |
252 virtual DebugEvent GetEvent() const; | 297 virtual DebugEvent GetEvent() const; |
253 virtual v8::Local<v8::Object> GetExecutionState() const; | 298 virtual v8::Local<v8::Object> GetExecutionState() const; |
254 virtual v8::Local<v8::Object> GetEventData() const; | 299 virtual v8::Local<v8::Object> GetEventData() const; |
255 virtual v8::Local<v8::Context> GetEventContext() const; | 300 virtual v8::Local<v8::Context> GetEventContext() const; |
256 virtual v8::Local<v8::Value> GetCallbackData() const; | 301 virtual v8::Local<v8::Value> GetCallbackData() const; |
| 302 virtual v8::Debug::ClientData* GetClientData() const; |
257 virtual v8::Isolate* GetIsolate() const; | 303 virtual v8::Isolate* GetIsolate() const; |
258 | 304 |
259 private: | 305 private: |
260 DebugEvent event_; // Debug event causing the break. | 306 DebugEvent event_; // Debug event causing the break. |
261 Handle<JSObject> exec_state_; // Current execution state. | 307 Handle<JSObject> exec_state_; // Current execution state. |
262 Handle<JSObject> event_data_; // Data associated with the event. | 308 Handle<JSObject> event_data_; // Data associated with the event. |
263 Handle<Object> callback_data_; // User data passed with the callback | 309 Handle<Object> callback_data_; // User data passed with the callback |
264 // when it was registered. | 310 // when it was registered. |
| 311 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. |
265 }; | 312 }; |
266 | 313 |
| 314 // Message send by user to v8 debugger or debugger output message. |
| 315 // In addition to command text it may contain a pointer to some user data |
| 316 // which are expected to be passed along with the command reponse to message |
| 317 // handler. |
| 318 class CommandMessage { |
| 319 public: |
| 320 static CommandMessage New(const Vector<uint16_t>& command, |
| 321 v8::Debug::ClientData* data); |
| 322 CommandMessage(); |
| 323 |
| 324 // Deletes user data and disposes of the text. |
| 325 void Dispose(); |
| 326 Vector<uint16_t> text() const { return text_; } |
| 327 v8::Debug::ClientData* client_data() const { return client_data_; } |
| 328 |
| 329 private: |
| 330 CommandMessage(const Vector<uint16_t>& text, v8::Debug::ClientData* data); |
| 331 |
| 332 Vector<uint16_t> text_; |
| 333 v8::Debug::ClientData* client_data_; |
| 334 }; |
| 335 |
| 336 // A Queue of CommandMessage objects. A thread-safe version is |
| 337 // LockingCommandMessageQueue, based on this class. |
| 338 class CommandMessageQueue BASE_EMBEDDED { |
| 339 public: |
| 340 explicit CommandMessageQueue(int size); |
| 341 ~CommandMessageQueue(); |
| 342 bool IsEmpty() const { return start_ == end_; } |
| 343 CommandMessage Get(); |
| 344 void Put(const CommandMessage& message); |
| 345 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). |
| 346 |
| 347 private: |
| 348 // Doubles the size of the message queue, and copies the messages. |
| 349 void Expand(); |
| 350 |
| 351 CommandMessage* messages_; |
| 352 int start_; |
| 353 int end_; |
| 354 int size_; // The size of the queue buffer. Queue can hold size-1 messages. |
| 355 }; |
| 356 |
| 357 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage |
| 358 // messages. The message data is not managed by LockingCommandMessageQueue. |
| 359 // Pointers to the data are passed in and out. Implemented by adding a |
| 360 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. |
| 361 class LockingCommandMessageQueue BASE_EMBEDDED { |
| 362 public: |
| 363 LockingCommandMessageQueue(Logger* logger, int size); |
| 364 bool IsEmpty() const; |
| 365 CommandMessage Get(); |
| 366 void Put(const CommandMessage& message); |
| 367 void Clear(); |
| 368 |
| 369 private: |
| 370 Logger* logger_; |
| 371 CommandMessageQueue queue_; |
| 372 mutable base::Mutex mutex_; |
| 373 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); |
| 374 }; |
267 | 375 |
268 class DebugFeatureTracker { | 376 class DebugFeatureTracker { |
269 public: | 377 public: |
270 enum Feature { | 378 enum Feature { |
271 kActive = 1, | 379 kActive = 1, |
272 kBreakPoint = 2, | 380 kBreakPoint = 2, |
273 kStepping = 3, | 381 kStepping = 3, |
274 kHeapSnapshot = 4, | 382 kHeapSnapshot = 4, |
275 kAllocationTracking = 5, | 383 kAllocationTracking = 5, |
276 kProfiler = 6, | 384 kProfiler = 6, |
(...skipping 13 matching lines...) Expand all Loading... |
290 // This class contains the debugger support. The main purpose is to handle | 398 // This class contains the debugger support. The main purpose is to handle |
291 // setting break points in the code. | 399 // setting break points in the code. |
292 // | 400 // |
293 // This class controls the debug info for all functions which currently have | 401 // This class controls the debug info for all functions which currently have |
294 // active breakpoints in them. This debug info is held in the heap root object | 402 // active breakpoints in them. This debug info is held in the heap root object |
295 // debug_info which is a FixedArray. Each entry in this list is of class | 403 // debug_info which is a FixedArray. Each entry in this list is of class |
296 // DebugInfo. | 404 // DebugInfo. |
297 class Debug { | 405 class Debug { |
298 public: | 406 public: |
299 // Debug event triggers. | 407 // Debug event triggers. |
300 void OnDebugBreak(Handle<Object> break_points_hit); | 408 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); |
301 | 409 |
302 void OnThrow(Handle<Object> exception); | 410 void OnThrow(Handle<Object> exception); |
303 void OnPromiseReject(Handle<Object> promise, Handle<Object> value); | 411 void OnPromiseReject(Handle<Object> promise, Handle<Object> value); |
304 void OnCompileError(Handle<Script> script); | 412 void OnCompileError(Handle<Script> script); |
305 void OnAfterCompile(Handle<Script> script); | 413 void OnAfterCompile(Handle<Script> script); |
306 void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id); | 414 void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id); |
307 | 415 |
308 // API facing. | 416 // API facing. |
309 void SetEventListener(Handle<Object> callback, Handle<Object> data); | 417 void SetEventListener(Handle<Object> callback, Handle<Object> data); |
| 418 void SetMessageHandler(v8::Debug::MessageHandler handler); |
| 419 void EnqueueCommandMessage(Vector<const uint16_t> command, |
| 420 v8::Debug::ClientData* client_data = NULL); |
310 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, | 421 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, |
311 Handle<Object> data); | 422 Handle<Object> data); |
312 Handle<Context> GetDebugContext(); | 423 Handle<Context> GetDebugContext(); |
313 void HandleDebugBreak(); | 424 void HandleDebugBreak(); |
| 425 void ProcessDebugMessages(bool debug_command_only); |
314 | 426 |
315 // Internal logic | 427 // Internal logic |
316 bool Load(); | 428 bool Load(); |
317 void Break(JavaScriptFrame* frame); | 429 void Break(JavaScriptFrame* frame); |
318 void SetAfterBreakTarget(JavaScriptFrame* frame); | 430 void SetAfterBreakTarget(JavaScriptFrame* frame); |
319 | 431 |
320 // Scripts handling. | 432 // Scripts handling. |
321 Handle<FixedArray> GetLoadedScripts(); | 433 Handle<FixedArray> GetLoadedScripts(); |
322 | 434 |
323 // Break point handling. | 435 // Break point handling. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 private: | 572 private: |
461 explicit Debug(Isolate* isolate); | 573 explicit Debug(Isolate* isolate); |
462 | 574 |
463 void UpdateState(); | 575 void UpdateState(); |
464 void UpdateHookOnFunctionCall(); | 576 void UpdateHookOnFunctionCall(); |
465 void Unload(); | 577 void Unload(); |
466 void SetNextBreakId() { | 578 void SetNextBreakId() { |
467 thread_local_.break_id_ = ++thread_local_.break_count_; | 579 thread_local_.break_id_ = ++thread_local_.break_count_; |
468 } | 580 } |
469 | 581 |
| 582 // Check whether there are commands in the command queue. |
| 583 inline bool has_commands() const { return !command_queue_.IsEmpty(); } |
470 inline bool ignore_events() const { | 584 inline bool ignore_events() const { |
471 return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check(); | 585 return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check(); |
472 } | 586 } |
473 inline bool break_disabled() const { | 587 inline bool break_disabled() const { |
474 return break_disabled_ || in_debug_event_listener_; | 588 return break_disabled_ || in_debug_event_listener_; |
475 } | 589 } |
476 | 590 |
477 void clear_suspended_generator() { | 591 void clear_suspended_generator() { |
478 thread_local_.suspended_generator_ = Smi::kZero; | 592 thread_local_.suspended_generator_ = Smi::kZero; |
479 } | 593 } |
480 | 594 |
481 bool has_suspended_generator() const { | 595 bool has_suspended_generator() const { |
482 return thread_local_.suspended_generator_ != Smi::kZero; | 596 return thread_local_.suspended_generator_ != Smi::kZero; |
483 } | 597 } |
484 | 598 |
485 // There are three types of event listeners: C++ message_handler, | 599 // There are three types of event listeners: C++ message_handler, |
486 // JavaScript event listener and C++ event listener. | 600 // JavaScript event listener and C++ event listener. |
487 // Currently inspector still uses C++ event listener and installs | 601 // Currently inspector still uses C++ event listener and installs |
488 // more specific event listeners for part of events. Calling of | 602 // more specific event listeners for part of events. Calling of |
489 // C++ event listener is redundant when more specific event listener | 603 // C++ event listener is redundant when more specific event listener |
490 // is presented. Other clients can install JavaScript event listener | 604 // is presented. Other clients can install JavaScript event listener |
491 // (e.g. some of NodeJS module). | 605 // (e.g. some of NodeJS module). |
492 bool non_inspector_listener_exists() const { | 606 bool non_inspector_listener_exists() const { |
493 return !event_listener_.is_null() && !event_listener_->IsForeign(); | 607 return message_handler_ != nullptr || |
| 608 (!event_listener_.is_null() && !event_listener_->IsForeign()); |
494 } | 609 } |
495 | 610 |
496 void OnException(Handle<Object> exception, Handle<Object> promise); | 611 void OnException(Handle<Object> exception, Handle<Object> promise); |
497 | 612 |
498 // Constructors for debug event objects. | 613 // Constructors for debug event objects. |
499 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); | 614 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); |
500 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( | 615 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( |
501 Handle<Object> break_points_hit); | 616 Handle<Object> break_points_hit); |
502 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( | 617 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( |
503 Handle<Object> exception, | 618 Handle<Object> exception, |
504 bool uncaught, | 619 bool uncaught, |
505 Handle<Object> promise); | 620 Handle<Object> promise); |
506 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( | 621 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( |
507 Handle<Script> script, v8::DebugEvent type); | 622 Handle<Script> script, v8::DebugEvent type); |
508 MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<Smi> type, | 623 MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<Smi> type, |
509 Handle<Smi> id); | 624 Handle<Smi> id); |
510 | 625 |
511 // Mirror cache handling. | 626 // Mirror cache handling. |
512 void ClearMirrorCache(); | 627 void ClearMirrorCache(); |
513 | 628 |
| 629 void CallEventCallback(v8::DebugEvent event, |
| 630 Handle<Object> exec_state, |
| 631 Handle<Object> event_data, |
| 632 v8::Debug::ClientData* client_data); |
514 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); | 633 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); |
515 void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data); | 634 void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data, |
| 635 bool auto_continue); |
| 636 void NotifyMessageHandler(v8::DebugEvent event, Handle<JSObject> exec_state, |
| 637 Handle<JSObject> event_data, bool auto_continue); |
| 638 void InvokeMessageHandler(MessageImpl message); |
516 | 639 |
517 // Find the closest source position for a break point for a given position. | 640 // Find the closest source position for a break point for a given position. |
518 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, | 641 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, |
519 BreakPositionAlignment alignment); | 642 BreakPositionAlignment alignment); |
520 // Instrument code to break at break points. | 643 // Instrument code to break at break points. |
521 void ApplyBreakPoints(Handle<DebugInfo> debug_info); | 644 void ApplyBreakPoints(Handle<DebugInfo> debug_info); |
522 // Clear code from instrumentation. | 645 // Clear code from instrumentation. |
523 void ClearBreakPoints(Handle<DebugInfo> debug_info); | 646 void ClearBreakPoints(Handle<DebugInfo> debug_info); |
524 // Clear all code from instrumentation. | 647 // Clear all code from instrumentation. |
525 void ClearAllBreakPoints(); | 648 void ClearAllBreakPoints(); |
(...skipping 20 matching lines...) Expand all Loading... |
546 | 669 |
547 void ThreadInit(); | 670 void ThreadInit(); |
548 | 671 |
549 void PrintBreakLocation(); | 672 void PrintBreakLocation(); |
550 | 673 |
551 // Global handles. | 674 // Global handles. |
552 Handle<Context> debug_context_; | 675 Handle<Context> debug_context_; |
553 Handle<Object> event_listener_; | 676 Handle<Object> event_listener_; |
554 Handle<Object> event_listener_data_; | 677 Handle<Object> event_listener_data_; |
555 | 678 |
| 679 v8::Debug::MessageHandler message_handler_; |
| 680 |
556 debug::DebugEventListener* debug_event_listener_ = nullptr; | 681 debug::DebugEventListener* debug_event_listener_ = nullptr; |
557 | 682 |
| 683 static const int kQueueInitialSize = 4; |
| 684 base::Semaphore command_received_; // Signaled for each command received. |
| 685 LockingCommandMessageQueue command_queue_; |
| 686 |
558 // Debugger is active, i.e. there is a debug event listener attached. | 687 // Debugger is active, i.e. there is a debug event listener attached. |
559 bool is_active_; | 688 bool is_active_; |
560 // Debugger needs to be notified on every new function call. | 689 // Debugger needs to be notified on every new function call. |
561 // Used for stepping and read-only checks | 690 // Used for stepping and read-only checks |
562 bool hook_on_function_call_; | 691 bool hook_on_function_call_; |
563 // Suppress debug events. | 692 // Suppress debug events. |
564 bool is_suppressed_; | 693 bool is_suppressed_; |
565 // LiveEdit is enabled. | 694 // LiveEdit is enabled. |
566 bool live_edit_enabled_; | 695 bool live_edit_enabled_; |
567 // Do not trigger debug break events. | 696 // Do not trigger debug break events. |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 Handle<Code> code); | 883 Handle<Code> code); |
755 static bool DebugBreakSlotIsPatched(Address pc); | 884 static bool DebugBreakSlotIsPatched(Address pc); |
756 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); | 885 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); |
757 }; | 886 }; |
758 | 887 |
759 | 888 |
760 } // namespace internal | 889 } // namespace internal |
761 } // namespace v8 | 890 } // namespace v8 |
762 | 891 |
763 #endif // V8_DEBUG_DEBUG_H_ | 892 #endif // V8_DEBUG_DEBUG_H_ |
OLD | NEW |