debug.h revision 6ded16be15dd865a9b21ea304d5273c8be299c87
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 44namespace v8 { 45namespace internal { 46 47 48// Forward declarations. 49class EnterDebugger; 50 51 52// Step actions. NOTE: These values are in macros.py as well. 53enum 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. 66enum ExceptionBreakType { 67 BreakException = 0, 68 BreakUncaughtException = 1 69}; 70 71 72// Type of exception break. NOTE: These values are in macros.py as well. 73enum 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. 81class 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 105 inline int code_position() { 106 return static_cast<int>(pc() - debug_info_->code()->entry()); 107 } 108 inline int break_point() { return break_point_; } 109 inline int position() { return position_; } 110 inline int statement_position() { return statement_position_; } 111 inline Address pc() { return reloc_iterator_->rinfo()->pc(); } 112 inline Code* code() { return debug_info_->code(); } 113 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); } 114 inline RelocInfo::Mode rmode() const { 115 return reloc_iterator_->rinfo()->rmode(); 116 } 117 inline RelocInfo* original_rinfo() { 118 return reloc_iterator_original_->rinfo(); 119 } 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. 157class ScriptCache : private HashMap { 158 public: 159 ScriptCache() : HashMap(ScriptMatch), collected_scripts_(10) {} 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). 173 static uint32_t Hash(int key) { return ComputeIntegerHash(key); } 174 175 // Scripts match if their keys (script id) match. 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. 191class DebugInfoListNode { 192 public: 193 explicit DebugInfoListNode(DebugInfo* debug_info); 194 virtual ~DebugInfoListNode(); 195 196 DebugInfoListNode* next() { return next_; } 197 void set_next(DebugInfoListNode* next) { next_ = next; } 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. 216class Debug { 217 public: 218 static void Setup(bool create_heap_objects); 219 static bool Load(); 220 static void Unload(); 221 static bool IsLoaded() { return !debug_context_.is_null(); } 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. 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. 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); 273 static StackFrame::Id break_frame_id() { 274 return thread_local_.break_frame_id_; 275 } 276 static int break_id() { return thread_local_.break_id_; } 277 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); 283 static Address step_in_fp() { return thread_local_.step_into_fp_; } 284 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } 285 286 static bool StepOutActive() { return thread_local_.step_out_fp_ != 0; } 287 static Address step_out_fp() { return thread_local_.step_out_fp_; } 288 289 static EnterDebugger* debugger_entry() { 290 return thread_local_.debugger_entry_; 291 } 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. 297 static bool is_interrupt_pending(InterruptFlag what) { 298 return (thread_local_.pending_interrupts_ & what) != 0; 299 } 300 301 // Set specified interrupts as pending. 302 static void set_interrupts_pending(InterruptFlag what) { 303 thread_local_.pending_interrupts_ |= what; 304 } 305 306 // Clear specified interrupts from pending. 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. 312 static bool disable_break() { return 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. 318 static bool break_on_exception() { return break_on_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. 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. 335 static Object** register_address(int r) { 336 return ®isters_[r]; 337 } 338 339 // Access to the debug break on return code. 340 static Code* debug_break_return() { return debug_break_return_; } 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(); 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 static void GeneratePlainReturnLiveEdit(MacroAssembler* masm); 381 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); 382 383 // Called from stub-cache.cc. 384 static void GenerateCallICDebugBreak(MacroAssembler* masm); 385 386 static void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id); 387 388 static void SetUpFrameDropperFrame(StackFrame* bottom_js_frame, 389 Handle<Code> code); 390 static const int kFrameDropperFrameSize; 391 392 private: 393 static bool CompileDebuggerScript(int index); 394 static void ClearOneShot(); 395 static void ActivateStepIn(StackFrame* frame); 396 static void ClearStepIn(); 397 static void ActivateStepOut(StackFrame* frame); 398 static void ClearStepOut(); 399 static void ClearStepNext(); 400 // Returns whether the compile succeeded. 401 static void RemoveDebugInfo(Handle<DebugInfo> debug_info); 402 static void SetAfterBreakTarget(JavaScriptFrame* frame); 403 static Handle<Object> CheckBreakPoints(Handle<Object> break_point); 404 static bool CheckBreakPoint(Handle<Object> break_point_object); 405 406 // Global handle to debug context where all the debugger JavaScript code is 407 // loaded. 408 static Handle<Context> debug_context_; 409 410 // Boolean state indicating whether any break points are set. 411 static bool has_break_points_; 412 413 // Cache of all scripts in the heap. 414 static ScriptCache* script_cache_; 415 416 // List of active debug info objects. 417 static DebugInfoListNode* debug_info_list_; 418 419 static bool disable_break_; 420 static bool break_on_exception_; 421 static bool break_on_uncaught_exception_; 422 423 // Per-thread data. 424 class ThreadLocal { 425 public: 426 // Counter for generating next break id. 427 int break_count_; 428 429 // Current break id. 430 int break_id_; 431 432 // Frame id for the frame of the current break. 433 StackFrame::Id break_frame_id_; 434 435 // Step action for last step performed. 436 StepAction last_step_action_; 437 438 // Source statement position from last step next action. 439 int last_statement_position_; 440 441 // Number of steps left to perform before debug event. 442 int step_count_; 443 444 // Frame pointer from last step next action. 445 Address last_fp_; 446 447 // Frame pointer for frame from which step in was performed. 448 Address step_into_fp_; 449 450 // Frame pointer for the frame where debugger should be called when current 451 // step out action is completed. 452 Address step_out_fp_; 453 454 // Storage location for jump when exiting debug break calls. 455 Address after_break_target_; 456 457 // Indicates that LiveEdit has patched the stack. 458 bool frames_are_dropped_; 459 460 // Top debugger entry. 461 EnterDebugger* debugger_entry_; 462 463 // Pending interrupts scheduled while debugging. 464 int pending_interrupts_; 465 }; 466 467 // Storage location for registers when handling debug break calls 468 static JSCallerSavedBuffer registers_; 469 static ThreadLocal thread_local_; 470 static void ThreadInit(); 471 472 // Code to call for handling debug break on return. 473 static Code* debug_break_return_; 474 475 DISALLOW_COPY_AND_ASSIGN(Debug); 476}; 477 478 479// Message delivered to the message handler callback. This is either a debugger 480// event or the response to a command. 481class MessageImpl: public v8::Debug::Message { 482 public: 483 // Create a message object for a debug event. 484 static MessageImpl NewEvent(DebugEvent event, 485 bool running, 486 Handle<JSObject> exec_state, 487 Handle<JSObject> event_data); 488 489 // Create a message object for the response to a debug command. 490 static MessageImpl NewResponse(DebugEvent event, 491 bool running, 492 Handle<JSObject> exec_state, 493 Handle<JSObject> event_data, 494 Handle<String> response_json, 495 v8::Debug::ClientData* client_data); 496 497 // Implementation of interface v8::Debug::Message. 498 virtual bool IsEvent() const; 499 virtual bool IsResponse() const; 500 virtual DebugEvent GetEvent() const; 501 virtual bool WillStartRunning() const; 502 virtual v8::Handle<v8::Object> GetExecutionState() const; 503 virtual v8::Handle<v8::Object> GetEventData() const; 504 virtual v8::Handle<v8::String> GetJSON() const; 505 virtual v8::Handle<v8::Context> GetEventContext() const; 506 virtual v8::Debug::ClientData* GetClientData() const; 507 508 private: 509 MessageImpl(bool is_event, 510 DebugEvent event, 511 bool running, 512 Handle<JSObject> exec_state, 513 Handle<JSObject> event_data, 514 Handle<String> response_json, 515 v8::Debug::ClientData* client_data); 516 517 bool is_event_; // Does this message represent a debug event? 518 DebugEvent event_; // Debug event causing the break. 519 bool running_; // Will the VM start running after this event? 520 Handle<JSObject> exec_state_; // Current execution state. 521 Handle<JSObject> event_data_; // Data associated with the event. 522 Handle<String> response_json_; // Response JSON if message holds a response. 523 v8::Debug::ClientData* client_data_; // Client data passed with the request. 524}; 525 526 527// Message send by user to v8 debugger or debugger output message. 528// In addition to command text it may contain a pointer to some user data 529// which are expected to be passed along with the command reponse to message 530// handler. 531class CommandMessage { 532 public: 533 static CommandMessage New(const Vector<uint16_t>& command, 534 v8::Debug::ClientData* data); 535 CommandMessage(); 536 ~CommandMessage(); 537 538 // Deletes user data and disposes of the text. 539 void Dispose(); 540 Vector<uint16_t> text() const { return text_; } 541 v8::Debug::ClientData* client_data() const { return client_data_; } 542 private: 543 CommandMessage(const Vector<uint16_t>& text, 544 v8::Debug::ClientData* data); 545 546 Vector<uint16_t> text_; 547 v8::Debug::ClientData* client_data_; 548}; 549 550// A Queue of CommandMessage objects. A thread-safe version is 551// LockingCommandMessageQueue, based on this class. 552class CommandMessageQueue BASE_EMBEDDED { 553 public: 554 explicit CommandMessageQueue(int size); 555 ~CommandMessageQueue(); 556 bool IsEmpty() const { return start_ == end_; } 557 CommandMessage Get(); 558 void Put(const CommandMessage& message); 559 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). 560 private: 561 // Doubles the size of the message queue, and copies the messages. 562 void Expand(); 563 564 CommandMessage* messages_; 565 int start_; 566 int end_; 567 int size_; // The size of the queue buffer. Queue can hold size-1 messages. 568}; 569 570 571class MessageDispatchHelperThread; 572 573 574// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage 575// messages. The message data is not managed by LockingCommandMessageQueue. 576// Pointers to the data are passed in and out. Implemented by adding a 577// Mutex to CommandMessageQueue. Includes logging of all puts and gets. 578class LockingCommandMessageQueue BASE_EMBEDDED { 579 public: 580 explicit LockingCommandMessageQueue(int size); 581 ~LockingCommandMessageQueue(); 582 bool IsEmpty() const; 583 CommandMessage Get(); 584 void Put(const CommandMessage& message); 585 void Clear(); 586 private: 587 CommandMessageQueue queue_; 588 Mutex* lock_; 589 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); 590}; 591 592 593class Debugger { 594 public: 595 static void DebugRequest(const uint16_t* json_request, int length); 596 597 static Handle<Object> MakeJSObject(Vector<const char> constructor_name, 598 int argc, Object*** argv, 599 bool* caught_exception); 600 static Handle<Object> MakeExecutionState(bool* caught_exception); 601 static Handle<Object> MakeBreakEvent(Handle<Object> exec_state, 602 Handle<Object> break_points_hit, 603 bool* caught_exception); 604 static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state, 605 Handle<Object> exception, 606 bool uncaught, 607 bool* caught_exception); 608 static Handle<Object> MakeNewFunctionEvent(Handle<Object> func, 609 bool* caught_exception); 610 static Handle<Object> MakeCompileEvent(Handle<Script> script, 611 bool before, 612 bool* caught_exception); 613 static Handle<Object> MakeScriptCollectedEvent(int id, 614 bool* caught_exception); 615 static void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 616 static void OnException(Handle<Object> exception, bool uncaught); 617 static void OnBeforeCompile(Handle<Script> script); 618 619 enum AfterCompileFlags { 620 NO_AFTER_COMPILE_FLAGS, 621 SEND_WHEN_DEBUGGING 622 }; 623 static void OnAfterCompile(Handle<Script> script, 624 AfterCompileFlags after_compile_flags); 625 static void OnNewFunction(Handle<JSFunction> fun); 626 static void OnScriptCollected(int id); 627 static void ProcessDebugEvent(v8::DebugEvent event, 628 Handle<JSObject> event_data, 629 bool auto_continue); 630 static void NotifyMessageHandler(v8::DebugEvent event, 631 Handle<JSObject> exec_state, 632 Handle<JSObject> event_data, 633 bool auto_continue); 634 static void SetEventListener(Handle<Object> callback, Handle<Object> data); 635 static void SetMessageHandler(v8::Debug::MessageHandler2 handler); 636 static void SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, 637 int period); 638 static void SetDebugMessageDispatchHandler( 639 v8::Debug::DebugMessageDispatchHandler handler, 640 bool provide_locker); 641 642 // Invoke the message handler function. 643 static void InvokeMessageHandler(MessageImpl message); 644 645 // Add a debugger command to the command queue. 646 static void ProcessCommand(Vector<const uint16_t> command, 647 v8::Debug::ClientData* client_data = NULL); 648 649 // Check whether there are commands in the command queue. 650 static bool HasCommands(); 651 652 static Handle<Object> Call(Handle<JSFunction> fun, 653 Handle<Object> data, 654 bool* pending_exception); 655 656 // Start the debugger agent listening on the provided port. 657 static bool StartAgent(const char* name, int port, 658 bool wait_for_connection = false); 659 660 // Stop the debugger agent. 661 static void StopAgent(); 662 663 // Blocks until the agent has started listening for connections 664 static void WaitForAgent(); 665 666 static void CallMessageDispatchHandler(); 667 668 static Handle<Context> GetDebugContext(); 669 670 // Unload the debugger if possible. Only called when no debugger is currently 671 // active. 672 static void UnloadDebugger(); 673 friend void ForceUnloadDebugger(); // In test-debug.cc 674 675 inline static bool EventActive(v8::DebugEvent event) { 676 ScopedLock with(debugger_access_); 677 678 // Check whether the message handler was been cleared. 679 if (debugger_unload_pending_) { 680 if (Debug::debugger_entry() == NULL) { 681 UnloadDebugger(); 682 } 683 } 684 685 // Currently argument event is not used. 686 return !compiling_natives_ && Debugger::IsDebuggerActive(); 687 } 688 689 static void set_compiling_natives(bool compiling_natives) { 690 Debugger::compiling_natives_ = compiling_natives; 691 } 692 static bool compiling_natives() { return Debugger::compiling_natives_; } 693 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; } 694 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; } 695 696 private: 697 static bool IsDebuggerActive(); 698 static void ListenersChanged(); 699 700 static Mutex* debugger_access_; // Mutex guarding debugger variables. 701 static Handle<Object> event_listener_; // Global handle to listener. 702 static Handle<Object> event_listener_data_; 703 static bool compiling_natives_; // Are we compiling natives? 704 static bool is_loading_debugger_; // Are we loading the debugger? 705 static bool never_unload_debugger_; // Can we unload the debugger? 706 static v8::Debug::MessageHandler2 message_handler_; 707 static bool debugger_unload_pending_; // Was message handler cleared? 708 static v8::Debug::HostDispatchHandler host_dispatch_handler_; 709 static Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler. 710 static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_; 711 static MessageDispatchHelperThread* message_dispatch_helper_thread_; 712 static int host_dispatch_micros_; 713 714 static DebuggerAgent* agent_; 715 716 static const int kQueueInitialSize = 4; 717 static LockingCommandMessageQueue command_queue_; 718 static Semaphore* command_received_; // Signaled for each command received. 719 720 friend class EnterDebugger; 721}; 722 723 724// This class is used for entering the debugger. Create an instance in the stack 725// to enter the debugger. This will set the current break state, make sure the 726// debugger is loaded and switch to the debugger context. If the debugger for 727// some reason could not be entered FailedToEnter will return true. 728class EnterDebugger BASE_EMBEDDED { 729 public: 730 EnterDebugger() 731 : prev_(Debug::debugger_entry()), 732 has_js_frames_(!it_.done()) { 733 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(PREEMPT)); 734 ASSERT(prev_ != NULL || !Debug::is_interrupt_pending(DEBUGBREAK)); 735 736 // Link recursive debugger entry. 737 Debug::set_debugger_entry(this); 738 739 // Store the previous break id and frame id. 740 break_id_ = Debug::break_id(); 741 break_frame_id_ = Debug::break_frame_id(); 742 743 // Create the new break info. If there is no JavaScript frames there is no 744 // break frame id. 745 if (has_js_frames_) { 746 Debug::NewBreak(it_.frame()->id()); 747 } else { 748 Debug::NewBreak(StackFrame::NO_ID); 749 } 750 751 // Make sure that debugger is loaded and enter the debugger context. 752 load_failed_ = !Debug::Load(); 753 if (!load_failed_) { 754 // NOTE the member variable save which saves the previous context before 755 // this change. 756 Top::set_context(*Debug::debug_context()); 757 } 758 } 759 760 ~EnterDebugger() { 761 // Restore to the previous break state. 762 Debug::SetBreak(break_frame_id_, break_id_); 763 764 // Check for leaving the debugger. 765 if (prev_ == NULL) { 766 // Clear mirror cache when leaving the debugger. Skip this if there is a 767 // pending exception as clearing the mirror cache calls back into 768 // JavaScript. This can happen if the v8::Debug::Call is used in which 769 // case the exception should end up in the calling code. 770 if (!Top::has_pending_exception()) { 771 // Try to avoid any pending debug break breaking in the clear mirror 772 // cache JavaScript code. 773 if (StackGuard::IsDebugBreak()) { 774 Debug::set_interrupts_pending(DEBUGBREAK); 775 StackGuard::Continue(DEBUGBREAK); 776 } 777 Debug::ClearMirrorCache(); 778 } 779 780 // Request preemption and debug break when leaving the last debugger entry 781 // if any of these where recorded while debugging. 782 if (Debug::is_interrupt_pending(PREEMPT)) { 783 // This re-scheduling of preemption is to avoid starvation in some 784 // debugging scenarios. 785 Debug::clear_interrupt_pending(PREEMPT); 786 StackGuard::Preempt(); 787 } 788 if (Debug::is_interrupt_pending(DEBUGBREAK)) { 789 Debug::clear_interrupt_pending(DEBUGBREAK); 790 StackGuard::DebugBreak(); 791 } 792 793 // If there are commands in the queue when leaving the debugger request 794 // that these commands are processed. 795 if (Debugger::HasCommands()) { 796 StackGuard::DebugCommand(); 797 } 798 799 // If leaving the debugger with the debugger no longer active unload it. 800 if (!Debugger::IsDebuggerActive()) { 801 Debugger::UnloadDebugger(); 802 } 803 } 804 805 // Leaving this debugger entry. 806 Debug::set_debugger_entry(prev_); 807 } 808 809 // Check whether the debugger could be entered. 810 inline bool FailedToEnter() { return load_failed_; } 811 812 // Check whether there are any JavaScript frames on the stack. 813 inline bool HasJavaScriptFrames() { return has_js_frames_; } 814 815 // Get the active context from before entering the debugger. 816 inline Handle<Context> GetContext() { return save_.context(); } 817 818 private: 819 EnterDebugger* prev_; // Previous debugger entry if entered recursively. 820 JavaScriptFrameIterator it_; 821 const bool has_js_frames_; // Were there any JavaScript frames? 822 StackFrame::Id break_frame_id_; // Previous break frame id. 823 int break_id_; // Previous break id. 824 bool load_failed_; // Did the debugger fail to load? 825 SaveContext save_; // Saves previous context. 826}; 827 828 829// Stack allocated class for disabling break. 830class DisableBreak BASE_EMBEDDED { 831 public: 832 // Enter the debugger by storing the previous top context and setting the 833 // current top context to the debugger context. 834 explicit DisableBreak(bool disable_break) { 835 prev_disable_break_ = Debug::disable_break(); 836 Debug::set_disable_break(disable_break); 837 } 838 ~DisableBreak() { 839 Debug::set_disable_break(prev_disable_break_); 840 } 841 842 private: 843 // The previous state of the disable break used to restore the value when this 844 // object is destructed. 845 bool prev_disable_break_; 846}; 847 848 849// Debug_Address encapsulates the Address pointers used in generating debug 850// code. 851class Debug_Address { 852 public: 853 Debug_Address(Debug::AddressId id, int reg = 0) 854 : id_(id), reg_(reg) { 855 ASSERT(reg == 0 || id == Debug::k_register_address); 856 } 857 858 static Debug_Address AfterBreakTarget() { 859 return Debug_Address(Debug::k_after_break_target_address); 860 } 861 862 static Debug_Address DebugBreakReturn() { 863 return Debug_Address(Debug::k_debug_break_return_address); 864 } 865 866 static Debug_Address Register(int reg) { 867 return Debug_Address(Debug::k_register_address, reg); 868 } 869 870 Address address() const { 871 switch (id_) { 872 case Debug::k_after_break_target_address: 873 return reinterpret_cast<Address>(Debug::after_break_target_address()); 874 case Debug::k_debug_break_return_address: 875 return reinterpret_cast<Address>(Debug::debug_break_return_address()); 876 case Debug::k_register_address: 877 return reinterpret_cast<Address>(Debug::register_address(reg_)); 878 default: 879 UNREACHABLE(); 880 return NULL; 881 } 882 } 883 private: 884 Debug::AddressId id_; 885 int reg_; 886}; 887 888// The optional thread that Debug Agent may use to temporary call V8 to process 889// pending debug requests if debuggee is not running V8 at the moment. 890// Techincally it does not call V8 itself, rather it asks embedding program 891// to do this via v8::Debug::HostDispatchHandler 892class MessageDispatchHelperThread: public Thread { 893 public: 894 MessageDispatchHelperThread(); 895 ~MessageDispatchHelperThread(); 896 897 void Schedule(); 898 899 private: 900 void Run(); 901 902 Semaphore* const sem_; 903 Mutex* const mutex_; 904 bool already_signalled_; 905 906 DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread); 907}; 908 909 910} } // namespace v8::internal 911 912#endif // ENABLE_DEBUGGER_SUPPORT 913 914#endif // V8_DEBUG_H_ 915