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