1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_DEBUG_DEBUG_H_ 6 #define V8_DEBUG_DEBUG_H_ 7 8 #include "src/allocation.h" 9 #include "src/arguments.h" 10 #include "src/assembler.h" 11 #include "src/base/atomicops.h" 12 #include "src/base/hashmap.h" 13 #include "src/base/platform/platform.h" 14 #include "src/debug/debug-interface.h" 15 #include "src/execution.h" 16 #include "src/factory.h" 17 #include "src/flags.h" 18 #include "src/frames.h" 19 #include "src/globals.h" 20 #include "src/runtime/runtime.h" 21 #include "src/source-position-table.h" 22 #include "src/string-stream.h" 23 #include "src/v8threads.h" 24 25 #include "include/v8-debug.h" 26 27 namespace v8 { 28 namespace internal { 29 30 31 // Forward declarations. 32 class DebugScope; 33 34 35 // Step actions. NOTE: These values are in macros.py as well. 36 enum StepAction : int8_t { 37 StepNone = -1, // Stepping not prepared. 38 StepOut = 0, // Step out of the current function. 39 StepNext = 1, // Step to the next statement in the current function. 40 StepIn = 2, // Step into new functions invoked or the next statement 41 // in the current function. 42 StepFrame = 3, // Step into a new frame or return to previous frame. 43 44 LastStepAction = StepFrame 45 }; 46 47 // Type of exception break. NOTE: These values are in macros.py as well. 48 enum ExceptionBreakType { 49 BreakException = 0, 50 BreakUncaughtException = 1 51 }; 52 53 54 // Type of exception break. 55 enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS }; 56 57 58 // The different types of breakpoint position alignments. 59 // Must match Debug.BreakPositionAlignment in debug.js 60 enum BreakPositionAlignment { 61 STATEMENT_ALIGNED = 0, 62 BREAK_POSITION_ALIGNED = 1 63 }; 64 65 enum DebugBreakType { 66 NOT_DEBUG_BREAK, 67 DEBUGGER_STATEMENT, 68 DEBUG_BREAK_SLOT, 69 DEBUG_BREAK_SLOT_AT_CALL, 70 DEBUG_BREAK_SLOT_AT_RETURN, 71 DEBUG_BREAK_SLOT_AT_TAIL_CALL, 72 }; 73 74 class BreakLocation { 75 public: 76 static BreakLocation FromFrame(Handle<DebugInfo> debug_info, 77 JavaScriptFrame* frame); 78 79 static void AllAtCurrentStatement(Handle<DebugInfo> debug_info, 80 JavaScriptFrame* frame, 81 List<BreakLocation>* result_out); 82 IsReturn()83 inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; } IsCall()84 inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; } IsTailCall()85 inline bool IsTailCall() const { 86 return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL; 87 } IsDebugBreakSlot()88 inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; } IsDebuggerStatement()89 inline bool IsDebuggerStatement() const { 90 return type_ == DEBUGGER_STATEMENT; 91 } 92 93 bool HasBreakPoint(Handle<DebugInfo> debug_info) const; 94 position()95 inline int position() const { return position_; } 96 97 private: BreakLocation(Handle<AbstractCode> abstract_code,DebugBreakType type,int code_offset,int position)98 BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type, 99 int code_offset, int position) 100 : abstract_code_(abstract_code), 101 code_offset_(code_offset), 102 type_(type), 103 position_(position) { 104 DCHECK_NE(NOT_DEBUG_BREAK, type_); 105 } 106 107 static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, 108 Handle<AbstractCode> abstract_code, 109 int offset); 110 111 void SetDebugBreak(); 112 void ClearDebugBreak(); 113 114 Handle<AbstractCode> abstract_code_; 115 int code_offset_; 116 DebugBreakType type_; 117 int position_; 118 119 friend class CodeBreakIterator; 120 friend class BytecodeArrayBreakIterator; 121 }; 122 123 class BreakIterator { 124 public: 125 static std::unique_ptr<BreakIterator> GetIterator( 126 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code, 127 BreakLocatorType type = ALL_BREAK_LOCATIONS); 128 ~BreakIterator()129 virtual ~BreakIterator() {} 130 131 virtual BreakLocation GetBreakLocation() = 0; 132 virtual bool Done() const = 0; 133 virtual void Next() = 0; 134 SkipTo(int count)135 void SkipTo(int count) { 136 while (count-- > 0) Next(); 137 } 138 139 virtual int code_offset() = 0; break_index()140 int break_index() const { return break_index_; } position()141 inline int position() const { return position_; } statement_position()142 inline int statement_position() const { return statement_position_; } 143 144 virtual bool IsDebugBreak() = 0; 145 virtual void ClearDebugBreak() = 0; 146 virtual void SetDebugBreak() = 0; 147 148 protected: 149 explicit BreakIterator(Handle<DebugInfo> debug_info, 150 BreakLocatorType break_locator_type); 151 152 int BreakIndexFromPosition(int position, BreakPositionAlignment alignment); 153 isolate()154 Isolate* isolate() { return debug_info_->GetIsolate(); } 155 156 Handle<DebugInfo> debug_info_; 157 int break_index_; 158 int position_; 159 int statement_position_; 160 BreakLocatorType break_locator_type_; 161 162 private: 163 DisallowHeapAllocation no_gc_; 164 DISALLOW_COPY_AND_ASSIGN(BreakIterator); 165 }; 166 167 class CodeBreakIterator : public BreakIterator { 168 public: 169 CodeBreakIterator(Handle<DebugInfo> debug_info, BreakLocatorType type); ~CodeBreakIterator()170 ~CodeBreakIterator() override {} 171 172 BreakLocation GetBreakLocation() override; Done()173 bool Done() const override { return reloc_iterator_.done(); } 174 void Next() override; 175 176 bool IsDebugBreak() override; 177 void ClearDebugBreak() override; 178 void SetDebugBreak() override; 179 180 void SkipToPosition(int position, BreakPositionAlignment alignment); 181 code_offset()182 int code_offset() override { 183 return static_cast<int>(rinfo()->pc() - 184 debug_info_->DebugCode()->instruction_start()); 185 } 186 187 private: 188 int GetModeMask(BreakLocatorType type); 189 DebugBreakType GetDebugBreakType(); 190 rmode()191 RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); } rinfo()192 RelocInfo* rinfo() { return reloc_iterator_.rinfo(); } 193 194 RelocIterator reloc_iterator_; 195 SourcePositionTableIterator source_position_iterator_; 196 DISALLOW_COPY_AND_ASSIGN(CodeBreakIterator); 197 }; 198 199 class BytecodeArrayBreakIterator : public BreakIterator { 200 public: 201 BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info, 202 BreakLocatorType type); ~BytecodeArrayBreakIterator()203 ~BytecodeArrayBreakIterator() override {} 204 205 BreakLocation GetBreakLocation() override; Done()206 bool Done() const override { return source_position_iterator_.done(); } 207 void Next() override; 208 209 bool IsDebugBreak() override; 210 void ClearDebugBreak() override; 211 void SetDebugBreak() override; 212 213 void SkipToPosition(int position, BreakPositionAlignment alignment); 214 code_offset()215 int code_offset() override { return source_position_iterator_.code_offset(); } 216 217 private: 218 DebugBreakType GetDebugBreakType(); 219 220 SourcePositionTableIterator source_position_iterator_; 221 DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBreakIterator); 222 }; 223 224 // Linked list holding debug info objects. The debug info objects are kept as 225 // weak handles to avoid a debug info object to keep a function alive. 226 class DebugInfoListNode { 227 public: 228 explicit DebugInfoListNode(DebugInfo* debug_info); 229 ~DebugInfoListNode(); 230 next()231 DebugInfoListNode* next() { return next_; } set_next(DebugInfoListNode * next)232 void set_next(DebugInfoListNode* next) { next_ = next; } debug_info()233 Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); } 234 235 private: 236 // Global (weak) handle to the debug info object. 237 DebugInfo** debug_info_; 238 239 // Next pointer for linked list. 240 DebugInfoListNode* next_; 241 }; 242 243 244 // Message delivered to the message handler callback. This is either a debugger 245 // event or the response to a command. 246 class MessageImpl: public v8::Debug::Message { 247 public: 248 // Create a message object for a debug event. 249 static MessageImpl NewEvent(DebugEvent event, 250 bool running, 251 Handle<JSObject> exec_state, 252 Handle<JSObject> event_data); 253 254 // Create a message object for the response to a debug command. 255 static MessageImpl NewResponse(DebugEvent event, 256 bool running, 257 Handle<JSObject> exec_state, 258 Handle<JSObject> event_data, 259 Handle<String> response_json, 260 v8::Debug::ClientData* client_data); 261 262 // Implementation of interface v8::Debug::Message. 263 virtual bool IsEvent() const; 264 virtual bool IsResponse() const; 265 virtual DebugEvent GetEvent() const; 266 virtual bool WillStartRunning() const; 267 virtual v8::Local<v8::Object> GetExecutionState() const; 268 virtual v8::Local<v8::Object> GetEventData() const; 269 virtual v8::Local<v8::String> GetJSON() const; 270 virtual v8::Local<v8::Context> GetEventContext() const; 271 virtual v8::Debug::ClientData* GetClientData() const; 272 virtual v8::Isolate* GetIsolate() const; 273 274 private: 275 MessageImpl(bool is_event, 276 DebugEvent event, 277 bool running, 278 Handle<JSObject> exec_state, 279 Handle<JSObject> event_data, 280 Handle<String> response_json, 281 v8::Debug::ClientData* client_data); 282 283 bool is_event_; // Does this message represent a debug event? 284 DebugEvent event_; // Debug event causing the break. 285 bool running_; // Will the VM start running after this event? 286 Handle<JSObject> exec_state_; // Current execution state. 287 Handle<JSObject> event_data_; // Data associated with the event. 288 Handle<String> response_json_; // Response JSON if message holds a response. 289 v8::Debug::ClientData* client_data_; // Client data passed with the request. 290 }; 291 292 293 // Details of the debug event delivered to the debug event listener. 294 class EventDetailsImpl : public v8::DebugInterface::EventDetails { 295 public: 296 EventDetailsImpl(DebugEvent event, 297 Handle<JSObject> exec_state, 298 Handle<JSObject> event_data, 299 Handle<Object> callback_data, 300 v8::Debug::ClientData* client_data); 301 virtual DebugEvent GetEvent() const; 302 virtual v8::Local<v8::Object> GetExecutionState() const; 303 virtual v8::Local<v8::Object> GetEventData() const; 304 virtual v8::Local<v8::Context> GetEventContext() const; 305 virtual v8::Local<v8::Value> GetCallbackData() const; 306 virtual v8::Debug::ClientData* GetClientData() const; 307 virtual v8::Isolate* GetIsolate() const; 308 309 private: 310 DebugEvent event_; // Debug event causing the break. 311 Handle<JSObject> exec_state_; // Current execution state. 312 Handle<JSObject> event_data_; // Data associated with the event. 313 Handle<Object> callback_data_; // User data passed with the callback 314 // when it was registered. 315 v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand. 316 }; 317 318 319 // Message send by user to v8 debugger or debugger output message. 320 // In addition to command text it may contain a pointer to some user data 321 // which are expected to be passed along with the command reponse to message 322 // handler. 323 class CommandMessage { 324 public: 325 static CommandMessage New(const Vector<uint16_t>& command, 326 v8::Debug::ClientData* data); 327 CommandMessage(); 328 329 // Deletes user data and disposes of the text. 330 void Dispose(); text()331 Vector<uint16_t> text() const { return text_; } client_data()332 v8::Debug::ClientData* client_data() const { return client_data_; } 333 private: 334 CommandMessage(const Vector<uint16_t>& text, 335 v8::Debug::ClientData* data); 336 337 Vector<uint16_t> text_; 338 v8::Debug::ClientData* client_data_; 339 }; 340 341 342 // A Queue of CommandMessage objects. A thread-safe version is 343 // LockingCommandMessageQueue, based on this class. 344 class CommandMessageQueue BASE_EMBEDDED { 345 public: 346 explicit CommandMessageQueue(int size); 347 ~CommandMessageQueue(); IsEmpty()348 bool IsEmpty() const { return start_ == end_; } 349 CommandMessage Get(); 350 void Put(const CommandMessage& message); Clear()351 void Clear() { start_ = end_ = 0; } // Queue is empty after Clear(). 352 private: 353 // Doubles the size of the message queue, and copies the messages. 354 void Expand(); 355 356 CommandMessage* messages_; 357 int start_; 358 int end_; 359 int size_; // The size of the queue buffer. Queue can hold size-1 messages. 360 }; 361 362 363 // LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage 364 // messages. The message data is not managed by LockingCommandMessageQueue. 365 // Pointers to the data are passed in and out. Implemented by adding a 366 // Mutex to CommandMessageQueue. Includes logging of all puts and gets. 367 class LockingCommandMessageQueue BASE_EMBEDDED { 368 public: 369 LockingCommandMessageQueue(Logger* logger, int size); 370 bool IsEmpty() const; 371 CommandMessage Get(); 372 void Put(const CommandMessage& message); 373 void Clear(); 374 private: 375 Logger* logger_; 376 CommandMessageQueue queue_; 377 mutable base::Mutex mutex_; 378 DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue); 379 }; 380 381 382 class DebugFeatureTracker { 383 public: 384 enum Feature { 385 kActive = 1, 386 kBreakPoint = 2, 387 kStepping = 3, 388 kHeapSnapshot = 4, 389 kAllocationTracking = 5, 390 kProfiler = 6, 391 kLiveEdit = 7, 392 }; 393 DebugFeatureTracker(Isolate * isolate)394 explicit DebugFeatureTracker(Isolate* isolate) 395 : isolate_(isolate), bitfield_(0) {} 396 void Track(Feature feature); 397 398 private: 399 Isolate* isolate_; 400 uint32_t bitfield_; 401 }; 402 403 404 // This class contains the debugger support. The main purpose is to handle 405 // setting break points in the code. 406 // 407 // This class controls the debug info for all functions which currently have 408 // active breakpoints in them. This debug info is held in the heap root object 409 // debug_info which is a FixedArray. Each entry in this list is of class 410 // DebugInfo. 411 class Debug { 412 public: 413 // Debug event triggers. 414 void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue); 415 416 void OnThrow(Handle<Object> exception); 417 void OnPromiseReject(Handle<Object> promise, Handle<Object> value); 418 void OnCompileError(Handle<Script> script); 419 void OnBeforeCompile(Handle<Script> script); 420 void OnAfterCompile(Handle<Script> script); 421 void OnAsyncTaskEvent(Handle<String> type, Handle<Object> id, 422 Handle<String> name); 423 424 // API facing. 425 void SetEventListener(Handle<Object> callback, Handle<Object> data); 426 void SetMessageHandler(v8::Debug::MessageHandler handler); 427 void EnqueueCommandMessage(Vector<const uint16_t> command, 428 v8::Debug::ClientData* client_data = NULL); 429 MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun, 430 Handle<Object> data); 431 Handle<Context> GetDebugContext(); 432 void HandleDebugBreak(); 433 void ProcessDebugMessages(bool debug_command_only); 434 435 // Internal logic 436 bool Load(); 437 void Break(JavaScriptFrame* frame); 438 void SetAfterBreakTarget(JavaScriptFrame* frame); 439 440 // Scripts handling. 441 Handle<FixedArray> GetLoadedScripts(); 442 443 // Break point handling. 444 bool SetBreakPoint(Handle<JSFunction> function, 445 Handle<Object> break_point_object, 446 int* source_position); 447 bool SetBreakPointForScript(Handle<Script> script, 448 Handle<Object> break_point_object, 449 int* source_position, 450 BreakPositionAlignment alignment); 451 void ClearBreakPoint(Handle<Object> break_point_object); 452 void ChangeBreakOnException(ExceptionBreakType type, bool enable); 453 bool IsBreakOnException(ExceptionBreakType type); 454 455 // Stepping handling. 456 void PrepareStep(StepAction step_action); 457 void PrepareStepIn(Handle<JSFunction> function); 458 void PrepareStepInSuspendedGenerator(); 459 void PrepareStepOnThrow(); 460 void ClearStepping(); 461 void ClearStepOut(); 462 463 bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared); 464 bool GetPossibleBreakpoints(Handle<Script> script, int start_position, 465 int end_position, std::set<int>* positions); 466 467 void RecordAsyncFunction(Handle<JSGeneratorObject> generator_object); 468 469 // Returns whether the operation succeeded. Compilation can only be triggered 470 // if a valid closure is passed as the second argument, otherwise the shared 471 // function needs to be compiled already. 472 bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 473 Handle<JSFunction> function); 474 void CreateDebugInfo(Handle<SharedFunctionInfo> shared); 475 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared); 476 477 template <typename C> 478 bool CompileToRevealInnerFunctions(C* compilable); 479 480 // This function is used in FunctionNameUsing* tests. 481 Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script, 482 int position); 483 484 static Handle<Object> GetSourceBreakLocations( 485 Handle<SharedFunctionInfo> shared, 486 BreakPositionAlignment position_aligment); 487 488 // Check whether a global object is the debug global object. 489 bool IsDebugGlobal(JSGlobalObject* global); 490 491 // Check whether this frame is just about to return. 492 bool IsBreakAtReturn(JavaScriptFrame* frame); 493 494 // Support for LiveEdit 495 void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 496 LiveEditFrameDropMode mode); 497 498 // Threading support. 499 char* ArchiveDebug(char* to); 500 char* RestoreDebug(char* from); 501 static int ArchiveSpacePerThread(); FreeThreadResources()502 void FreeThreadResources() { } 503 void Iterate(ObjectVisitor* v); 504 CheckExecutionState(int id)505 bool CheckExecutionState(int id) { 506 return CheckExecutionState() && break_id() == id; 507 } 508 CheckExecutionState()509 bool CheckExecutionState() { 510 return is_active() && !debug_context().is_null() && break_id() != 0; 511 } 512 513 // Flags and states. debugger_entry()514 DebugScope* debugger_entry() { 515 return reinterpret_cast<DebugScope*>( 516 base::NoBarrier_Load(&thread_local_.current_debug_scope_)); 517 } debug_context()518 inline Handle<Context> debug_context() { return debug_context_; } 519 set_live_edit_enabled(bool v)520 void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; } live_edit_enabled()521 bool live_edit_enabled() const { 522 return FLAG_enable_liveedit && live_edit_enabled_; 523 } 524 is_active()525 inline bool is_active() const { return is_active_; } is_loaded()526 inline bool is_loaded() const { return !debug_context_.is_null(); } in_debug_scope()527 inline bool in_debug_scope() const { 528 return !!base::NoBarrier_Load(&thread_local_.current_debug_scope_); 529 } set_break_points_active(bool v)530 void set_break_points_active(bool v) { break_points_active_ = v; } break_points_active()531 bool break_points_active() const { return break_points_active_; } 532 break_frame_id()533 StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; } break_id()534 int break_id() { return thread_local_.break_id_; } 535 return_value()536 Handle<Object> return_value() { return thread_local_.return_value_; } set_return_value(Handle<Object> value)537 void set_return_value(Handle<Object> value) { 538 thread_local_.return_value_ = value; 539 } 540 541 // Support for embedding into generated code. is_active_address()542 Address is_active_address() { 543 return reinterpret_cast<Address>(&is_active_); 544 } 545 after_break_target_address()546 Address after_break_target_address() { 547 return reinterpret_cast<Address>(&after_break_target_); 548 } 549 last_step_action_address()550 Address last_step_action_address() { 551 return reinterpret_cast<Address>(&thread_local_.last_step_action_); 552 } 553 suspended_generator_address()554 Address suspended_generator_address() { 555 return reinterpret_cast<Address>(&thread_local_.suspended_generator_); 556 } 557 last_step_action()558 StepAction last_step_action() { return thread_local_.last_step_action_; } 559 feature_tracker()560 DebugFeatureTracker* feature_tracker() { return &feature_tracker_; } 561 562 private: 563 explicit Debug(Isolate* isolate); 564 565 void UpdateState(); 566 void Unload(); SetNextBreakId()567 void SetNextBreakId() { 568 thread_local_.break_id_ = ++thread_local_.break_count_; 569 } 570 571 // Check whether there are commands in the command queue. has_commands()572 inline bool has_commands() const { return !command_queue_.IsEmpty(); } ignore_events()573 inline bool ignore_events() const { return is_suppressed_ || !is_active_; } break_disabled()574 inline bool break_disabled() const { 575 return break_disabled_ || in_debug_event_listener_; 576 } 577 clear_suspended_generator()578 void clear_suspended_generator() { 579 thread_local_.suspended_generator_ = Smi::kZero; 580 } 581 has_suspended_generator()582 bool has_suspended_generator() const { 583 return thread_local_.suspended_generator_ != Smi::kZero; 584 } 585 586 void OnException(Handle<Object> exception, Handle<Object> promise); 587 588 // Constructors for debug event objects. 589 MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState(); 590 MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent( 591 Handle<Object> break_points_hit); 592 MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent( 593 Handle<Object> exception, 594 bool uncaught, 595 Handle<Object> promise); 596 MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent( 597 Handle<Script> script, v8::DebugEvent type); 598 MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(Handle<String> type, 599 Handle<Object> id, 600 Handle<String> name); 601 602 // Mirror cache handling. 603 void ClearMirrorCache(); 604 605 void CallEventCallback(v8::DebugEvent event, 606 Handle<Object> exec_state, 607 Handle<Object> event_data, 608 v8::Debug::ClientData* client_data); 609 void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script); 610 void ProcessDebugEvent(v8::DebugEvent event, 611 Handle<JSObject> event_data, 612 bool auto_continue); 613 void NotifyMessageHandler(v8::DebugEvent event, 614 Handle<JSObject> exec_state, 615 Handle<JSObject> event_data, 616 bool auto_continue); 617 void InvokeMessageHandler(MessageImpl message); 618 619 // Find the closest source position for a break point for a given position. 620 int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position, 621 BreakPositionAlignment alignment); 622 // Instrument code to break at break points. 623 void ApplyBreakPoints(Handle<DebugInfo> debug_info); 624 // Clear code from instrumentation. 625 void ClearBreakPoints(Handle<DebugInfo> debug_info); 626 // Clear all code from instrumentation. 627 void ClearAllBreakPoints(); 628 // Instrument a function with one-shots. 629 void FloodWithOneShot(Handle<JSFunction> function, 630 BreakLocatorType type = ALL_BREAK_LOCATIONS); 631 // Clear all one-shot instrumentations, but restore break points. 632 void ClearOneShot(); 633 634 void ActivateStepOut(StackFrame* frame); 635 void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info); 636 Handle<Object> CheckBreakPoints(Handle<DebugInfo> debug_info, 637 BreakLocation* location, 638 bool* has_break_points = nullptr); 639 bool IsMutedAtCurrentLocation(JavaScriptFrame* frame); 640 bool CheckBreakPoint(Handle<Object> break_point_object); 641 MaybeHandle<Object> CallFunction(const char* name, int argc, 642 Handle<Object> args[]); 643 AssertDebugContext()644 inline void AssertDebugContext() { 645 DCHECK(isolate_->context() == *debug_context()); 646 DCHECK(in_debug_scope()); 647 } 648 649 void ThreadInit(); 650 651 void PrintBreakLocation(); 652 653 // Global handles. 654 Handle<Context> debug_context_; 655 Handle<Object> event_listener_; 656 Handle<Object> event_listener_data_; 657 658 v8::Debug::MessageHandler message_handler_; 659 660 static const int kQueueInitialSize = 4; 661 base::Semaphore command_received_; // Signaled for each command received. 662 LockingCommandMessageQueue command_queue_; 663 664 bool is_active_; 665 bool is_suppressed_; 666 bool live_edit_enabled_; 667 bool break_disabled_; 668 bool break_points_active_; 669 bool in_debug_event_listener_; 670 bool break_on_exception_; 671 bool break_on_uncaught_exception_; 672 673 DebugInfoListNode* debug_info_list_; // List of active debug info objects. 674 675 // Storage location for jump when exiting debug break calls. 676 // Note that this address is not GC safe. It should be computed immediately 677 // before returning to the DebugBreakCallHelper. 678 Address after_break_target_; 679 680 // Used to collect histogram data on debugger feature usage. 681 DebugFeatureTracker feature_tracker_; 682 683 // Per-thread data. 684 class ThreadLocal { 685 public: 686 // Top debugger entry. 687 base::AtomicWord current_debug_scope_; 688 689 // Counter for generating next break id. 690 int break_count_; 691 692 // Current break id. 693 int break_id_; 694 695 // Frame id for the frame of the current break. 696 StackFrame::Id break_frame_id_; 697 698 // Step action for last step performed. 699 StepAction last_step_action_; 700 701 // Source statement position from last step next action. 702 int last_statement_position_; 703 704 // Frame pointer from last step next or step frame action. 705 Address last_fp_; 706 707 // Frame pointer of the target frame we want to arrive at. 708 Address target_fp_; 709 710 // Stores the way how LiveEdit has patched the stack. It is used when 711 // debugger returns control back to user script. 712 LiveEditFrameDropMode frame_drop_mode_; 713 714 // Value of accumulator in interpreter frames. In non-interpreter frames 715 // this value will be the hole. 716 Handle<Object> return_value_; 717 718 Object* suspended_generator_; 719 }; 720 721 // Storage location for registers when handling debug break calls 722 ThreadLocal thread_local_; 723 724 Isolate* isolate_; 725 726 friend class Isolate; 727 friend class DebugScope; 728 friend class DisableBreak; 729 friend class LiveEdit; 730 friend class SuppressDebug; 731 732 friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc 733 friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc 734 735 DISALLOW_COPY_AND_ASSIGN(Debug); 736 }; 737 738 739 // This scope is used to load and enter the debug context and create a new 740 // break state. Leaving the scope will restore the previous state. 741 // On failure to load, FailedToEnter returns true. 742 class DebugScope BASE_EMBEDDED { 743 public: 744 explicit DebugScope(Debug* debug); 745 ~DebugScope(); 746 747 // Check whether loading was successful. failed()748 inline bool failed() { return failed_; } 749 750 // Get the active context from before entering the debugger. GetContext()751 inline Handle<Context> GetContext() { return save_.context(); } 752 753 private: isolate()754 Isolate* isolate() { return debug_->isolate_; } 755 756 Debug* debug_; 757 DebugScope* prev_; // Previous scope if entered recursively. 758 StackFrame::Id break_frame_id_; // Previous break frame id. 759 int break_id_; // Previous break id. 760 Handle<Object> return_value_; // Previous result. 761 bool failed_; // Did the debug context fail to load? 762 SaveContext save_; // Saves previous context. 763 PostponeInterruptsScope no_termination_exceptons_; 764 }; 765 766 767 // Stack allocated class for disabling break. 768 class DisableBreak BASE_EMBEDDED { 769 public: DisableBreak(Debug * debug,bool disable_break)770 explicit DisableBreak(Debug* debug, bool disable_break) 771 : debug_(debug), 772 previous_break_disabled_(debug->break_disabled_), 773 previous_in_debug_event_listener_(debug->in_debug_event_listener_) { 774 debug_->break_disabled_ = disable_break; 775 debug_->in_debug_event_listener_ = disable_break; 776 } ~DisableBreak()777 ~DisableBreak() { 778 debug_->break_disabled_ = previous_break_disabled_; 779 debug_->in_debug_event_listener_ = previous_in_debug_event_listener_; 780 } 781 782 private: 783 Debug* debug_; 784 bool previous_break_disabled_; 785 bool previous_in_debug_event_listener_; 786 DISALLOW_COPY_AND_ASSIGN(DisableBreak); 787 }; 788 789 790 class SuppressDebug BASE_EMBEDDED { 791 public: SuppressDebug(Debug * debug)792 explicit SuppressDebug(Debug* debug) 793 : debug_(debug), old_state_(debug->is_suppressed_) { 794 debug_->is_suppressed_ = true; 795 } ~SuppressDebug()796 ~SuppressDebug() { debug_->is_suppressed_ = old_state_; } 797 798 private: 799 Debug* debug_; 800 bool old_state_; 801 DISALLOW_COPY_AND_ASSIGN(SuppressDebug); 802 }; 803 804 805 // Code generator routines. 806 class DebugCodegen : public AllStatic { 807 public: 808 enum DebugBreakCallHelperMode { 809 SAVE_RESULT_REGISTER, 810 IGNORE_RESULT_REGISTER 811 }; 812 813 static void GenerateDebugBreakStub(MacroAssembler* masm, 814 DebugBreakCallHelperMode mode); 815 816 // FrameDropper is a code replacement for a JavaScript frame with possibly 817 // several frames above. 818 // There is no calling conventions here, because it never actually gets 819 // called, it only gets returned to. 820 static void GenerateFrameDropperLiveEdit(MacroAssembler* masm); 821 822 823 static void GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode); 824 825 static void PatchDebugBreakSlot(Isolate* isolate, Address pc, 826 Handle<Code> code); 827 static bool DebugBreakSlotIsPatched(Address pc); 828 static void ClearDebugBreakSlot(Isolate* isolate, Address pc); 829 }; 830 831 832 } // namespace internal 833 } // namespace v8 834 835 #endif // V8_DEBUG_DEBUG_H_ 836