1 // Copyright 2006-2008 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 "assembler.h" 32 #include "code-stubs.h" 33 #include "debug-agent.h" 34 #include "execution.h" 35 #include "factory.h" 36 #include "hashmap.h" 37 #include "platform.h" 38 #include "string-stream.h" 39 #include "v8threads.h" 40 41 #ifdef ENABLE_DEBUGGER_SUPPORT 42 #include "../include/v8-debug.h" 43 44 namespace v8 { 45 namespace internal { 46 47 48 // Forward declarations. 49 class EnterDebugger; 50 51 52 // Step actions. NOTE: These values are in macros.py as well. 53 enum StepAction { 54 StepNone = -1, // Stepping not prepared. 55 StepOut = 0, // Step out of the current function. 56 StepNext = 1, // Step to the next statement in the current function. 57 StepIn = 2, // Step into new functions invoked or the next statement 58 // in the current function. 59 StepMin = 3, // Perform a minimum step in the current function. 60 StepInMin = 4 // Step into new functions invoked or perform a minimum step 61 // in the current function. 62 }; 63 64 65 // Type of exception break. NOTE: These values are in macros.py as well. 66 enum ExceptionBreakType { 67 BreakException = 0, 68 BreakUncaughtException = 1 69 }; 70 71 72 // Type of exception break. NOTE: These values are in macros.py as well. 73 enum BreakLocatorType { 74 ALL_BREAK_LOCATIONS = 0, 75 SOURCE_BREAK_LOCATIONS = 1 76 }; 77 78 79 // Class for iterating through the break points in a function and changing 80 // them. 81 class BreakLocationIterator { 82 public: 83 explicit BreakLocationIterator(Handle<DebugInfo> debug_info, 84 BreakLocatorType type); 85 virtual ~BreakLocationIterator(); 86 87 void Next(); 88 void Next(int count); 89 void FindBreakLocationFromAddress(Address pc); 90 void FindBreakLocationFromPosition(int position); 91 void Reset(); 92 bool Done() const; 93 void SetBreakPoint(Handle<Object> break_point_object); 94 void ClearBreakPoint(Handle<Object> break_point_object); 95 void SetOneShot(); 96 void ClearOneShot(); 97 void PrepareStepIn(); 98 bool IsExit() const; 99 bool HasBreakPoint(); 100 bool IsDebugBreak(); 101 Object* BreakPointObjects(); 102 void ClearAllDebugBreak(); 103 104 code_position()105 inline int code_position() { return pc() - debug_info_->code()->entry(); } break_point()106 inline int break_point() { return break_point_; } position()107 inline int position() { return position_; } statement_position()108 inline int statement_position() { return statement_position_; } pc()109 inline Address pc() { return reloc_iterator_->rinfo()->pc(); } code()110 inline Code* code() { return debug_info_->code(); } rinfo()111 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); } rmode()112 inline RelocInfo::Mode rmode() const { 113 return reloc_iterator_->rinfo()->rmode(); 114 } original_rinfo()115 inline RelocInfo* original_rinfo() { 116 return reloc_iterator_original_->rinfo(); 117 } original_rmode()118 inline RelocInfo::Mode original_rmode() const { 119 return reloc_iterator_original_->rinfo()->rmode(); 120 } 121 122 bool IsDebuggerStatement(); 123 124 protected: 125 bool RinfoDone() const; 126 void RinfoNext(); 127 128 BreakLocatorType type_; 129 int break_point_; 130 int position_; 131 int statement_position_; 132 Handle<DebugInfo> debug_info_; 133 Handle<Code> debug_break_stub_; 134 RelocIterator* reloc_iterator_; 135 RelocIterator* reloc_iterator_original_; 136 137 private: 138 void SetDebugBreak(); 139 void ClearDebugBreak(); 140 141 void SetDebugBreakAtIC(); 142 void ClearDebugBreakAtIC(); 143 144 bool IsDebugBreakAtReturn(); 145 void SetDebugBreakAtReturn(); 146 void ClearDebugBreakAtReturn(); 147 148 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator); 149 }; 150 151 152 // Cache of all script objects in the heap. When a script is added a weak handle 153 // to it is created and that weak handle is stored in the cache. The weak handle 154 // callback takes care of removing the script from the cache. The key used in 155 // the cache is the script id. 156 class ScriptCache : private HashMap { 157 public: ScriptCache()158 ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {} ~ScriptCache()159 virtual ~ScriptCache() { Clear(); } 160 161 // Add script to the cache. 162 void Add(Handle<Script> script); 163 164 // Return the scripts in the cache. 165 Handle<FixedArray> GetScripts(); 166 167 // Generate debugger events for collected scripts. 168 void ProcessCollectedScripts(); 169 170 private: 171 // Calculate the hash value from the key (script id). Hash(int key)172 static uint32_t Hash(int key) { return ComputeIntegerHash(key); } 173 174 // Scripts match if their keys (script id) match. ScriptMatch(void * key1,void * key2)175 static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; } 176 177 // Clear the cache releasing all the weak handles. 178 void Clear(); 179 180 // Weak handle callback for scripts in the cache. 181 static void HandleWeakScript(v8::Persistent<v8::Value> obj, void* data); 182 183 // List used during GC to temporarily store id's of collected scripts. 184 List<int> collected_scripts_; 185 }; 186 187 188 // Linked list holding debug info objects. The debug info objects are kept as 189 // weak handles to avoid a debug info object to keep a function alive. 190 class DebugInfoListNode { 191 public: 192 explicit DebugInfoListNode(DebugInfo* debug_info); 193 virtual ~DebugInfoListNode(); 194 next()195 DebugInfoListNode* next() { return next_; } set_next(DebugInfoListNode * next)196 void set_next(DebugInfoListNode* next) { next_ = next; } debug_info()197 Handle<DebugInfo> debug_info() { return debug_info_; } 198 199 private: 200 // Global (weak) handle to the debug info object. 201 Handle<DebugInfo> debug_info_; 202 203 // Next pointer for linked list. 204 DebugInfoListNode* next_; 205 }; 206 207 208 // This class contains the debugger support. The main purpose is to handle 209 // setting break points in the code. 210 // 211 // This class controls the debug info for all functions which currently have 212 // active breakpoints in them. This debug info is held in the heap root object 213 // debug_info which is a FixedArray. Each entry in this list is of class 214 // DebugInfo. 215 class Debug { 216 public: 217 static void Setup(bool create_heap_objects); 218 static bool Load(); 219 static void Unload(); IsLoaded()220 static bool IsLoaded() { return !debug_context_.is_null(); } InDebugger()221 static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; } 222 static void PreemptionWhileInDebugger(); 223 static void Iterate(ObjectVisitor* v); 224 225 static Object* Break(Arguments args); 226 static void SetBreakPoint(Handle<SharedFunctionInfo> shared, 227 int source_position, 228 Handle<Object> break_point_object); 229 static void ClearBreakPoint(Handle<Object> break_point_object); 230 static void ClearAllBreakPoints(); 231 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); 232 static void FloodHandlerWithOneShot(); 233 static void ChangeBreakOnException(ExceptionBreakType type, bool enable); 234 static void PrepareStep(StepAction step_action, int step_count); 235 static void ClearStepping(); 236 static bool StepNextContinue(BreakLocationIterator* break_location_iterator, 237 JavaScriptFrame* frame); 238 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); 239 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared); 240 241 // Returns whether the operation succeeded. 242 static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared); 243 244 // Returns true if the current stub call is patched to call the debugger. 245 static bool IsDebugBreak(Address addr); 246 // Returns true if the current return statement has been patched to be 247 // a debugger breakpoint. 248 static bool IsDebugBreakAtReturn(RelocInfo* rinfo); 249 250 // Check whether a code stub with the specified major key is a possible break 251 // point location. 252 static bool IsSourceBreakStub(Code* code); 253 static bool IsBreakStub(Code* code); 254 255 // Find the builtin to use for invoking the debug break 256 static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode); 257 258 static Handle<Object> GetSourceBreakLocations( 259 Handle<SharedFunctionInfo> shared); 260 261 // Getter for the debug_context. debug_context()262 inline static Handle<Context> debug_context() { return debug_context_; } 263 264 // Check whether a global object is the debug global object. 265 static bool IsDebugGlobal(GlobalObject* global); 266 267 // Fast check to see if any break points are active. has_break_points()268 inline static bool has_break_points() { return has_break_points_; } 269 270 static void NewBreak(StackFrame::Id break_frame_id); 271 static void SetBreak(StackFrame::Id break_frame_id, int break_id); break_frame_id()272 static StackFrame::Id break_frame_id() { 273 return thread_local_.break_frame_id_; 274 } break_id()275 static int break_id() { return thread_local_.break_id_; } 276 StepInActive()277 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } 278 static void HandleStepIn(Handle<JSFunction> function, 279 Handle<Object> holder, 280 Address fp, 281 bool is_constructor); step_in_fp()282 static Address step_in_fp() { return thread_local_.step_into_fp_; } step_in_fp_addr()283 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } 284 debugger_entry()285 static EnterDebugger* debugger_entry() { 286 return thread_local_.debugger_entry_; 287 } set_debugger_entry(EnterDebugger * entry)288 static void set_debugger_entry(EnterDebugger* entry) { 289 thread_local_.debugger_entry_ = entry; 290 } 291 292 // Check whether any of the specified interrupts are pending. is_interrupt_pending(InterruptFlag what)293 static bool is_interrupt_pending(InterruptFlag what) { 294 return (thread_local_.pending_interrupts_ & what) != 0; 295 } 296 297 // Set specified interrupts as pending. set_interrupts_pending(InterruptFlag what)298 static void set_interrupts_pending(InterruptFlag what) { 299 thread_local_.pending_interrupts_ |= what; 300 } 301 302 // Clear specified interrupts from pending. clear_interrupt_pending(InterruptFlag what)303 static void clear_interrupt_pending(InterruptFlag what) { 304 thread_local_.pending_interrupts_ &= ~static_cast<int>(what); 305 } 306 307 // Getter and setter for the disable break state. disable_break()308 static bool disable_break() { return disable_break_; } set_disable_break(bool disable_break)309 static void set_disable_break(bool disable_break) { 310 disable_break_ = disable_break; 311 } 312 313 // Getters for the current exception break state. break_on_exception()314 static bool break_on_exception() { return break_on_exception_; } break_on_uncaught_exception()315 static bool break_on_uncaught_exception() { 316 return break_on_uncaught_exception_; 317 } 318 319 enum AddressId { 320 k_after_break_target_address, 321 k_debug_break_return_address, 322 k_register_address 323 }; 324 325 // Support for setting the address to jump to when returning from break point. after_break_target_address()326 static Address* after_break_target_address() { 327 return reinterpret_cast<Address*>(&thread_local_.after_break_target_); 328 } 329 330 // Support for saving/restoring registers when handling debug break calls. register_address(int r)331 static Object** register_address(int r) { 332 return ®isters_[r]; 333 } 334 335 // Address of the debug break return entry code. debug_break_return_entry()336 static Code* debug_break_return_entry() { return debug_break_return_entry_; } 337 338 // Support for getting the address of the debug break on return code. debug_break_return_address()339 static Code** debug_break_return_address() { 340 return &debug_break_return_; 341 } 342 343 static const int kEstimatedNofDebugInfoEntries = 16; 344 static const int kEstimatedNofBreakPointsInFunction = 16; 345 346 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data); 347 348 friend class Debugger; 349 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc 350 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc 351 352 // Threading support. 353 static char* ArchiveDebug(char* to); 354 static char* RestoreDebug(char* from); 355 static int ArchiveSpacePerThread(); 356 357 // Mirror cache handling. 358 static void ClearMirrorCache(); 359 360 // Script cache handling. 361 static void CreateScriptCache(); 362 static void DestroyScriptCache(); 363 static void AddScriptToScriptCache(Handle<Script> script); 364 static Handle<FixedArray> GetLoadedScripts(); 365 366 // Garbage collection notifications. 367 static void AfterGarbageCollection(); 368 369 // Code generation assumptions. 370 static const int kIa32CallInstructionLength = 5; 371 static const int kIa32JSReturnSequenceLength = 6; 372 373 // The x64 JS return sequence is padded with int3 to make it large 374 // enough to hold a call instruction when the debugger patches it. 375 static const int kX64CallInstructionLength = 13; 376 static const int kX64JSReturnSequenceLength = 13; 377 378 // Code generator routines. 379 static void GenerateLoadICDebugBreak(MacroAssembler* masm); 380 static void GenerateStoreICDebugBreak(MacroAssembler* masm); 381 static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm); 382 static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm); 383 static void GenerateConstructCallDebugBreak(MacroAssembler* masm); 384 static void GenerateReturnDebugBreak(MacroAssembler* masm); 385 static void GenerateReturnDebugBreakEntry(MacroAssembler* masm); 386 static void GenerateStubNoRegistersDebugBreak(MacroAssembler* masm); 387 388 // Called from stub-cache.cc. 389 static void GenerateCallICDebugBreak(MacroAssembler* masm); 390 391 private: 392 static bool CompileDebuggerScript(int index); 393 static void ClearOneShot(); 394 static void ActivateStepIn(StackFrame* frame); 395 static void ClearStepIn(); 396 static void ClearStepNext(); 397 // Returns whether the compile succeeded. 398 static bool EnsureCompiled(Handle<SharedFunctionInfo> shared); 399 static void RemoveDebugInfo(Handle<DebugInfo> debug_info); 400 static void SetAfterBreakTarget(JavaScriptFrame* frame); 401 static Handle<Object> CheckBreakPoints(Handle<Object> break_point); 402 static bool CheckBreakPoint(Handle<Object> break_point_object); 403 404 // Global handle to debug context where all the debugger JavaScript code is 405 // loaded. 406 static Handle<Context> debug_context_; 407 408 // Boolean state indicating whether any break points are set. 409 static bool has_break_points_; 410 411 // Cache of all scripts in the heap. 412 static ScriptCache* script_cache_; 413 414 // List of active debug info objects. 415 static DebugInfoListNode* debug_info_list_; 416 417 static bool disable_break_; 418 static bool break_on_exception_; 419 static bool break_on_uncaught_exception_; 420 421 // Per-thread data. 422 class ThreadLocal { 423 public: 424 // Counter for generating next break id. 425 int break_count_; 426 427 // Current break id. 428 int break_id_; 429 430 // Frame id for the frame of the current break. 431 StackFrame::Id break_frame_id_; 432 433 // Step action for last step performed. 434 StepAction last_step_action_; 435 436 // Source statement position from last step next action. 437 int last_statement_position_; 438 439 // Number of steps left to perform before debug event. 440 int step_count_; 441 442 // Frame pointer from last step next action. 443 Address last_fp_; 444 445 // Frame pointer for frame from which step in was performed. 446 Address step_into_fp_; 447 448 // Storage location for jump when exiting debug break calls. 449 Address after_break_target_; 450 451 // Top debugger entry. 452 EnterDebugger* debugger_entry_; 453 454 // Pending interrupts scheduled while debugging. 455 int pending_interrupts_; 456 }; 457 458 // Storage location for registers when handling debug break calls 459 static JSCallerSavedBuffer registers_; 460 static ThreadLocal thread_local_; 461 static void ThreadInit(); 462 463 // Code object for debug break return entry code. 464 static Code* debug_break_return_entry_; 465 466 // Code to call for handling debug break on return. 467 static Code* debug_break_return_; 468 469 DISALLOW_COPY_AND_ASSIGN(Debug); 470 }; 471 472 473 // Message delivered to the message handler callback. This is either a debugger 474 // event or the response to a command. 475 class MessageImpl: public v8::Debug::Message { 476 public: 477 // Create a message object for a debug event. 478 static MessageImpl NewEvent(DebugEvent event, 479 bool running, 480 Handle<JSObject> exec_state, 481 Handle<JSObject> event_data); 482 483 // Create a message object for the response to a debug command. 484 static MessageImpl NewResponse(DebugEvent event, 485 bool running, 486 Handle<JSObject> exec_state, 487 Handle<JSObject> event_data, 488 Handle<String> response_json, 489 v8::Debug::ClientData* client_data); 490 491 // Implementation of interface v8::Debug::Message. 492 virtual bool IsEvent() const; 493 virtual bool IsResponse() const; 494 virtual DebugEvent GetEvent() const; 495 virtual bool WillStartRunning() const; 496 virtual v8::Handle<v8::Object> GetExecutionState() const; 497 virtual v8::Handle<v8::Object> GetEventData() const; 498 virtual v8::Handle<v8::String> GetJSON() const; 499 virtual v8::Handle<v8::Context> GetEventContext() const; 500 virtual v8::Debug::ClientData* GetClientData() const; 501 502 private: 503 MessageImpl(bool is_event, 504 DebugEvent event, 505 bool running, 506 Handle<JSObject> exec_state, 507 Handle<JSObject> event_data, 508 Handle<String> response_json, 509 v8::Debug::ClientData* client_data); 510 511 bool is_event_; // Does this message represent a debug event? 512 DebugEvent event_; // Debug event causing the break. 513 bool running_; // Will the VM start running after this event? 514 Handle<JSObject> exec_state_; // Current execution state. 515 Handle<JSObject> event_data_; // Data associated with the event. 516 Handle<String> response_json_; // Response JSON if message holds a response. 517 v8::Debug::ClientData* client_data_; // Client data passed with the request. 518 }; 519 520 521 // Message send by user to v8 debugger or debugger output message. 522 // In addition to command text it may contain a pointer to some user data 523 // which are expected to be passed along with the command reponse to message 524 // handler. 525 class CommandMessage { 526 public: 527 static CommandMessage New(const Vector<uint16_t>& command, 528 v8::Debug::ClientData* data); 529 CommandMessage(); 530 ~CommandMessage(); 531 532 // Deletes user data and disposes of the text. 533 void Dispose(); text()534 Vector<uint16_t> text() const { return text_; } client_data()535 v8::Debug::ClientData* client_data() const { return client_data_; } 536 private: 537 CommandMessage(const Vector<uint16_t>& text, 538 v8::Debug::ClientData* data); 539 540 Vector<uint16_t> text_; 541 v8::Debug::ClientData* client_data_; 542 }; 543 544 // A Queue of CommandMessage objects. A thread-safe version is 545 // LockingCommandMessageQueue, based on this class. 546 class CommandMessageQueue BASE_EMBEDDED { 547 public: 548 explicit CommandMessageQueue(int size); 549 ~CommandMessageQueue(); IsEmpty()550 bool IsEmpty() const { return start_ == end_; } 551 CommandMessage Get(); 552 void Put(const CommandMessage& message); Clear()553 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). 554 private: 555 // Doubles the size of the message queue, and copies the messages. 556 void Expand(); 557 558 CommandMessage* messages_; 559 int start_; 560 int end_; 561 int size_; // The size of the queue buffer. Queue can hold size-1 messages. 562 }; 563 564 565 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage 566 // messages. The message data is not managed by LockingCommandMessageQueue. 567 // Pointers to the data are passed in and out. Implemented by adding a 568 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. 569 class LockingCommandMessageQueue BASE_EMBEDDED { 570 public: 571 explicit LockingCommandMessageQueue(int size); 572 ~LockingCommandMessageQueue(); 573 bool IsEmpty() const; 574 CommandMessage Get(); 575 void Put(const CommandMessage& message); 576 void Clear(); 577 private: 578 CommandMessageQueue queue_; 579 Mutex* lock_; 580 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); 581 }; 582 583 584 class Debugger { 585 public: 586 static void DebugRequest(const uint16_t* json_request, int length); 587 588 static Handle<Object> MakeJSObject(Vector<const char> constructor_name, 589 int argc, Object*** argv, 590 bool* caught_exception); 591 static Handle<Object> MakeExecutionState(bool* caught_exception); 592 static Handle<Object> MakeBreakEvent(Handle<Object> exec_state, 593 Handle<Object> break_points_hit, 594 bool* caught_exception); 595 static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, 596 Handle<Object> exception, 597 bool uncaught, 598 bool* caught_exception); 599 static Handle<Object> MakeNewFunctionEvent(Handle<Object> func, 600 bool* caught_exception); 601 static Handle<Object> MakeCompileEvent(Handle<Script> script, 602 bool before, 603 bool* caught_exception); 604 static Handle<Object> MakeScriptCollectedEvent(int id, 605 bool* caught_exception); 606 static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 607 static void OnException(Handle<Object> exception, bool uncaught); 608 static void OnBeforeCompile(Handle<Script> script); 609 static void OnAfterCompile(Handle<Script> script, 610 Handle<JSFunction> fun); 611 static void OnNewFunction(Handle<JSFunction> fun); 612 static void OnScriptCollected(int id); 613 static void ProcessDebugEvent(v8::DebugEvent event, 614 Handle<JSObject> event_data, 615 bool auto_continue); 616 static void NotifyMessageHandler(v8::DebugEvent event, 617 Handle<JSObject> exec_state, 618 Handle<JSObject> event_data, 619 bool auto_continue); 620 static void SetEventListener(Handle<Object> callback, Handle<Object> data); 621 static void SetMessageHandler(v8::Debug::MessageHandler2 handler); 622 static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, 623 int period); 624 625 // Invoke the message handler function. 626 static void InvokeMessageHandler(MessageImpl message); 627 628 // Add a debugger command to the command queue. 629 static void ProcessCommand(Vector<const uint16_t> command, 630 v8::Debug::ClientData* client_data = NULL); 631 632 // Check whether there are commands in the command queue. 633 static bool HasCommands(); 634 635 static Handle<Object> Call(Handle<JSFunction> fun, 636 Handle<Object> data, 637 bool* pending_exception); 638 639 // Start the debugger agent listening on the provided port. 640 static bool StartAgent(const char* name, int port); 641 642 // Stop the debugger agent. 643 static void StopAgent(); 644 645 // Unload the debugger if possible. Only called when no debugger is currently 646 // active. 647 static void UnloadDebugger(); 648 EventActive(v8::DebugEvent event)649 inline static bool EventActive(v8::DebugEvent event) { 650 ScopedLock with(debugger_access_); 651 652 // Check whether the message handler was been cleared. 653 if (debugger_unload_pending_) { 654 UnloadDebugger(); 655 } 656 657 // Currently argument event is not used. 658 return !compiling_natives_ && Debugger::IsDebuggerActive(); 659 } 660 set_compiling_natives(bool compiling_natives)661 static void set_compiling_natives(bool compiling_natives) { 662 Debugger::compiling_natives_ = compiling_natives; 663 } compiling_natives()664 static bool compiling_natives() { return Debugger::compiling_natives_; } set_loading_debugger(bool v)665 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; } is_loading_debugger()666 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; } 667 668 private: 669 static bool IsDebuggerActive(); 670 static void ListenersChanged(); 671 672 static Mutex* debugger_access_; // Mutex guarding debugger variables. 673 static Handle<Object> event_listener_; // Global handle to listener. 674 static Handle<Object> event_listener_data_; 675 static bool compiling_natives_; // Are we compiling natives? 676 static bool is_loading_debugger_; // Are we loading the debugger? 677 static bool never_unload_debugger_; // Can we unload the debugger? 678 static v8::Debug::MessageHandler2 message_handler_; 679 static bool debugger_unload_pending_; // Was message handler cleared? 680 static v8::Debug::HostDispatchHandler host_dispatch_handler_; 681 static int host_dispatch_micros_; 682 683 static DebuggerAgent* agent_; 684 685 static const int kQueueInitialSize = 4; 686 static LockingCommandMessageQueue command_queue_; 687 static Semaphore* command_received_; // Signaled for each command received. 688 689 friend class EnterDebugger; 690 }; 691 692 693 // This class is used for entering the debugger. Create an instance in the stack 694 // to enter the debugger. This will set the current break state, make sure the 695 // debugger is loaded and switch to the debugger context. If the debugger for 696 // some reason could not be entered FailedToEnter will return true. 697 class EnterDebugger BASE_EMBEDDED { 698 public: EnterDebugger()699 EnterDebugger() 700 : prev_(Debug::debugger_entry()), 701 has_js_frames_(!it_.done()) { 702 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT)); 703 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK)); 704 705 // Link recursive debugger entry. 706 Debug::set_debugger_entry(this); 707 708 // Store the previous break id and frame id. 709 break_id_ = Debug::break_id(); 710 break_frame_id_ = Debug::break_frame_id(); 711 712 // Create the new break info. If there is no JavaScript frames there is no 713 // break frame id. 714 if (has_js_frames_) { 715 Debug::NewBreak(it_.frame()->id()); 716 } else { 717 Debug::NewBreak(StackFrame::NO_ID); 718 } 719 720 // Make sure that debugger is loaded and enter the debugger context. 721 load_failed_ = !Debug::Load(); 722 if (!load_failed_) { 723 // NOTE the member variable save which saves the previous context before 724 // this change. 725 Top::set_context(*Debug::debug_context()); 726 } 727 } 728 ~EnterDebugger()729 ~EnterDebugger() { 730 // Restore to the previous break state. 731 Debug::SetBreak(break_frame_id_, break_id_); 732 733 // Check for leaving the debugger. 734 if (prev_ == NULL) { 735 // Clear mirror cache when leaving the debugger. Skip this if there is a 736 // pending exception as clearing the mirror cache calls back into 737 // JavaScript. This can happen if the v8::Debug::Call is used in which 738 // case the exception should end up in the calling code. 739 if (!Top::has_pending_exception()) { 740 // Try to avoid any pending debug break breaking in the clear mirror 741 // cache JavaScript code. 742 if (StackGuard::IsDebugBreak()) { 743 Debug::set_interrupts_pending(DEBUGBREAK); 744 StackGuard::Continue(DEBUGBREAK); 745 } 746 Debug::ClearMirrorCache(); 747 } 748 749 // Request preemption and debug break when leaving the last debugger entry 750 // if any of these where recorded while debugging. 751 if (Debug::is_interrupt_pending(PREEMPT)) { 752 // This re-scheduling of preemption is to avoid starvation in some 753 // debugging scenarios. 754 Debug::clear_interrupt_pending(PREEMPT); 755 StackGuard::Preempt(); 756 } 757 if (Debug::is_interrupt_pending(DEBUGBREAK)) { 758 Debug::clear_interrupt_pending(DEBUGBREAK); 759 StackGuard::DebugBreak(); 760 } 761 762 // If there are commands in the queue when leaving the debugger request 763 // that these commands are processed. 764 if (Debugger::HasCommands()) { 765 StackGuard::DebugCommand(); 766 } 767 768 // If leaving the debugger with the debugger no longer active unload it. 769 if (!Debugger::IsDebuggerActive()) { 770 Debugger::UnloadDebugger(); 771 } 772 } 773 774 // Leaving this debugger entry. 775 Debug::set_debugger_entry(prev_); 776 } 777 778 // Check whether the debugger could be entered. FailedToEnter()779 inline bool FailedToEnter() { return load_failed_; } 780 781 // Check whether there are any JavaScript frames on the stack. HasJavaScriptFrames()782 inline bool HasJavaScriptFrames() { return has_js_frames_; } 783 784 // Get the active context from before entering the debugger. GetContext()785 inline Handle<Context> GetContext() { return save_.context(); } 786 787 private: 788 EnterDebugger* prev_; // Previous debugger entry if entered recursively. 789 JavaScriptFrameIterator it_; 790 const bool has_js_frames_; // Were there any JavaScript frames? 791 StackFrame::Id break_frame_id_; // Previous break frame id. 792 int break_id_; // Previous break id. 793 bool load_failed_; // Did the debugger fail to load? 794 SaveContext save_; // Saves previous context. 795 }; 796 797 798 // Stack allocated class for disabling break. 799 class DisableBreak BASE_EMBEDDED { 800 public: 801 // Enter the debugger by storing the previous top context and setting the 802 // current top context to the debugger context. DisableBreak(bool disable_break)803 explicit DisableBreak(bool disable_break) { 804 prev_disable_break_ = Debug::disable_break(); 805 Debug::set_disable_break(disable_break); 806 } ~DisableBreak()807 ~DisableBreak() { 808 Debug::set_disable_break(prev_disable_break_); 809 } 810 811 private: 812 // The previous state of the disable break used to restore the value when this 813 // object is destructed. 814 bool prev_disable_break_; 815 }; 816 817 818 // Debug_Address encapsulates the Address pointers used in generating debug 819 // code. 820 class Debug_Address { 821 public: 822 Debug_Address(Debug::AddressId id, int reg = 0) id_(id)823 : id_(id), reg_(reg) { 824 ASSERT(reg == 0 || id == Debug::k_register_address); 825 } 826 AfterBreakTarget()827 static Debug_Address AfterBreakTarget() { 828 return Debug_Address(Debug::k_after_break_target_address); 829 } 830 DebugBreakReturn()831 static Debug_Address DebugBreakReturn() { 832 return Debug_Address(Debug::k_debug_break_return_address); 833 } 834 Register(int reg)835 static Debug_Address Register(int reg) { 836 return Debug_Address(Debug::k_register_address, reg); 837 } 838 address()839 Address address() const { 840 switch (id_) { 841 case Debug::k_after_break_target_address: 842 return reinterpret_cast<Address>(Debug::after_break_target_address()); 843 case Debug::k_debug_break_return_address: 844 return reinterpret_cast<Address>(Debug::debug_break_return_address()); 845 case Debug::k_register_address: 846 return reinterpret_cast<Address>(Debug::register_address(reg_)); 847 default: 848 UNREACHABLE(); 849 return NULL; 850 } 851 } 852 private: 853 Debug::AddressId id_; 854 int reg_; 855 }; 856 857 858 } } // namespace v8::internal 859 860 #endif // ENABLE_DEBUGGER_SUPPORT 861 862 #endif // V8_DEBUG_H_ 863