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 | |
289 // Details of the debug event delivered to the debug event listener. | 247 // Details of the debug event delivered to the debug event listener. |
290 class EventDetailsImpl : public v8::Debug::EventDetails { | 248 class EventDetailsImpl : public v8::Debug::EventDetails { |
291 public: | 249 public: |
292 EventDetailsImpl(DebugEvent event, | 250 EventDetailsImpl(DebugEvent event, Handle<JSObject> exec_state, |
293 Handle<JSObject> exec_state, | 251 Handle<JSObject> event_data, Handle<Object> callback_data); |
294 Handle<JSObject> event_data, | |
295 Handle<Object> callback_data, | |
296 v8::Debug::ClientData* client_data); | |
297 virtual DebugEvent GetEvent() const; | 252 virtual DebugEvent GetEvent() const; |
298 virtual v8::Local<v8::Object> GetExecutionState() const; | 253 virtual v8::Local<v8::Object> GetExecutionState() const; |
299 virtual v8::Local<v8::Object> GetEventData() const; | 254 virtual v8::Local<v8::Object> GetEventData() const; |
300 virtual v8::Local<v8::Context> GetEventContext() const; | 255 virtual v8::Local<v8::Context> GetEventContext() const; |
301 virtual v8::Local<v8::Value> GetCallbackData() const; | 256 virtual v8::Local<v8::Value> GetCallbackData() const; |
302 virtual v8::Debug::ClientData* GetClientData() const; | 257 virtual v8::Debug::ClientData* GetClientData() const { return nullptr; } |
303 virtual v8::Isolate* GetIsolate() const; | 258 virtual v8::Isolate* GetIsolate() const; |
304 | 259 |
305 private: | 260 private: |
306 DebugEvent event_; // Debug event causing the break. | 261 DebugEvent event_; // Debug event causing the break. |
307 Handle<JSObject> exec_state_; // Current execution state. | 262 Handle<JSObject> exec_state_; // Current execution state. |
308 Handle<JSObject> event_data_; // Data associated with the event. | 263 Handle<JSObject> event_data_; // Data associated with the event. |
309 Handle<Object> callback_data_; // User data passed with the callback | 264 Handle<Object> callback_data_; // User data passed with the callback |
310 // when it was registered. | 265 // when it was registered. |
311 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. | |
312 }; | 266 }; |
313 | 267 |
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 }; | |
375 | 268 |
376 class DebugFeatureTracker { | 269 class DebugFeatureTracker { |
377 public: | 270 public: |
378 enum Feature { | 271 enum Feature { |
379 kActive = 1, | 272 kActive = 1, |
380 kBreakPoint = 2, | 273 kBreakPoint = 2, |
381 kStepping = 3, | 274 kStepping = 3, |
382 kHeapSnapshot = 4, | 275 kHeapSnapshot = 4, |
383 kAllocationTracking = 5, | 276 kAllocationTracking = 5, |
384 kProfiler = 6, | 277 kProfiler = 6, |
(...skipping 13 matching lines...) Expand all Loading... |
398 // This class contains the debugger support. The main purpose is to handle | 291 // This class contains the debugger support. The main purpose is to handle |
399 // setting break points in the code. | 292 // setting break points in the code. |
400 // | 293 // |
401 // This class controls the debug info for all functions which currently have | 294 // This class controls the debug info for all functions which currently have |
402 // active breakpoints in them. This debug info is held in the heap root object | 295 // active breakpoints in them. This debug info is held in the heap root object |
403 // debug_info which is a FixedArray. Each entry in this list is of class | 296 // debug_info which is a FixedArray. Each entry in this list is of class |
404 // DebugInfo. | 297 // DebugInfo. |
405 class Debug { | 298 class Debug { |
406 public: | 299 public: |
407 // Debug event triggers. | 300 // Debug event triggers. |
408 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); | 301 void OnDebugBreak(Handle<Object> break_points_hit); |
409 | 302 |
410 void OnThrow(Handle<Object> exception); | 303 void OnThrow(Handle<Object> exception); |
411 void OnPromiseReject(Handle<Object> promise, Handle<Object> value); | 304 void OnPromiseReject(Handle<Object> promise, Handle<Object> value); |
412 void OnCompileError(Handle<Script> script); | 305 void OnCompileError(Handle<Script> script); |
413 void OnAfterCompile(Handle<Script> script); | 306 void OnAfterCompile(Handle<Script> script); |
414 void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id); | 307 void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id); |
415 | 308 |
416 // API facing. | 309 // API facing. |
417 void SetEventListener(Handle<Object> callback, Handle<Object> data); | 310 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); | |
421 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, | 311 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, |
422 Handle<Object> data); | 312 Handle<Object> data); |
423 Handle<Context> GetDebugContext(); | 313 Handle<Context> GetDebugContext(); |
424 void HandleDebugBreak(); | 314 void HandleDebugBreak(); |
425 void ProcessDebugMessages(bool debug_command_only); | |
426 | 315 |
427 // Internal logic | 316 // Internal logic |
428 bool Load(); | 317 bool Load(); |
429 void Break(JavaScriptFrame* frame); | 318 void Break(JavaScriptFrame* frame); |
430 void SetAfterBreakTarget(JavaScriptFrame* frame); | 319 void SetAfterBreakTarget(JavaScriptFrame* frame); |
431 | 320 |
432 // Scripts handling. | 321 // Scripts handling. |
433 Handle<FixedArray> GetLoadedScripts(); | 322 Handle<FixedArray> GetLoadedScripts(); |
434 | 323 |
435 // Break point handling. | 324 // Break point handling. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 private: | 461 private: |
573 explicit Debug(Isolate* isolate); | 462 explicit Debug(Isolate* isolate); |
574 | 463 |
575 void UpdateState(); | 464 void UpdateState(); |
576 void UpdateHookOnFunctionCall(); | 465 void UpdateHookOnFunctionCall(); |
577 void Unload(); | 466 void Unload(); |
578 void SetNextBreakId() { | 467 void SetNextBreakId() { |
579 thread_local_.break_id_ = ++thread_local_.break_count_; | 468 thread_local_.break_id_ = ++thread_local_.break_count_; |
580 } | 469 } |
581 | 470 |
582 // Check whether there are commands in the command queue. | |
583 inline bool has_commands() const { return !command_queue_.IsEmpty(); } | |
584 inline bool ignore_events() const { | 471 inline bool ignore_events() const { |
585 return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check(); | 472 return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check(); |
586 } | 473 } |
587 inline bool break_disabled() const { | 474 inline bool break_disabled() const { |
588 return break_disabled_ || in_debug_event_listener_; | 475 return break_disabled_ || in_debug_event_listener_; |
589 } | 476 } |
590 | 477 |
591 void clear_suspended_generator() { | 478 void clear_suspended_generator() { |
592 thread_local_.suspended_generator_ = Smi::kZero; | 479 thread_local_.suspended_generator_ = Smi::kZero; |
593 } | 480 } |
594 | 481 |
595 bool has_suspended_generator() const { | 482 bool has_suspended_generator() const { |
596 return thread_local_.suspended_generator_ != Smi::kZero; | 483 return thread_local_.suspended_generator_ != Smi::kZero; |
597 } | 484 } |
598 | 485 |
599 // There are three types of event listeners: C++ message_handler, | 486 // There are three types of event listeners: C++ message_handler, |
600 // JavaScript event listener and C++ event listener. | 487 // JavaScript event listener and C++ event listener. |
601 // Currently inspector still uses C++ event listener and installs | 488 // Currently inspector still uses C++ event listener and installs |
602 // more specific event listeners for part of events. Calling of | 489 // more specific event listeners for part of events. Calling of |
603 // C++ event listener is redundant when more specific event listener | 490 // C++ event listener is redundant when more specific event listener |
604 // is presented. Other clients can install JavaScript event listener | 491 // is presented. Other clients can install JavaScript event listener |
605 // (e.g. some of NodeJS module). | 492 // (e.g. some of NodeJS module). |
606 bool non_inspector_listener_exists() const { | 493 bool non_inspector_listener_exists() const { |
607 return message_handler_ != nullptr || | 494 return !event_listener_.is_null() && !event_listener_->IsForeign(); |
608 (!event_listener_.is_null() && !event_listener_->IsForeign()); | |
609 } | 495 } |
610 | 496 |
611 void OnException(Handle<Object> exception, Handle<Object> promise); | 497 void OnException(Handle<Object> exception, Handle<Object> promise); |
612 | 498 |
613 // Constructors for debug event objects. | 499 // Constructors for debug event objects. |
614 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); | 500 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); |
615 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( | 501 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( |
616 Handle<Object> break_points_hit); | 502 Handle<Object> break_points_hit); |
617 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( | 503 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( |
618 Handle<Object> exception, | 504 Handle<Object> exception, |
619 bool uncaught, | 505 bool uncaught, |
620 Handle<Object> promise); | 506 Handle<Object> promise); |
621 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( | 507 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( |
622 Handle<Script> script, v8::DebugEvent type); | 508 Handle<Script> script, v8::DebugEvent type); |
623 MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<Smi> type, | 509 MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<Smi> type, |
624 Handle<Smi> id); | 510 Handle<Smi> id); |
625 | 511 |
626 // Mirror cache handling. | 512 // Mirror cache handling. |
627 void ClearMirrorCache(); | 513 void ClearMirrorCache(); |
628 | 514 |
629 void CallEventCallback(v8::DebugEvent event, | |
630 Handle<Object> exec_state, | |
631 Handle<Object> event_data, | |
632 v8::Debug::ClientData* client_data); | |
633 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); | 515 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); |
634 void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data, | 516 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); | |
639 | 517 |
640 // Find the closest source position for a break point for a given position. | 518 // Find the closest source position for a break point for a given position. |
641 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, | 519 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, |
642 BreakPositionAlignment alignment); | 520 BreakPositionAlignment alignment); |
643 // Instrument code to break at break points. | 521 // Instrument code to break at break points. |
644 void ApplyBreakPoints(Handle<DebugInfo> debug_info); | 522 void ApplyBreakPoints(Handle<DebugInfo> debug_info); |
645 // Clear code from instrumentation. | 523 // Clear code from instrumentation. |
646 void ClearBreakPoints(Handle<DebugInfo> debug_info); | 524 void ClearBreakPoints(Handle<DebugInfo> debug_info); |
647 // Clear all code from instrumentation. | 525 // Clear all code from instrumentation. |
648 void ClearAllBreakPoints(); | 526 void ClearAllBreakPoints(); |
(...skipping 20 matching lines...) Expand all Loading... |
669 | 547 |
670 void ThreadInit(); | 548 void ThreadInit(); |
671 | 549 |
672 void PrintBreakLocation(); | 550 void PrintBreakLocation(); |
673 | 551 |
674 // Global handles. | 552 // Global handles. |
675 Handle<Context> debug_context_; | 553 Handle<Context> debug_context_; |
676 Handle<Object> event_listener_; | 554 Handle<Object> event_listener_; |
677 Handle<Object> event_listener_data_; | 555 Handle<Object> event_listener_data_; |
678 | 556 |
679 v8::Debug::MessageHandler message_handler_; | |
680 | |
681 debug::DebugEventListener* debug_event_listener_ = nullptr; | 557 debug::DebugEventListener* debug_event_listener_ = nullptr; |
682 | 558 |
683 static const int kQueueInitialSize = 4; | |
684 base::Semaphore command_received_; // Signaled for each command received. | |
685 LockingCommandMessageQueue command_queue_; | |
686 | |
687 // Debugger is active, i.e. there is a debug event listener attached. | 559 // Debugger is active, i.e. there is a debug event listener attached. |
688 bool is_active_; | 560 bool is_active_; |
689 // Debugger needs to be notified on every new function call. | 561 // Debugger needs to be notified on every new function call. |
690 // Used for stepping and read-only checks | 562 // Used for stepping and read-only checks |
691 bool hook_on_function_call_; | 563 bool hook_on_function_call_; |
692 // Suppress debug events. | 564 // Suppress debug events. |
693 bool is_suppressed_; | 565 bool is_suppressed_; |
694 // LiveEdit is enabled. | 566 // LiveEdit is enabled. |
695 bool live_edit_enabled_; | 567 bool live_edit_enabled_; |
696 // Do not trigger debug break events. | 568 // Do not trigger debug break events. |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 Handle<Code> code); | 755 Handle<Code> code); |
884 static bool DebugBreakSlotIsPatched(Address pc); | 756 static bool DebugBreakSlotIsPatched(Address pc); |
885 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); | 757 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); |
886 }; | 758 }; |
887 | 759 |
888 | 760 |
889 } // namespace internal | 761 } // namespace internal |
890 } // namespace v8 | 762 } // namespace v8 |
891 | 763 |
892 #endif // V8_DEBUG_DEBUG_H_ | 764 #endif // V8_DEBUG_DEBUG_H_ |
OLD | NEW |