1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_DEBUG_H_ 29 #define V8_DEBUG_H_ 30 31 #include "allocation.h" 32 #include "arguments.h" 33 #include "assembler.h" 34 #include "debug-agent.h" 35 #include "execution.h" 36 #include "factory.h" 37 #include "flags.h" 38 #include "frames-inl.h" 39 #include "hashmap.h" 40 #include "platform.h" 41 #include "string-stream.h" 42 #include "v8threads.h" 43 44 #ifdef ENABLE_DEBUGGER_SUPPORT 45 #include "../include/v8-debug.h" 46 47 namespace v8 { 48 namespace internal { 49 50 51 // Forward declarations. 52 class EnterDebugger; 53 54 55 // Step actions. NOTE: These values are in macros.py as well. 56 enum StepAction { 57 StepNone = -1, // Stepping not prepared. 58 StepOut = 0, // Step out of the current function. 59 StepNext = 1, // Step to the next statement in the current function. 60 StepIn = 2, // Step into new functions invoked or the next statement 61 // in the current function. 62 StepMin = 3, // Perform a minimum step in the current function. 63 StepInMin = 4 // Step into new functions invoked or perform a minimum step 64 // in the current function. 65 }; 66 67 68 // Type of exception break. NOTE: These values are in macros.py as well. 69 enum ExceptionBreakType { 70 BreakException = 0, 71 BreakUncaughtException = 1 72 }; 73 74 75 // Type of exception break. NOTE: These values are in macros.py as well. 76 enum BreakLocatorType { 77 ALL_BREAK_LOCATIONS = 0, 78 SOURCE_BREAK_LOCATIONS = 1 79 }; 80 81 82 // The different types of breakpoint position alignments. 83 // Must match Debug.BreakPositionAlignment in debug-debugger.js 84 enum BreakPositionAlignment { 85 STATEMENT_ALIGNED = 0, 86 BREAK_POSITION_ALIGNED = 1 87 }; 88 89 90 // Class for iterating through the break points in a function and changing 91 // them. 92 class BreakLocationIterator { 93 public: 94 explicit BreakLocationIterator(Handle<DebugInfo> debug_info, 95 BreakLocatorType type); 96 virtual ~BreakLocationIterator(); 97 98 void Next(); 99 void Next(int count); 100 void FindBreakLocationFromAddress(Address pc); 101 void FindBreakLocationFromPosition(int position, 102 BreakPositionAlignment alignment); 103 void Reset(); 104 bool Done() const; 105 void SetBreakPoint(Handle<Object> break_point_object); 106 void ClearBreakPoint(Handle<Object> break_point_object); 107 void SetOneShot(); 108 void ClearOneShot(); 109 bool IsStepInLocation(Isolate* isolate); 110 void PrepareStepIn(Isolate* isolate); 111 bool IsExit() const; 112 bool HasBreakPoint(); 113 bool IsDebugBreak(); 114 Object* BreakPointObjects(); 115 void ClearAllDebugBreak(); 116 117 118 inline int code_position() { 119 return static_cast<int>(pc() - debug_info_->code()->entry()); 120 } 121 inline int break_point() { return break_point_; } 122 inline int position() { return position_; } 123 inline int statement_position() { return statement_position_; } 124 inline Address pc() { return reloc_iterator_->rinfo()->pc(); } 125 inline Code* code() { return debug_info_->code(); } 126 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); } 127 inline RelocInfo::Mode rmode() const { 128 return reloc_iterator_->rinfo()->rmode(); 129 } 130 inline RelocInfo* original_rinfo() { 131 return reloc_iterator_original_->rinfo(); 132 } 133 inline RelocInfo::Mode original_rmode() const { 134 return reloc_iterator_original_->rinfo()->rmode(); 135 } 136 137 bool IsDebuggerStatement(); 138 139 protected: 140 bool RinfoDone() const; 141 void RinfoNext(); 142 143 BreakLocatorType type_; 144 int break_point_; 145 int position_; 146 int statement_position_; 147 Handle<DebugInfo> debug_info_; 148 RelocIterator* reloc_iterator_; 149 RelocIterator* reloc_iterator_original_; 150 151 private: 152 void SetDebugBreak(); 153 void ClearDebugBreak(); 154 155 void SetDebugBreakAtIC(); 156 void ClearDebugBreakAtIC(); 157 158 bool IsDebugBreakAtReturn(); 159 void SetDebugBreakAtReturn(); 160 void ClearDebugBreakAtReturn(); 161 162 bool IsDebugBreakSlot(); 163 bool IsDebugBreakAtSlot(); 164 void SetDebugBreakAtSlot(); 165 void ClearDebugBreakAtSlot(); 166 167 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator); 168 }; 169 170 171 // Cache of all script objects in the heap. When a script is added a weak handle 172 // to it is created and that weak handle is stored in the cache. The weak handle 173 // callback takes care of removing the script from the cache. The key used in 174 // the cache is the script id. 175 class ScriptCache : private HashMap { 176 public: 177 ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {} 178 virtual ~ScriptCache() { Clear(); } 179 180 // Add script to the cache. 181 void Add(Handle<Script> script); 182 183 // Return the scripts in the cache. 184 Handle<FixedArray> GetScripts(); 185 186 // Generate debugger events for collected scripts. 187 void ProcessCollectedScripts(); 188 189 private: 190 // Calculate the hash value from the key (script id). 191 static uint32_t Hash(int key) { 192 return ComputeIntegerHash(key, v8::internal::kZeroHashSeed); 193 } 194 195 // Scripts match if their keys (script id) match. 196 static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; } 197 198 // Clear the cache releasing all the weak handles. 199 void Clear(); 200 201 // Weak handle callback for scripts in the cache. 202 static void HandleWeakScript(v8::Isolate* isolate, 203 v8::Persistent<v8::Value>* obj, 204 void* data); 205 206 // List used during GC to temporarily store id's of collected scripts. 207 List<int> collected_scripts_; 208 }; 209 210 211 // Linked list holding debug info objects. The debug info objects are kept as 212 // weak handles to avoid a debug info object to keep a function alive. 213 class DebugInfoListNode { 214 public: 215 explicit DebugInfoListNode(DebugInfo* debug_info); 216 virtual ~DebugInfoListNode(); 217 218 DebugInfoListNode* next() { return next_; } 219 void set_next(DebugInfoListNode* next) { next_ = next; } 220 Handle<DebugInfo> debug_info() { return debug_info_; } 221 222 private: 223 // Global (weak) handle to the debug info object. 224 Handle<DebugInfo> debug_info_; 225 226 // Next pointer for linked list. 227 DebugInfoListNode* next_; 228 }; 229 230 // This class contains the debugger support. The main purpose is to handle 231 // setting break points in the code. 232 // 233 // This class controls the debug info for all functions which currently have 234 // active breakpoints in them. This debug info is held in the heap root object 235 // debug_info which is a FixedArray. Each entry in this list is of class 236 // DebugInfo. 237 class Debug { 238 public: 239 void SetUp(bool create_heap_objects); 240 bool Load(); 241 void Unload(); 242 bool IsLoaded() { return !debug_context_.is_null(); } 243 bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } 244 void PreemptionWhileInDebugger(); 245 void Iterate(ObjectVisitor* v); 246 247 Object* Break(Arguments args); 248 void SetBreakPoint(Handle<JSFunction> function, 249 Handle<Object> break_point_object, 250 int* source_position); 251 bool SetBreakPointForScript(Handle<Script> script, 252 Handle<Object> break_point_object, 253 int* source_position, 254 BreakPositionAlignment alignment); 255 void ClearBreakPoint(Handle<Object> break_point_object); 256 void ClearAllBreakPoints(); 257 void FloodWithOneShot(Handle<JSFunction> function); 258 void FloodBoundFunctionWithOneShot(Handle<JSFunction> function); 259 void FloodHandlerWithOneShot(); 260 void ChangeBreakOnException(ExceptionBreakType type, bool enable); 261 bool IsBreakOnException(ExceptionBreakType type); 262 void PrepareStep(StepAction step_action, int step_count); 263 void ClearStepping(); 264 void ClearStepOut(); 265 bool IsStepping() { return thread_local_.step_count_ > 0; } 266 bool StepNextContinue(BreakLocationIterator* break_location_iterator, 267 JavaScriptFrame* frame); 268 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); 269 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); 270 271 void PrepareForBreakPoints(); 272 273 // This function is used in FunctionNameUsing* tests. 274 Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position); 275 276 // Returns whether the operation succeeded. Compilation can only be triggered 277 // if a valid closure is passed as the second argument, otherwise the shared 278 // function needs to be compiled already. 279 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 280 Handle<JSFunction> function); 281 282 // Returns true if the current stub call is patched to call the debugger. 283 static bool IsDebugBreak(Address addr); 284 // Returns true if the current return statement has been patched to be 285 // a debugger breakpoint. 286 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); 287 288 // Check whether a code stub with the specified major key is a possible break 289 // point location. 290 static bool IsSourceBreakStub(Code* code); 291 static bool IsBreakStub(Code* code); 292 293 // Find the builtin to use for invoking the debug break 294 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode); 295 296 static Handle<Object> GetSourceBreakLocations( 297 Handle<SharedFunctionInfo> shared, 298 BreakPositionAlignment position_aligment); 299 300 // Getter for the debug_context. 301 inline Handle<Context> debug_context() { return debug_context_; } 302 303 // Check whether a global object is the debug global object. 304 bool IsDebugGlobal(GlobalObject* global); 305 306 // Check whether this frame is just about to return. 307 bool IsBreakAtReturn(JavaScriptFrame* frame); 308 309 // Fast check to see if any break points are active. 310 inline bool has_break_points() { return has_break_points_; } 311 312 void NewBreak(StackFrame::Id break_frame_id); 313 void SetBreak(StackFrame::Id break_frame_id, int break_id); 314 StackFrame::Id break_frame_id() { 315 return thread_local_.break_frame_id_; 316 } 317 int break_id() { return thread_local_.break_id_; } 318 319 bool StepInActive() { return thread_local_.step_into_fp_ != 0; } 320 void HandleStepIn(Handle<JSFunction> function, 321 Handle<Object> holder, 322 Address fp, 323 bool is_constructor); 324 Address step_in_fp() { return thread_local_.step_into_fp_; } 325 Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } 326 327 bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } 328 Address step_out_fp() { return thread_local_.step_out_fp_; } 329 330 EnterDebugger* debugger_entry() { 331 return thread_local_.debugger_entry_; 332 } 333 void set_debugger_entry(EnterDebugger* entry) { 334 thread_local_.debugger_entry_ = entry; 335 } 336 337 // Check whether any of the specified interrupts are pending. 338 bool is_interrupt_pending(InterruptFlag what) { 339 return (thread_local_.pending_interrupts_ & what) != 0; 340 } 341 342 // Set specified interrupts as pending. 343 void set_interrupts_pending(InterruptFlag what) { 344 thread_local_.pending_interrupts_ |= what; 345 } 346 347 // Clear specified interrupts from pending. 348 void clear_interrupt_pending(InterruptFlag what) { 349 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); 350 } 351 352 // Getter and setter for the disable break state. 353 bool disable_break() { return disable_break_; } 354 void set_disable_break(bool disable_break) { 355 disable_break_ = disable_break; 356 } 357 358 // Getters for the current exception break state. 359 bool break_on_exception() { return break_on_exception_; } 360 bool break_on_uncaught_exception() { 361 return break_on_uncaught_exception_; 362 } 363 364 enum AddressId { 365 k_after_break_target_address, 366 k_debug_break_return_address, 367 k_debug_break_slot_address, 368 k_restarter_frame_function_pointer 369 }; 370 371 // Support for setting the address to jump to when returning from break point. 372 Address* after_break_target_address() { 373 return reinterpret_cast<Address*>(&thread_local_.after_break_target_); 374 } 375 Address* restarter_frame_function_pointer_address() { 376 Object*** address = &thread_local_.restarter_frame_function_pointer_; 377 return reinterpret_cast<Address*>(address); 378 } 379 380 // Support for saving/restoring registers when handling debug break calls. 381 Object** register_address(int r) { 382 return ®isters_[r]; 383 } 384 385 // Access to the debug break on return code. 386 Code* debug_break_return() { return debug_break_return_; } 387 Code** debug_break_return_address() { 388 return &debug_break_return_; 389 } 390 391 // Access to the debug break in debug break slot code. 392 Code* debug_break_slot() { return debug_break_slot_; } 393 Code** debug_break_slot_address() { 394 return &debug_break_slot_; 395 } 396 397 static const int kEstimatedNofDebugInfoEntries = 16; 398 static const int kEstimatedNofBreakPointsInFunction = 16; 399 400 // Passed to MakeWeak. 401 static void HandleWeakDebugInfo(v8::Isolate* isolate, 402 v8::Persistent<v8::Value>* obj, 403 void* data); 404 405 friend class Debugger; 406 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc 407 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc 408 409 // Threading support. 410 char* ArchiveDebug(char* to); 411 char* RestoreDebug(char* from); 412 static int ArchiveSpacePerThread(); 413 void FreeThreadResources() { } 414 415 // Mirror cache handling. 416 void ClearMirrorCache(); 417 418 // Script cache handling. 419 void CreateScriptCache(); 420 void DestroyScriptCache(); 421 void AddScriptToScriptCache(Handle<Script> script); 422 Handle<FixedArray> GetLoadedScripts(); 423 424 // Garbage collection notifications. 425 void AfterGarbageCollection(); 426 427 // Code generator routines. 428 static void GenerateSlot(MacroAssembler* masm); 429 static void GenerateLoadICDebugBreak(MacroAssembler* masm); 430 static void GenerateStoreICDebugBreak(MacroAssembler* masm); 431 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); 432 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); 433 static void GenerateCompareNilICDebugBreak(MacroAssembler* masm); 434 static void GenerateReturnDebugBreak(MacroAssembler* masm); 435 static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm); 436 static void GenerateCallFunctionStubRecordDebugBreak(MacroAssembler* masm); 437 static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm); 438 static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm); 439 static void GenerateSlotDebugBreak(MacroAssembler* masm); 440 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm); 441 442 // FrameDropper is a code replacement for a JavaScript frame with possibly 443 // several frames above. 444 // There is no calling conventions here, because it never actually gets 445 // called, it only gets returned to. 446 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); 447 448 // Called from stub-cache.cc. 449 static void GenerateCallICDebugBreak(MacroAssembler* masm); 450 451 // Describes how exactly a frame has been dropped from stack. 452 enum FrameDropMode { 453 // No frame has been dropped. 454 FRAMES_UNTOUCHED, 455 // The top JS frame had been calling IC stub. IC stub mustn't be called now. 456 FRAME_DROPPED_IN_IC_CALL, 457 // The top JS frame had been calling debug break slot stub. Patch the 458 // address this stub jumps to in the end. 459 FRAME_DROPPED_IN_DEBUG_SLOT_CALL, 460 // The top JS frame had been calling some C++ function. The return address 461 // gets patched automatically. 462 FRAME_DROPPED_IN_DIRECT_CALL, 463 FRAME_DROPPED_IN_RETURN_CALL, 464 CURRENTLY_SET_MODE 465 }; 466 467 void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 468 FrameDropMode mode, 469 Object** restarter_frame_function_pointer); 470 471 // Initializes an artificial stack frame. The data it contains is used for: 472 // a. successful work of frame dropper code which eventually gets control, 473 // b. being compatible with regular stack structure for various stack 474 // iterators. 475 // Returns address of stack allocated pointer to restarted function, 476 // the value that is called 'restarter_frame_function_pointer'. The value 477 // at this address (possibly updated by GC) may be used later when preparing 478 // 'step in' operation. 479 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, 480 Handle<Code> code); 481 482 static const int kFrameDropperFrameSize; 483 484 // Architecture-specific constant. 485 static const bool kFrameDropperSupported; 486 487 /** 488 * Defines layout of a stack frame that supports padding. This is a regular 489 * internal frame that has a flexible stack structure. LiveEdit can shift 490 * its lower part up the stack, taking up the 'padding' space when additional 491 * stack memory is required. 492 * Such frame is expected immediately above the topmost JavaScript frame. 493 * 494 * Stack Layout: 495 * --- Top 496 * LiveEdit routine frames 497 * --- 498 * C frames of debug handler 499 * --- 500 * ... 501 * --- 502 * An internal frame that has n padding words: 503 * - any number of words as needed by code -- upper part of frame 504 * - padding size: a Smi storing n -- current size of padding 505 * - padding: n words filled with kPaddingValue in form of Smi 506 * - 3 context/type words of a regular InternalFrame 507 * - fp 508 * --- 509 * Topmost JavaScript frame 510 * --- 511 * ... 512 * --- Bottom 513 */ 514 class FramePaddingLayout : public AllStatic { 515 public: 516 // Architecture-specific constant. 517 static const bool kIsSupported; 518 519 // A size of frame base including fp. Padding words starts right above 520 // the base. 521 static const int kFrameBaseSize = 4; 522 523 // A number of words that should be reserved on stack for the LiveEdit use. 524 // Normally equals 1. Stored on stack in form of Smi. 525 static const int kInitialSize; 526 // A value that padding words are filled with (in form of Smi). Going 527 // bottom-top, the first word not having this value is a counter word. 528 static const int kPaddingValue; 529 }; 530 531 private: 532 explicit Debug(Isolate* isolate); 533 ~Debug(); 534 535 static bool CompileDebuggerScript(int index); 536 void ClearOneShot(); 537 void ActivateStepIn(StackFrame* frame); 538 void ClearStepIn(); 539 void ActivateStepOut(StackFrame* frame); 540 void ClearStepNext(); 541 // Returns whether the compile succeeded. 542 void RemoveDebugInfo(Handle<DebugInfo> debug_info); 543 void SetAfterBreakTarget(JavaScriptFrame* frame); 544 Handle<Object> CheckBreakPoints(Handle<Object> break_point); 545 bool CheckBreakPoint(Handle<Object> break_point_object); 546 547 // Global handle to debug context where all the debugger JavaScript code is 548 // loaded. 549 Handle<Context> debug_context_; 550 551 // Boolean state indicating whether any break points are set. 552 bool has_break_points_; 553 554 // Cache of all scripts in the heap. 555 ScriptCache* script_cache_; 556 557 // List of active debug info objects. 558 DebugInfoListNode* debug_info_list_; 559 560 bool disable_break_; 561 bool break_on_exception_; 562 bool break_on_uncaught_exception_; 563 564 // Per-thread data. 565 class ThreadLocal { 566 public: 567 // Counter for generating next break id. 568 int break_count_; 569 570 // Current break id. 571 int break_id_; 572 573 // Frame id for the frame of the current break. 574 StackFrame::Id break_frame_id_; 575 576 // Step action for last step performed. 577 StepAction last_step_action_; 578 579 // Source statement position from last step next action. 580 int last_statement_position_; 581 582 // Number of steps left to perform before debug event. 583 int step_count_; 584 585 // Frame pointer from last step next action. 586 Address last_fp_; 587 588 // Number of queued steps left to perform before debug event. 589 int queued_step_count_; 590 591 // Frame pointer for frame from which step in was performed. 592 Address step_into_fp_; 593 594 // Frame pointer for the frame where debugger should be called when current 595 // step out action is completed. 596 Address step_out_fp_; 597 598 // Storage location for jump when exiting debug break calls. 599 Address after_break_target_; 600 601 // Stores the way how LiveEdit has patched the stack. It is used when 602 // debugger returns control back to user script. 603 FrameDropMode frame_drop_mode_; 604 605 // Top debugger entry. 606 EnterDebugger* debugger_entry_; 607 608 // Pending interrupts scheduled while debugging. 609 int pending_interrupts_; 610 611 // When restarter frame is on stack, stores the address 612 // of the pointer to function being restarted. Otherwise (most of the time) 613 // stores NULL. This pointer is used with 'step in' implementation. 614 Object** restarter_frame_function_pointer_; 615 }; 616 617 // Storage location for registers when handling debug break calls 618 JSCallerSavedBuffer registers_; 619 ThreadLocal thread_local_; 620 void ThreadInit(); 621 622 // Code to call for handling debug break on return. 623 Code* debug_break_return_; 624 625 // Code to call for handling debug break in debug break slots. 626 Code* debug_break_slot_; 627 628 Isolate* isolate_; 629 630 friend class Isolate; 631 632 DISALLOW_COPY_AND_ASSIGN(Debug); 633 }; 634 635 636 DECLARE_RUNTIME_FUNCTION(Object*, Debug_Break); 637 638 639 // Message delivered to the message handler callback. This is either a debugger 640 // event or the response to a command. 641 class MessageImpl: public v8::Debug::Message { 642 public: 643 // Create a message object for a debug event. 644 static MessageImpl NewEvent(DebugEvent event, 645 bool running, 646 Handle<JSObject> exec_state, 647 Handle<JSObject> event_data); 648 649 // Create a message object for the response to a debug command. 650 static MessageImpl NewResponse(DebugEvent event, 651 bool running, 652 Handle<JSObject> exec_state, 653 Handle<JSObject> event_data, 654 Handle<String> response_json, 655 v8::Debug::ClientData* client_data); 656 657 // Implementation of interface v8::Debug::Message. 658 virtual bool IsEvent() const; 659 virtual bool IsResponse() const; 660 virtual DebugEvent GetEvent() const; 661 virtual bool WillStartRunning() const; 662 virtual v8::Handle<v8::Object> GetExecutionState() const; 663 virtual v8::Handle<v8::Object> GetEventData() const; 664 virtual v8::Handle<v8::String> GetJSON() const; 665 virtual v8::Handle<v8::Context> GetEventContext() const; 666 virtual v8::Debug::ClientData* GetClientData() const; 667 668 private: 669 MessageImpl(bool is_event, 670 DebugEvent event, 671 bool running, 672 Handle<JSObject> exec_state, 673 Handle<JSObject> event_data, 674 Handle<String> response_json, 675 v8::Debug::ClientData* client_data); 676 677 bool is_event_; // Does this message represent a debug event? 678 DebugEvent event_; // Debug event causing the break. 679 bool running_; // Will the VM start running after this event? 680 Handle<JSObject> exec_state_; // Current execution state. 681 Handle<JSObject> event_data_; // Data associated with the event. 682 Handle<String> response_json_; // Response JSON if message holds a response. 683 v8::Debug::ClientData* client_data_; // Client data passed with the request. 684 }; 685 686 687 // Details of the debug event delivered to the debug event listener. 688 class EventDetailsImpl : public v8::Debug::EventDetails { 689 public: 690 EventDetailsImpl(DebugEvent event, 691 Handle<JSObject> exec_state, 692 Handle<JSObject> event_data, 693 Handle<Object> callback_data, 694 v8::Debug::ClientData* client_data); 695 virtual DebugEvent GetEvent() const; 696 virtual v8::Handle<v8::Object> GetExecutionState() const; 697 virtual v8::Handle<v8::Object> GetEventData() const; 698 virtual v8::Handle<v8::Context> GetEventContext() const; 699 virtual v8::Handle<v8::Value> GetCallbackData() const; 700 virtual v8::Debug::ClientData* GetClientData() const; 701 private: 702 DebugEvent event_; // Debug event causing the break. 703 Handle<JSObject> exec_state_; // Current execution state. 704 Handle<JSObject> event_data_; // Data associated with the event. 705 Handle<Object> callback_data_; // User data passed with the callback 706 // when it was registered. 707 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. 708 }; 709 710 711 // Message send by user to v8 debugger or debugger output message. 712 // In addition to command text it may contain a pointer to some user data 713 // which are expected to be passed along with the command reponse to message 714 // handler. 715 class CommandMessage { 716 public: 717 static CommandMessage New(const Vector<uint16_t>& command, 718 v8::Debug::ClientData* data); 719 CommandMessage(); 720 ~CommandMessage(); 721 722 // Deletes user data and disposes of the text. 723 void Dispose(); 724 Vector<uint16_t> text() const { return text_; } 725 v8::Debug::ClientData* client_data() const { return client_data_; } 726 private: 727 CommandMessage(const Vector<uint16_t>& text, 728 v8::Debug::ClientData* data); 729 730 Vector<uint16_t> text_; 731 v8::Debug::ClientData* client_data_; 732 }; 733 734 // A Queue of CommandMessage objects. A thread-safe version is 735 // LockingCommandMessageQueue, based on this class. 736 class CommandMessageQueue BASE_EMBEDDED { 737 public: 738 explicit CommandMessageQueue(int size); 739 ~CommandMessageQueue(); 740 bool IsEmpty() const { return start_ == end_; } 741 CommandMessage Get(); 742 void Put(const CommandMessage& message); 743 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). 744 private: 745 // Doubles the size of the message queue, and copies the messages. 746 void Expand(); 747 748 CommandMessage* messages_; 749 int start_; 750 int end_; 751 int size_; // The size of the queue buffer. Queue can hold size-1 messages. 752 }; 753 754 755 class MessageDispatchHelperThread; 756 757 758 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage 759 // messages. The message data is not managed by LockingCommandMessageQueue. 760 // Pointers to the data are passed in and out. Implemented by adding a 761 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. 762 class LockingCommandMessageQueue BASE_EMBEDDED { 763 public: 764 LockingCommandMessageQueue(Logger* logger, int size); 765 ~LockingCommandMessageQueue(); 766 bool IsEmpty() const; 767 CommandMessage Get(); 768 void Put(const CommandMessage& message); 769 void Clear(); 770 private: 771 Logger* logger_; 772 CommandMessageQueue queue_; 773 Mutex* lock_; 774 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); 775 }; 776 777 778 class Debugger { 779 public: 780 ~Debugger(); 781 782 void DebugRequest(const uint16_t* json_request, int length); 783 784 Handle<Object> MakeJSObject(Vector<const char> constructor_name, 785 int argc, 786 Handle<Object> argv[], 787 bool* caught_exception); 788 Handle<Object> MakeExecutionState(bool* caught_exception); 789 Handle<Object> MakeBreakEvent(Handle<Object> exec_state, 790 Handle<Object> break_points_hit, 791 bool* caught_exception); 792 Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, 793 Handle<Object> exception, 794 bool uncaught, 795 bool* caught_exception); 796 Handle<Object> MakeNewFunctionEvent(Handle<Object> func, 797 bool* caught_exception); 798 Handle<Object> MakeCompileEvent(Handle<Script> script, 799 bool before, 800 bool* caught_exception); 801 Handle<Object> MakeScriptCollectedEvent(int id, 802 bool* caught_exception); 803 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 804 void OnException(Handle<Object> exception, bool uncaught); 805 void OnBeforeCompile(Handle<Script> script); 806 807 enum AfterCompileFlags { 808 NO_AFTER_COMPILE_FLAGS, 809 SEND_WHEN_DEBUGGING 810 }; 811 void OnAfterCompile(Handle<Script> script, 812 AfterCompileFlags after_compile_flags); 813 void OnScriptCollected(int id); 814 void ProcessDebugEvent(v8::DebugEvent event, 815 Handle<JSObject> event_data, 816 bool auto_continue); 817 void NotifyMessageHandler(v8::DebugEvent event, 818 Handle<JSObject> exec_state, 819 Handle<JSObject> event_data, 820 bool auto_continue); 821 void SetEventListener(Handle<Object> callback, Handle<Object> data); 822 void SetMessageHandler(v8::Debug::MessageHandler2 handler); 823 void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, 824 int period); 825 void SetDebugMessageDispatchHandler( 826 v8::Debug::DebugMessageDispatchHandler handler, 827 bool provide_locker); 828 829 // Invoke the message handler function. 830 void InvokeMessageHandler(MessageImpl message); 831 832 // Add a debugger command to the command queue. 833 void ProcessCommand(Vector<const uint16_t> command, 834 v8::Debug::ClientData* client_data = NULL); 835 836 // Check whether there are commands in the command queue. 837 bool HasCommands(); 838 839 // Enqueue a debugger command to the command queue for event listeners. 840 void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL); 841 842 Handle<Object> Call(Handle<JSFunction> fun, 843 Handle<Object> data, 844 bool* pending_exception); 845 846 // Start the debugger agent listening on the provided port. 847 bool StartAgent(const char* name, int port, 848 bool wait_for_connection = false); 849 850 // Stop the debugger agent. 851 void StopAgent(); 852 853 // Blocks until the agent has started listening for connections 854 void WaitForAgent(); 855 856 void CallMessageDispatchHandler(); 857 858 Handle<Context> GetDebugContext(); 859 860 // Unload the debugger if possible. Only called when no debugger is currently 861 // active. 862 void UnloadDebugger(); 863 friend void ForceUnloadDebugger(); // In test-debug.cc 864 865 inline bool EventActive(v8::DebugEvent event) { 866 ScopedLock with(debugger_access_); 867 868 // Check whether the message handler was been cleared. 869 if (debugger_unload_pending_) { 870 if (isolate_->debug()->debugger_entry() == NULL) { 871 UnloadDebugger(); 872 } 873 } 874 875 if (((event == v8::BeforeCompile) || (event == v8::AfterCompile)) && 876 !FLAG_debug_compile_events) { 877 return false; 878 879 } else if ((event == v8::ScriptCollected) && 880 !FLAG_debug_script_collected_events) { 881 return false; 882 } 883 884 // Currently argument event is not used. 885 return !compiling_natives_ && Debugger::IsDebuggerActive(); 886 } 887 888 void set_compiling_natives(bool compiling_natives) { 889 compiling_natives_ = compiling_natives; 890 } 891 bool compiling_natives() const { return compiling_natives_; } 892 void set_loading_debugger(bool v) { is_loading_debugger_ = v; } 893 bool is_loading_debugger() const { return is_loading_debugger_; } 894 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } 895 bool live_edit_enabled() const { 896 return FLAG_enable_liveedit && live_edit_enabled_ ; 897 } 898 void set_force_debugger_active(bool force_debugger_active) { 899 force_debugger_active_ = force_debugger_active; 900 } 901 bool force_debugger_active() const { return force_debugger_active_; } 902 903 bool IsDebuggerActive(); 904 905 private: 906 explicit Debugger(Isolate* isolate); 907 908 void CallEventCallback(v8::DebugEvent event, 909 Handle<Object> exec_state, 910 Handle<Object> event_data, 911 v8::Debug::ClientData* client_data); 912 void CallCEventCallback(v8::DebugEvent event, 913 Handle<Object> exec_state, 914 Handle<Object> event_data, 915 v8::Debug::ClientData* client_data); 916 void CallJSEventCallback(v8::DebugEvent event, 917 Handle<Object> exec_state, 918 Handle<Object> event_data); 919 void ListenersChanged(); 920 921 Mutex* debugger_access_; // Mutex guarding debugger variables. 922 Handle<Object> event_listener_; // Global handle to listener. 923 Handle<Object> event_listener_data_; 924 bool compiling_natives_; // Are we compiling natives? 925 bool is_loading_debugger_; // Are we loading the debugger? 926 bool live_edit_enabled_; // Enable LiveEdit. 927 bool never_unload_debugger_; // Can we unload the debugger? 928 bool force_debugger_active_; // Activate debugger without event listeners. 929 v8::Debug::MessageHandler2 message_handler_; 930 bool debugger_unload_pending_; // Was message handler cleared? 931 v8::Debug::HostDispatchHandler host_dispatch_handler_; 932 Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. 933 v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; 934 MessageDispatchHelperThread* message_dispatch_helper_thread_; 935 int host_dispatch_micros_; 936 937 DebuggerAgent* agent_; 938 939 static const int kQueueInitialSize = 4; 940 LockingCommandMessageQueue command_queue_; 941 Semaphore* command_received_; // Signaled for each command received. 942 LockingCommandMessageQueue event_command_queue_; 943 944 Isolate* isolate_; 945 946 friend class EnterDebugger; 947 friend class Isolate; 948 949 DISALLOW_COPY_AND_ASSIGN(Debugger); 950 }; 951 952 953 // This class is used for entering the debugger. Create an instance in the stack 954 // to enter the debugger. This will set the current break state, make sure the 955 // debugger is loaded and switch to the debugger context. If the debugger for 956 // some reason could not be entered FailedToEnter will return true. 957 class EnterDebugger BASE_EMBEDDED { 958 public: 959 EnterDebugger(); 960 ~EnterDebugger(); 961 962 // Check whether the debugger could be entered. 963 inline bool FailedToEnter() { return load_failed_; } 964 965 // Check whether there are any JavaScript frames on the stack. 966 inline bool HasJavaScriptFrames() { return has_js_frames_; } 967 968 // Get the active context from before entering the debugger. 969 inline Handle<Context> GetContext() { return save_.context(); } 970 971 private: 972 Isolate* isolate_; 973 EnterDebugger* prev_; // Previous debugger entry if entered recursively. 974 JavaScriptFrameIterator it_; 975 const bool has_js_frames_; // Were there any JavaScript frames? 976 StackFrame::Id break_frame_id_; // Previous break frame id. 977 int break_id_; // Previous break id. 978 bool load_failed_; // Did the debugger fail to load? 979 SaveContext save_; // Saves previous context. 980 }; 981 982 983 // Stack allocated class for disabling break. 984 class DisableBreak BASE_EMBEDDED { 985 public: 986 explicit DisableBreak(bool disable_break) : isolate_(Isolate::Current()) { 987 prev_disable_break_ = isolate_->debug()->disable_break(); 988 isolate_->debug()->set_disable_break(disable_break); 989 } 990 ~DisableBreak() { 991 ASSERT(Isolate::Current() == isolate_); 992 isolate_->debug()->set_disable_break(prev_disable_break_); 993 } 994 995 private: 996 Isolate* isolate_; 997 // The previous state of the disable break used to restore the value when this 998 // object is destructed. 999 bool prev_disable_break_; 1000 }; 1001 1002 1003 // Debug_Address encapsulates the Address pointers used in generating debug 1004 // code. 1005 class Debug_Address { 1006 public: 1007 explicit Debug_Address(Debug::AddressId id) : id_(id) { } 1008 1009 static Debug_Address AfterBreakTarget() { 1010 return Debug_Address(Debug::k_after_break_target_address); 1011 } 1012 1013 static Debug_Address DebugBreakReturn() { 1014 return Debug_Address(Debug::k_debug_break_return_address); 1015 } 1016 1017 static Debug_Address RestarterFrameFunctionPointer() { 1018 return Debug_Address(Debug::k_restarter_frame_function_pointer); 1019 } 1020 1021 Address address(Isolate* isolate) const { 1022 Debug* debug = isolate->debug(); 1023 switch (id_) { 1024 case Debug::k_after_break_target_address: 1025 return reinterpret_cast<Address>(debug->after_break_target_address()); 1026 case Debug::k_debug_break_return_address: 1027 return reinterpret_cast<Address>(debug->debug_break_return_address()); 1028 case Debug::k_debug_break_slot_address: 1029 return reinterpret_cast<Address>(debug->debug_break_slot_address()); 1030 case Debug::k_restarter_frame_function_pointer: 1031 return reinterpret_cast<Address>( 1032 debug->restarter_frame_function_pointer_address()); 1033 default: 1034 UNREACHABLE(); 1035 return NULL; 1036 } 1037 } 1038 1039 private: 1040 Debug::AddressId id_; 1041 }; 1042 1043 // The optional thread that Debug Agent may use to temporary call V8 to process 1044 // pending debug requests if debuggee is not running V8 at the moment. 1045 // Techincally it does not call V8 itself, rather it asks embedding program 1046 // to do this via v8::Debug::HostDispatchHandler 1047 class MessageDispatchHelperThread: public Thread { 1048 public: 1049 explicit MessageDispatchHelperThread(Isolate* isolate); 1050 ~MessageDispatchHelperThread(); 1051 1052 void Schedule(); 1053 1054 private: 1055 void Run(); 1056 1057 Isolate* isolate_; 1058 Semaphore* const sem_; 1059 Mutex* const mutex_; 1060 bool already_signalled_; 1061 1062 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); 1063 }; 1064 1065 1066 } } // namespace v8::internal 1067 1068 #endif // ENABLE_DEBUGGER_SUPPORT 1069 1070 #endif // V8_DEBUG_H_ 1071