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