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