| 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_H_ | 5 #ifndef V8_DEBUG_H_ |
| 6 #define V8_DEBUG_H_ | 6 #define V8_DEBUG_H_ |
| 7 | 7 |
| 8 #include "allocation.h" | 8 #include "allocation.h" |
| 9 #include "arguments.h" | 9 #include "arguments.h" |
| 10 #include "assembler.h" | 10 #include "assembler.h" |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 Handle<DebugInfo> debug_info() { return debug_info_; } | 195 Handle<DebugInfo> debug_info() { return debug_info_; } |
| 196 | 196 |
| 197 private: | 197 private: |
| 198 // Global (weak) handle to the debug info object. | 198 // Global (weak) handle to the debug info object. |
| 199 Handle<DebugInfo> debug_info_; | 199 Handle<DebugInfo> debug_info_; |
| 200 | 200 |
| 201 // Next pointer for linked list. | 201 // Next pointer for linked list. |
| 202 DebugInfoListNode* next_; | 202 DebugInfoListNode* next_; |
| 203 }; | 203 }; |
| 204 | 204 |
| 205 |
| 206 |
| 207 // Message delivered to the message handler callback. This is either a debugger |
| 208 // event or the response to a command. |
| 209 class MessageImpl: public v8::Debug::Message { |
| 210 public: |
| 211 // Create a message object for a debug event. |
| 212 static MessageImpl NewEvent(DebugEvent event, |
| 213 bool running, |
| 214 Handle<JSObject> exec_state, |
| 215 Handle<JSObject> event_data); |
| 216 |
| 217 // Create a message object for the response to a debug command. |
| 218 static MessageImpl NewResponse(DebugEvent event, |
| 219 bool running, |
| 220 Handle<JSObject> exec_state, |
| 221 Handle<JSObject> event_data, |
| 222 Handle<String> response_json, |
| 223 v8::Debug::ClientData* client_data); |
| 224 |
| 225 // Implementation of interface v8::Debug::Message. |
| 226 virtual bool IsEvent() const; |
| 227 virtual bool IsResponse() const; |
| 228 virtual DebugEvent GetEvent() const; |
| 229 virtual bool WillStartRunning() const; |
| 230 virtual v8::Handle<v8::Object> GetExecutionState() const; |
| 231 virtual v8::Handle<v8::Object> GetEventData() const; |
| 232 virtual v8::Handle<v8::String> GetJSON() const; |
| 233 virtual v8::Handle<v8::Context> GetEventContext() const; |
| 234 virtual v8::Debug::ClientData* GetClientData() const; |
| 235 virtual v8::Isolate* GetIsolate() const; |
| 236 |
| 237 private: |
| 238 MessageImpl(bool is_event, |
| 239 DebugEvent event, |
| 240 bool running, |
| 241 Handle<JSObject> exec_state, |
| 242 Handle<JSObject> event_data, |
| 243 Handle<String> response_json, |
| 244 v8::Debug::ClientData* client_data); |
| 245 |
| 246 bool is_event_; // Does this message represent a debug event? |
| 247 DebugEvent event_; // Debug event causing the break. |
| 248 bool running_; // Will the VM start running after this event? |
| 249 Handle<JSObject> exec_state_; // Current execution state. |
| 250 Handle<JSObject> event_data_; // Data associated with the event. |
| 251 Handle<String> response_json_; // Response JSON if message holds a response. |
| 252 v8::Debug::ClientData* client_data_; // Client data passed with the request. |
| 253 }; |
| 254 |
| 255 |
| 256 // Details of the debug event delivered to the debug event listener. |
| 257 class EventDetailsImpl : public v8::Debug::EventDetails { |
| 258 public: |
| 259 EventDetailsImpl(DebugEvent event, |
| 260 Handle<JSObject> exec_state, |
| 261 Handle<JSObject> event_data, |
| 262 Handle<Object> callback_data, |
| 263 v8::Debug::ClientData* client_data); |
| 264 virtual DebugEvent GetEvent() const; |
| 265 virtual v8::Handle<v8::Object> GetExecutionState() const; |
| 266 virtual v8::Handle<v8::Object> GetEventData() const; |
| 267 virtual v8::Handle<v8::Context> GetEventContext() const; |
| 268 virtual v8::Handle<v8::Value> GetCallbackData() const; |
| 269 virtual v8::Debug::ClientData* GetClientData() const; |
| 270 private: |
| 271 DebugEvent event_; // Debug event causing the break. |
| 272 Handle<JSObject> exec_state_; // Current execution state. |
| 273 Handle<JSObject> event_data_; // Data associated with the event. |
| 274 Handle<Object> callback_data_; // User data passed with the callback |
| 275 // when it was registered. |
| 276 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. |
| 277 }; |
| 278 |
| 279 |
| 280 // Message send by user to v8 debugger or debugger output message. |
| 281 // In addition to command text it may contain a pointer to some user data |
| 282 // which are expected to be passed along with the command reponse to message |
| 283 // handler. |
| 284 class CommandMessage { |
| 285 public: |
| 286 static CommandMessage New(const Vector<uint16_t>& command, |
| 287 v8::Debug::ClientData* data); |
| 288 CommandMessage(); |
| 289 ~CommandMessage(); |
| 290 |
| 291 // Deletes user data and disposes of the text. |
| 292 void Dispose(); |
| 293 Vector<uint16_t> text() const { return text_; } |
| 294 v8::Debug::ClientData* client_data() const { return client_data_; } |
| 295 private: |
| 296 CommandMessage(const Vector<uint16_t>& text, |
| 297 v8::Debug::ClientData* data); |
| 298 |
| 299 Vector<uint16_t> text_; |
| 300 v8::Debug::ClientData* client_data_; |
| 301 }; |
| 302 |
| 303 |
| 304 // A Queue of CommandMessage objects. A thread-safe version is |
| 305 // LockingCommandMessageQueue, based on this class. |
| 306 class CommandMessageQueue BASE_EMBEDDED { |
| 307 public: |
| 308 explicit CommandMessageQueue(int size); |
| 309 ~CommandMessageQueue(); |
| 310 bool IsEmpty() const { return start_ == end_; } |
| 311 CommandMessage Get(); |
| 312 void Put(const CommandMessage& message); |
| 313 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). |
| 314 private: |
| 315 // Doubles the size of the message queue, and copies the messages. |
| 316 void Expand(); |
| 317 |
| 318 CommandMessage* messages_; |
| 319 int start_; |
| 320 int end_; |
| 321 int size_; // The size of the queue buffer. Queue can hold size-1 messages. |
| 322 }; |
| 323 |
| 324 |
| 325 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage |
| 326 // messages. The message data is not managed by LockingCommandMessageQueue. |
| 327 // Pointers to the data are passed in and out. Implemented by adding a |
| 328 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. |
| 329 class LockingCommandMessageQueue BASE_EMBEDDED { |
| 330 public: |
| 331 LockingCommandMessageQueue(Logger* logger, int size); |
| 332 bool IsEmpty() const; |
| 333 CommandMessage Get(); |
| 334 void Put(const CommandMessage& message); |
| 335 void Clear(); |
| 336 private: |
| 337 Logger* logger_; |
| 338 CommandMessageQueue queue_; |
| 339 mutable Mutex mutex_; |
| 340 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); |
| 341 }; |
| 342 |
| 343 |
| 205 // This class contains the debugger support. The main purpose is to handle | 344 // This class contains the debugger support. The main purpose is to handle |
| 206 // setting break points in the code. | 345 // setting break points in the code. |
| 207 // | 346 // |
| 208 // This class controls the debug info for all functions which currently have | 347 // This class controls the debug info for all functions which currently have |
| 209 // active breakpoints in them. This debug info is held in the heap root object | 348 // active breakpoints in them. This debug info is held in the heap root object |
| 210 // debug_info which is a FixedArray. Each entry in this list is of class | 349 // debug_info which is a FixedArray. Each entry in this list is of class |
| 211 // DebugInfo. | 350 // DebugInfo. |
| 212 class Debug { | 351 class Debug { |
| 213 public: | 352 public: |
| 353 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); |
| 354 void OnException(Handle<Object> exception, bool uncaught); |
| 355 void OnBeforeCompile(Handle<Script> script); |
| 356 |
| 357 enum AfterCompileFlags { |
| 358 NO_AFTER_COMPILE_FLAGS, |
| 359 SEND_WHEN_DEBUGGING |
| 360 }; |
| 361 void OnAfterCompile(Handle<Script> script, |
| 362 AfterCompileFlags after_compile_flags); |
| 363 void OnScriptCollected(int id); |
| 364 |
| 365 void SetEventListener(Handle<Object> callback, Handle<Object> data); |
| 366 void SetMessageHandler(v8::Debug::MessageHandler handler); |
| 367 |
| 368 // Add a debugger command to the command queue. |
| 369 void EnqueueCommandMessage(Vector<const uint16_t> command, |
| 370 v8::Debug::ClientData* client_data = NULL); |
| 371 |
| 372 // Check whether there are commands in the command queue. |
| 373 bool HasCommands(); |
| 374 |
| 375 // Enqueue a debugger command to the command queue for event listeners. |
| 376 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); |
| 377 |
| 378 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun, |
| 379 Handle<Object> data); |
| 380 |
| 381 Handle<Context> GetDebugContext(); |
| 382 |
| 383 bool ignore_debugger() const { return ignore_debugger_; } |
| 384 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } |
| 385 bool live_edit_enabled() const { |
| 386 return FLAG_enable_liveedit && live_edit_enabled_ ; |
| 387 } |
| 388 |
| 389 bool is_active() { return is_active_; } |
| 390 |
| 391 class IgnoreScope { |
| 392 public: |
| 393 explicit IgnoreScope(Debug* debug) |
| 394 : debug_(debug), |
| 395 old_state_(debug->ignore_debugger_) { |
| 396 debug_->ignore_debugger_ = true; |
| 397 } |
| 398 |
| 399 ~IgnoreScope() { |
| 400 debug_->ignore_debugger_ = old_state_; |
| 401 } |
| 402 |
| 403 private: |
| 404 Debug* debug_; |
| 405 bool old_state_; |
| 406 DISALLOW_COPY_AND_ASSIGN(IgnoreScope); |
| 407 }; |
| 408 |
| 409 |
| 214 bool Load(); | 410 bool Load(); |
| 215 void Unload(); | 411 void Unload(); |
| 216 bool IsLoaded() { return !debug_context_.is_null(); } | 412 bool IsLoaded() { return !debug_context_.is_null(); } |
| 217 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } | 413 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } |
| 218 | 414 |
| 219 Object* Break(Arguments args); | 415 Object* Break(Arguments args); |
| 220 bool SetBreakPoint(Handle<JSFunction> function, | 416 bool SetBreakPoint(Handle<JSFunction> function, |
| 221 Handle<Object> break_point_object, | 417 Handle<Object> break_point_object, |
| 222 int* source_position); | 418 int* source_position); |
| 223 bool SetBreakPointForScript(Handle<Script> script, | 419 bool SetBreakPointForScript(Handle<Script> script, |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 return reinterpret_cast<Address>(address); | 547 return reinterpret_cast<Address>(address); |
| 352 } | 548 } |
| 353 | 549 |
| 354 static const int kEstimatedNofDebugInfoEntries = 16; | 550 static const int kEstimatedNofDebugInfoEntries = 16; |
| 355 static const int kEstimatedNofBreakPointsInFunction = 16; | 551 static const int kEstimatedNofBreakPointsInFunction = 16; |
| 356 | 552 |
| 357 // Passed to MakeWeak. | 553 // Passed to MakeWeak. |
| 358 static void HandleWeakDebugInfo( | 554 static void HandleWeakDebugInfo( |
| 359 const v8::WeakCallbackData<v8::Value, void>& data); | 555 const v8::WeakCallbackData<v8::Value, void>& data); |
| 360 | 556 |
| 361 friend class Debugger; | |
| 362 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc | 557 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc |
| 363 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc | 558 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc |
| 364 | 559 |
| 365 // Threading support. | 560 // Threading support. |
| 366 char* ArchiveDebug(char* to); | 561 char* ArchiveDebug(char* to); |
| 367 char* RestoreDebug(char* from); | 562 char* RestoreDebug(char* from); |
| 368 static int ArchiveSpacePerThread(); | 563 static int ArchiveSpacePerThread(); |
| 369 void FreeThreadResources() { } | 564 void FreeThreadResources() { } |
| 370 | 565 |
| 371 // Mirror cache handling. | 566 // Mirror cache handling. |
| 372 void ClearMirrorCache(); | 567 void ClearMirrorCache(); |
| 373 | 568 |
| 374 // Script cache handling. | 569 // Script cache handling. |
| 375 void CreateScriptCache(); | 570 void CreateScriptCache(); |
| 376 void DestroyScriptCache(); | 571 void DestroyScriptCache(); |
| 377 void AddScriptToScriptCache(Handle<Script> script); | 572 void AddScriptToScriptCache(Handle<Script> script); |
| 378 Handle<FixedArray> GetLoadedScripts(); | 573 Handle<FixedArray> GetLoadedScripts(); |
| 379 | 574 |
| 380 // Record function from which eval was called. | 575 // Record function from which eval was called. |
| 381 static void RecordEvalCaller(Handle<Script> script); | 576 static void RecordEvalCaller(Handle<Script> script); |
| 382 | 577 |
| 383 // Garbage collection notifications. | 578 // Garbage collection notifications. |
| 384 void AfterGarbageCollection(); | 579 void AfterGarbageCollection(); |
| 385 | 580 |
| 386 // Code generator routines. | |
| 387 static void GenerateSlot(MacroAssembler* masm); | |
| 388 static void GenerateCallICStubDebugBreak(MacroAssembler* masm); | |
| 389 static void GenerateLoadICDebugBreak(MacroAssembler* masm); | |
| 390 static void GenerateStoreICDebugBreak(MacroAssembler* masm); | |
| 391 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); | |
| 392 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); | |
| 393 static void GenerateCompareNilICDebugBreak(MacroAssembler* masm); | |
| 394 static void GenerateReturnDebugBreak(MacroAssembler* masm); | |
| 395 static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm); | |
| 396 static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm); | |
| 397 static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm); | |
| 398 static void GenerateSlotDebugBreak(MacroAssembler* masm); | |
| 399 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm); | |
| 400 | |
| 401 // FrameDropper is a code replacement for a JavaScript frame with possibly | |
| 402 // several frames above. | |
| 403 // There is no calling conventions here, because it never actually gets | |
| 404 // called, it only gets returned to. | |
| 405 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); | |
| 406 | |
| 407 // Describes how exactly a frame has been dropped from stack. | 581 // Describes how exactly a frame has been dropped from stack. |
| 408 enum FrameDropMode { | 582 enum FrameDropMode { |
| 409 // No frame has been dropped. | 583 // No frame has been dropped. |
| 410 FRAMES_UNTOUCHED, | 584 FRAMES_UNTOUCHED, |
| 411 // The top JS frame had been calling IC stub. IC stub mustn't be called now. | 585 // The top JS frame had been calling IC stub. IC stub mustn't be called now. |
| 412 FRAME_DROPPED_IN_IC_CALL, | 586 FRAME_DROPPED_IN_IC_CALL, |
| 413 // The top JS frame had been calling debug break slot stub. Patch the | 587 // The top JS frame had been calling debug break slot stub. Patch the |
| 414 // address this stub jumps to in the end. | 588 // address this stub jumps to in the end. |
| 415 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, | 589 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, |
| 416 // The top JS frame had been calling some C++ function. The return address | 590 // The top JS frame had been calling some C++ function. The return address |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 // Normally equals 1. Stored on stack in form of Smi. | 654 // Normally equals 1. Stored on stack in form of Smi. |
| 481 static const int kInitialSize; | 655 static const int kInitialSize; |
| 482 // A value that padding words are filled with (in form of Smi). Going | 656 // A value that padding words are filled with (in form of Smi). Going |
| 483 // bottom-top, the first word not having this value is a counter word. | 657 // bottom-top, the first word not having this value is a counter word. |
| 484 static const int kPaddingValue; | 658 static const int kPaddingValue; |
| 485 }; | 659 }; |
| 486 | 660 |
| 487 private: | 661 private: |
| 488 explicit Debug(Isolate* isolate); | 662 explicit Debug(Isolate* isolate); |
| 489 | 663 |
| 664 MUST_USE_RESULT MaybeHandle<Object> MakeJSObject( |
| 665 Vector<const char> constructor_name, |
| 666 int argc, |
| 667 Handle<Object> argv[]); |
| 668 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); |
| 669 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( |
| 670 Handle<Object> break_points_hit); |
| 671 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( |
| 672 Handle<Object> exception, |
| 673 bool uncaught, |
| 674 Handle<Object> promise); |
| 675 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( |
| 676 Handle<Script> script, bool before); |
| 677 MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id); |
| 678 |
| 679 void CallEventCallback(v8::DebugEvent event, |
| 680 Handle<Object> exec_state, |
| 681 Handle<Object> event_data, |
| 682 v8::Debug::ClientData* client_data); |
| 683 void CallCEventCallback(v8::DebugEvent event, |
| 684 Handle<Object> exec_state, |
| 685 Handle<Object> event_data, |
| 686 v8::Debug::ClientData* client_data); |
| 687 void CallJSEventCallback(v8::DebugEvent event, |
| 688 Handle<Object> exec_state, |
| 689 Handle<Object> event_data); |
| 690 void UpdateState(); |
| 691 |
| 692 void ProcessDebugEvent(v8::DebugEvent event, |
| 693 Handle<JSObject> event_data, |
| 694 bool auto_continue); |
| 695 void NotifyMessageHandler(v8::DebugEvent event, |
| 696 Handle<JSObject> exec_state, |
| 697 Handle<JSObject> event_data, |
| 698 bool auto_continue); |
| 699 |
| 700 // Invoke the message handler function. |
| 701 void InvokeMessageHandler(MessageImpl message); |
| 702 |
| 703 inline bool EventActive() { |
| 704 // Check whether the message handler was been cleared. |
| 705 // TODO(yangguo): handle loading and unloading of the debugger differently. |
| 706 // Currently argument event is not used. |
| 707 return !ignore_debugger_ && is_active_; |
| 708 } |
| 709 |
| 490 static bool CompileDebuggerScript(Isolate* isolate, int index); | 710 static bool CompileDebuggerScript(Isolate* isolate, int index); |
| 491 void ClearOneShot(); | 711 void ClearOneShot(); |
| 492 void ActivateStepIn(StackFrame* frame); | 712 void ActivateStepIn(StackFrame* frame); |
| 493 void ClearStepIn(); | 713 void ClearStepIn(); |
| 494 void ActivateStepOut(StackFrame* frame); | 714 void ActivateStepOut(StackFrame* frame); |
| 495 void ClearStepNext(); | 715 void ClearStepNext(); |
| 496 // Returns whether the compile succeeded. | 716 // Returns whether the compile succeeded. |
| 497 void RemoveDebugInfo(Handle<DebugInfo> debug_info); | 717 void RemoveDebugInfo(Handle<DebugInfo> debug_info); |
| 498 void SetAfterBreakTarget(JavaScriptFrame* frame); | 718 void SetAfterBreakTarget(JavaScriptFrame* frame); |
| 499 Handle<Object> CheckBreakPoints(Handle<Object> break_point); | 719 Handle<Object> CheckBreakPoints(Handle<Object> break_point); |
| 500 bool CheckBreakPoint(Handle<Object> break_point_object); | 720 bool CheckBreakPoint(Handle<Object> break_point_object); |
| 501 | 721 |
| 502 void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function); | 722 void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function); |
| 503 void RecompileAndRelocateSuspendedGenerators( | 723 void RecompileAndRelocateSuspendedGenerators( |
| 504 const List<Handle<JSGeneratorObject> > &suspended_generators); | 724 const List<Handle<JSGeneratorObject> > &suspended_generators); |
| 505 | 725 |
| 506 // Global handle to debug context where all the debugger JavaScript code is | 726 void ThreadInit(); |
| 507 // loaded. | |
| 508 Handle<Context> debug_context_; | |
| 509 | |
| 510 // Boolean state indicating whether any break points are set. | |
| 511 bool has_break_points_; | |
| 512 | |
| 513 // Cache of all scripts in the heap. | |
| 514 ScriptCache* script_cache_; | |
| 515 | |
| 516 // List of active debug info objects. | |
| 517 DebugInfoListNode* debug_info_list_; | |
| 518 | |
| 519 bool disable_break_; | |
| 520 bool break_on_exception_; | |
| 521 bool break_on_uncaught_exception_; | |
| 522 | 727 |
| 523 class PromiseOnStack { | 728 class PromiseOnStack { |
| 524 public: | 729 public: |
| 525 PromiseOnStack(Isolate* isolate, | 730 PromiseOnStack(Isolate* isolate, |
| 526 PromiseOnStack* prev, | 731 PromiseOnStack* prev, |
| 527 Handle<JSFunction> getter); | 732 Handle<JSFunction> getter); |
| 528 ~PromiseOnStack(); | 733 ~PromiseOnStack(); |
| 529 StackHandler* handler() { return handler_; } | 734 StackHandler* handler() { return handler_; } |
| 530 Handle<JSFunction> getter() { return getter_; } | 735 Handle<JSFunction> getter() { return getter_; } |
| 531 PromiseOnStack* prev() { return prev_; } | 736 PromiseOnStack* prev() { return prev_; } |
| 532 private: | 737 private: |
| 533 Isolate* isolate_; | 738 Isolate* isolate_; |
| 534 StackHandler* handler_; | 739 StackHandler* handler_; |
| 535 Handle<JSFunction> getter_; | 740 Handle<JSFunction> getter_; |
| 536 PromiseOnStack* prev_; | 741 PromiseOnStack* prev_; |
| 537 }; | 742 }; |
| 538 | 743 |
| 744 // Global handles. |
| 745 Handle<Context> debug_context_; |
| 746 Handle<Object> event_listener_; |
| 747 Handle<Object> event_listener_data_; |
| 748 |
| 749 v8::Debug::MessageHandler message_handler_; |
| 750 |
| 751 static const int kQueueInitialSize = 4; |
| 752 Semaphore command_received_; // Signaled for each command received. |
| 753 LockingCommandMessageQueue command_queue_; |
| 754 LockingCommandMessageQueue event_command_queue_; |
| 755 |
| 756 bool is_active_; |
| 757 bool ignore_debugger_; |
| 758 bool live_edit_enabled_; |
| 759 bool has_break_points_; |
| 760 bool disable_break_; |
| 761 bool break_on_exception_; |
| 762 bool break_on_uncaught_exception_; |
| 763 |
| 764 ScriptCache* script_cache_; // Cache of all scripts in the heap. |
| 765 DebugInfoListNode* debug_info_list_; // List of active debug info objects. |
| 766 |
| 539 // Per-thread data. | 767 // Per-thread data. |
| 540 class ThreadLocal { | 768 class ThreadLocal { |
| 541 public: | 769 public: |
| 542 // Counter for generating next break id. | 770 // Counter for generating next break id. |
| 543 int break_count_; | 771 int break_count_; |
| 544 | 772 |
| 545 // Current break id. | 773 // Current break id. |
| 546 int break_id_; | 774 int break_id_; |
| 547 | 775 |
| 548 // Frame id for the frame of the current break. | 776 // Frame id for the frame of the current break. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 // When a promise is being resolved, we may want to trigger a debug event | 819 // When a promise is being resolved, we may want to trigger a debug event |
| 592 // if we catch a throw. For this purpose we remember the try-catch | 820 // if we catch a throw. For this purpose we remember the try-catch |
| 593 // handler address that would catch the exception. We also hold onto a | 821 // handler address that would catch the exception. We also hold onto a |
| 594 // closure that returns a promise if the exception is considered uncaught. | 822 // closure that returns a promise if the exception is considered uncaught. |
| 595 // Due to the possibility of reentry we use a linked list. | 823 // Due to the possibility of reentry we use a linked list. |
| 596 PromiseOnStack* promise_on_stack_; | 824 PromiseOnStack* promise_on_stack_; |
| 597 }; | 825 }; |
| 598 | 826 |
| 599 // Storage location for registers when handling debug break calls | 827 // Storage location for registers when handling debug break calls |
| 600 ThreadLocal thread_local_; | 828 ThreadLocal thread_local_; |
| 601 void ThreadInit(); | |
| 602 | 829 |
| 603 Isolate* isolate_; | 830 Isolate* isolate_; |
| 604 | 831 |
| 605 friend class Isolate; | 832 friend class Isolate; |
| 833 friend class EnterDebugger; |
| 606 | 834 |
| 607 DISALLOW_COPY_AND_ASSIGN(Debug); | 835 DISALLOW_COPY_AND_ASSIGN(Debug); |
| 608 }; | 836 }; |
| 609 | 837 |
| 610 | 838 |
| 611 DECLARE_RUNTIME_FUNCTION(Debug_Break); | 839 DECLARE_RUNTIME_FUNCTION(Debug_Break); |
| 612 | 840 |
| 613 | 841 |
| 614 // Message delivered to the message handler callback. This is either a debugger | |
| 615 // event or the response to a command. | |
| 616 class MessageImpl: public v8::Debug::Message { | |
| 617 public: | |
| 618 // Create a message object for a debug event. | |
| 619 static MessageImpl NewEvent(DebugEvent event, | |
| 620 bool running, | |
| 621 Handle<JSObject> exec_state, | |
| 622 Handle<JSObject> event_data); | |
| 623 | |
| 624 // Create a message object for the response to a debug command. | |
| 625 static MessageImpl NewResponse(DebugEvent event, | |
| 626 bool running, | |
| 627 Handle<JSObject> exec_state, | |
| 628 Handle<JSObject> event_data, | |
| 629 Handle<String> response_json, | |
| 630 v8::Debug::ClientData* client_data); | |
| 631 | |
| 632 // Implementation of interface v8::Debug::Message. | |
| 633 virtual bool IsEvent() const; | |
| 634 virtual bool IsResponse() const; | |
| 635 virtual DebugEvent GetEvent() const; | |
| 636 virtual bool WillStartRunning() const; | |
| 637 virtual v8::Handle<v8::Object> GetExecutionState() const; | |
| 638 virtual v8::Handle<v8::Object> GetEventData() const; | |
| 639 virtual v8::Handle<v8::String> GetJSON() const; | |
| 640 virtual v8::Handle<v8::Context> GetEventContext() const; | |
| 641 virtual v8::Debug::ClientData* GetClientData() const; | |
| 642 virtual v8::Isolate* GetIsolate() const; | |
| 643 | |
| 644 private: | |
| 645 MessageImpl(bool is_event, | |
| 646 DebugEvent event, | |
| 647 bool running, | |
| 648 Handle<JSObject> exec_state, | |
| 649 Handle<JSObject> event_data, | |
| 650 Handle<String> response_json, | |
| 651 v8::Debug::ClientData* client_data); | |
| 652 | |
| 653 bool is_event_; // Does this message represent a debug event? | |
| 654 DebugEvent event_; // Debug event causing the break. | |
| 655 bool running_; // Will the VM start running after this event? | |
| 656 Handle<JSObject> exec_state_; // Current execution state. | |
| 657 Handle<JSObject> event_data_; // Data associated with the event. | |
| 658 Handle<String> response_json_; // Response JSON if message holds a response. | |
| 659 v8::Debug::ClientData* client_data_; // Client data passed with the request. | |
| 660 }; | |
| 661 | |
| 662 | |
| 663 // Details of the debug event delivered to the debug event listener. | |
| 664 class EventDetailsImpl : public v8::Debug::EventDetails { | |
| 665 public: | |
| 666 EventDetailsImpl(DebugEvent event, | |
| 667 Handle<JSObject> exec_state, | |
| 668 Handle<JSObject> event_data, | |
| 669 Handle<Object> callback_data, | |
| 670 v8::Debug::ClientData* client_data); | |
| 671 virtual DebugEvent GetEvent() const; | |
| 672 virtual v8::Handle<v8::Object> GetExecutionState() const; | |
| 673 virtual v8::Handle<v8::Object> GetEventData() const; | |
| 674 virtual v8::Handle<v8::Context> GetEventContext() const; | |
| 675 virtual v8::Handle<v8::Value> GetCallbackData() const; | |
| 676 virtual v8::Debug::ClientData* GetClientData() const; | |
| 677 private: | |
| 678 DebugEvent event_; // Debug event causing the break. | |
| 679 Handle<JSObject> exec_state_; // Current execution state. | |
| 680 Handle<JSObject> event_data_; // Data associated with the event. | |
| 681 Handle<Object> callback_data_; // User data passed with the callback | |
| 682 // when it was registered. | |
| 683 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. | |
| 684 }; | |
| 685 | |
| 686 | |
| 687 // Message send by user to v8 debugger or debugger output message. | |
| 688 // In addition to command text it may contain a pointer to some user data | |
| 689 // which are expected to be passed along with the command reponse to message | |
| 690 // handler. | |
| 691 class CommandMessage { | |
| 692 public: | |
| 693 static CommandMessage New(const Vector<uint16_t>& command, | |
| 694 v8::Debug::ClientData* data); | |
| 695 CommandMessage(); | |
| 696 ~CommandMessage(); | |
| 697 | |
| 698 // Deletes user data and disposes of the text. | |
| 699 void Dispose(); | |
| 700 Vector<uint16_t> text() const { return text_; } | |
| 701 v8::Debug::ClientData* client_data() const { return client_data_; } | |
| 702 private: | |
| 703 CommandMessage(const Vector<uint16_t>& text, | |
| 704 v8::Debug::ClientData* data); | |
| 705 | |
| 706 Vector<uint16_t> text_; | |
| 707 v8::Debug::ClientData* client_data_; | |
| 708 }; | |
| 709 | |
| 710 // A Queue of CommandMessage objects. A thread-safe version is | |
| 711 // LockingCommandMessageQueue, based on this class. | |
| 712 class CommandMessageQueue BASE_EMBEDDED { | |
| 713 public: | |
| 714 explicit CommandMessageQueue(int size); | |
| 715 ~CommandMessageQueue(); | |
| 716 bool IsEmpty() const { return start_ == end_; } | |
| 717 CommandMessage Get(); | |
| 718 void Put(const CommandMessage& message); | |
| 719 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). | |
| 720 private: | |
| 721 // Doubles the size of the message queue, and copies the messages. | |
| 722 void Expand(); | |
| 723 | |
| 724 CommandMessage* messages_; | |
| 725 int start_; | |
| 726 int end_; | |
| 727 int size_; // The size of the queue buffer. Queue can hold size-1 messages. | |
| 728 }; | |
| 729 | |
| 730 | |
| 731 class MessageDispatchHelperThread; | |
| 732 | |
| 733 | |
| 734 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage | |
| 735 // messages. The message data is not managed by LockingCommandMessageQueue. | |
| 736 // Pointers to the data are passed in and out. Implemented by adding a | |
| 737 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. | |
| 738 class LockingCommandMessageQueue BASE_EMBEDDED { | |
| 739 public: | |
| 740 LockingCommandMessageQueue(Logger* logger, int size); | |
| 741 bool IsEmpty() const; | |
| 742 CommandMessage Get(); | |
| 743 void Put(const CommandMessage& message); | |
| 744 void Clear(); | |
| 745 private: | |
| 746 Logger* logger_; | |
| 747 CommandMessageQueue queue_; | |
| 748 mutable Mutex mutex_; | |
| 749 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); | |
| 750 }; | |
| 751 | |
| 752 | |
| 753 class Debugger { | |
| 754 public: | |
| 755 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); | |
| 756 void OnException(Handle<Object> exception, bool uncaught); | |
| 757 void OnBeforeCompile(Handle<Script> script); | |
| 758 | |
| 759 enum AfterCompileFlags { | |
| 760 NO_AFTER_COMPILE_FLAGS, | |
| 761 SEND_WHEN_DEBUGGING | |
| 762 }; | |
| 763 void OnAfterCompile(Handle<Script> script, | |
| 764 AfterCompileFlags after_compile_flags); | |
| 765 void OnScriptCollected(int id); | |
| 766 | |
| 767 void SetEventListener(Handle<Object> callback, Handle<Object> data); | |
| 768 void SetMessageHandler(v8::Debug::MessageHandler handler); | |
| 769 | |
| 770 // Add a debugger command to the command queue. | |
| 771 void EnqueueCommandMessage(Vector<const uint16_t> command, | |
| 772 v8::Debug::ClientData* client_data = NULL); | |
| 773 | |
| 774 // Check whether there are commands in the command queue. | |
| 775 bool HasCommands(); | |
| 776 | |
| 777 // Enqueue a debugger command to the command queue for event listeners. | |
| 778 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); | |
| 779 | |
| 780 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun, | |
| 781 Handle<Object> data); | |
| 782 | |
| 783 Handle<Context> GetDebugContext(); | |
| 784 | |
| 785 bool ignore_debugger() const { return ignore_debugger_; } | |
| 786 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } | |
| 787 bool live_edit_enabled() const { | |
| 788 return FLAG_enable_liveedit && live_edit_enabled_ ; | |
| 789 } | |
| 790 | |
| 791 bool is_active() { return is_active_; } | |
| 792 | |
| 793 class IgnoreScope { | |
| 794 public: | |
| 795 explicit IgnoreScope(Debugger* debugger) | |
| 796 : debugger_(debugger), | |
| 797 old_state_(debugger_->ignore_debugger_) { | |
| 798 debugger_->ignore_debugger_ = true; | |
| 799 } | |
| 800 | |
| 801 ~IgnoreScope() { | |
| 802 debugger_->ignore_debugger_ = old_state_; | |
| 803 } | |
| 804 | |
| 805 private: | |
| 806 Debugger* debugger_; | |
| 807 bool old_state_; | |
| 808 DISALLOW_COPY_AND_ASSIGN(IgnoreScope); | |
| 809 }; | |
| 810 | |
| 811 private: | |
| 812 explicit Debugger(Isolate* isolate); | |
| 813 ~Debugger(); | |
| 814 | |
| 815 MUST_USE_RESULT MaybeHandle<Object> MakeJSObject( | |
| 816 Vector<const char> constructor_name, | |
| 817 int argc, | |
| 818 Handle<Object> argv[]); | |
| 819 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); | |
| 820 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( | |
| 821 Handle<Object> break_points_hit); | |
| 822 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( | |
| 823 Handle<Object> exception, | |
| 824 bool uncaught, | |
| 825 Handle<Object> promise); | |
| 826 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( | |
| 827 Handle<Script> script, bool before); | |
| 828 MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id); | |
| 829 | |
| 830 void CallEventCallback(v8::DebugEvent event, | |
| 831 Handle<Object> exec_state, | |
| 832 Handle<Object> event_data, | |
| 833 v8::Debug::ClientData* client_data); | |
| 834 void CallCEventCallback(v8::DebugEvent event, | |
| 835 Handle<Object> exec_state, | |
| 836 Handle<Object> event_data, | |
| 837 v8::Debug::ClientData* client_data); | |
| 838 void CallJSEventCallback(v8::DebugEvent event, | |
| 839 Handle<Object> exec_state, | |
| 840 Handle<Object> event_data); | |
| 841 void UpdateState(); | |
| 842 | |
| 843 void ProcessDebugEvent(v8::DebugEvent event, | |
| 844 Handle<JSObject> event_data, | |
| 845 bool auto_continue); | |
| 846 void NotifyMessageHandler(v8::DebugEvent event, | |
| 847 Handle<JSObject> exec_state, | |
| 848 Handle<JSObject> event_data, | |
| 849 bool auto_continue); | |
| 850 | |
| 851 // Invoke the message handler function. | |
| 852 void InvokeMessageHandler(MessageImpl message); | |
| 853 | |
| 854 inline bool EventActive() { | |
| 855 // Check whether the message handler was been cleared. | |
| 856 // TODO(yangguo): handle loading and unloading of the debugger differently. | |
| 857 // Currently argument event is not used. | |
| 858 return !ignore_debugger_ && is_active_; | |
| 859 } | |
| 860 | |
| 861 Handle<Object> event_listener_; // Global handle to listener. | |
| 862 Handle<Object> event_listener_data_; | |
| 863 bool is_active_; | |
| 864 bool ignore_debugger_; // Are we temporarily ignoring the debugger? | |
| 865 bool live_edit_enabled_; // Enable LiveEdit. | |
| 866 v8::Debug::MessageHandler message_handler_; | |
| 867 bool debugger_unload_pending_; // Was message handler cleared? | |
| 868 | |
| 869 static const int kQueueInitialSize = 4; | |
| 870 LockingCommandMessageQueue command_queue_; | |
| 871 Semaphore command_received_; // Signaled for each command received. | |
| 872 LockingCommandMessageQueue event_command_queue_; | |
| 873 | |
| 874 Isolate* isolate_; | |
| 875 | |
| 876 friend class EnterDebugger; | |
| 877 friend class Isolate; | |
| 878 | |
| 879 DISALLOW_COPY_AND_ASSIGN(Debugger); | |
| 880 }; | |
| 881 | |
| 882 | |
| 883 // This class is used for entering the debugger. Create an instance in the stack | 842 // This class is used for entering the debugger. Create an instance in the stack |
| 884 // to enter the debugger. This will set the current break state, make sure the | 843 // to enter the debugger. This will set the current break state, make sure the |
| 885 // debugger is loaded and switch to the debugger context. If the debugger for | 844 // debugger is loaded and switch to the debugger context. If the debugger for |
| 886 // some reason could not be entered FailedToEnter will return true. | 845 // some reason could not be entered FailedToEnter will return true. |
| 887 class EnterDebugger BASE_EMBEDDED { | 846 class EnterDebugger BASE_EMBEDDED { |
| 888 public: | 847 public: |
| 889 explicit EnterDebugger(Isolate* isolate); | 848 explicit EnterDebugger(Isolate* isolate); |
| 890 ~EnterDebugger(); | 849 ~EnterDebugger(); |
| 891 | 850 |
| 892 // Check whether the debugger could be entered. | 851 // Check whether the debugger could be entered. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 921 isolate_->debug()->set_disable_break(prev_disable_break_); | 880 isolate_->debug()->set_disable_break(prev_disable_break_); |
| 922 } | 881 } |
| 923 | 882 |
| 924 private: | 883 private: |
| 925 Isolate* isolate_; | 884 Isolate* isolate_; |
| 926 // The previous state of the disable break used to restore the value when this | 885 // The previous state of the disable break used to restore the value when this |
| 927 // object is destructed. | 886 // object is destructed. |
| 928 bool prev_disable_break_; | 887 bool prev_disable_break_; |
| 929 }; | 888 }; |
| 930 | 889 |
| 890 |
| 891 // Code generator routines. |
| 892 class DebugCodegen : public AllStatic { |
| 893 public: |
| 894 static void GenerateSlot(MacroAssembler* masm); |
| 895 static void GenerateCallICStubDebugBreak(MacroAssembler* masm); |
| 896 static void GenerateLoadICDebugBreak(MacroAssembler* masm); |
| 897 static void GenerateStoreICDebugBreak(MacroAssembler* masm); |
| 898 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); |
| 899 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); |
| 900 static void GenerateCompareNilICDebugBreak(MacroAssembler* masm); |
| 901 static void GenerateReturnDebugBreak(MacroAssembler* masm); |
| 902 static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm); |
| 903 static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm); |
| 904 static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm); |
| 905 static void GenerateSlotDebugBreak(MacroAssembler* masm); |
| 906 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm); |
| 907 |
| 908 // FrameDropper is a code replacement for a JavaScript frame with possibly |
| 909 // several frames above. |
| 910 // There is no calling conventions here, because it never actually gets |
| 911 // called, it only gets returned to. |
| 912 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); |
| 913 }; |
| 914 |
| 931 } } // namespace v8::internal | 915 } } // namespace v8::internal |
| 932 | 916 |
| 933 #endif // V8_DEBUG_H_ | 917 #endif // V8_DEBUG_H_ |
| OLD | NEW |