LCOV - code coverage report
Current view: top level - src/debug - debug.h (source / functions) Hit Total Coverage
Test: app.info Lines: 60 62 96.8 %
Date: 2017-04-26 Functions: 25 35 71.4 %

          Line data    Source code
       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/assembler.h"
      10             : #include "src/base/atomicops.h"
      11             : #include "src/base/hashmap.h"
      12             : #include "src/base/platform/platform.h"
      13             : #include "src/debug/debug-interface.h"
      14             : #include "src/debug/interface-types.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             :   LastStepAction = StepIn
      43             : };
      44             : 
      45             : // Type of exception break. NOTE: These values are in macros.py as well.
      46             : enum ExceptionBreakType {
      47             :   BreakException = 0,
      48             :   BreakUncaughtException = 1
      49             : };
      50             : 
      51             : 
      52             : // The different types of breakpoint position alignments.
      53             : // Must match Debug.BreakPositionAlignment in debug.js
      54             : enum BreakPositionAlignment {
      55             :   STATEMENT_ALIGNED = 0,
      56             :   BREAK_POSITION_ALIGNED = 1
      57             : };
      58             : 
      59             : enum DebugBreakType {
      60             :   NOT_DEBUG_BREAK,
      61             :   DEBUGGER_STATEMENT,
      62             :   DEBUG_BREAK_SLOT,
      63             :   DEBUG_BREAK_SLOT_AT_CALL,
      64             :   DEBUG_BREAK_SLOT_AT_RETURN,
      65             :   DEBUG_BREAK_SLOT_AT_TAIL_CALL,
      66             : };
      67             : 
      68             : enum IgnoreBreakMode {
      69             :   kIgnoreIfAllFramesBlackboxed,
      70             :   kIgnoreIfTopFrameBlackboxed
      71             : };
      72             : 
      73             : class BreakLocation {
      74             :  public:
      75             :   static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
      76             :                                  JavaScriptFrame* frame);
      77             : 
      78             :   static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
      79             :                                     JavaScriptFrame* frame,
      80             :                                     List<BreakLocation>* result_out);
      81             : 
      82      116702 :   inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
      83             :   inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
      84             :   inline bool IsTailCall() const {
      85       13398 :     return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
      86             :   }
      87             :   inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
      88             :   inline bool IsDebuggerStatement() const {
      89             :     return type_ == DEBUGGER_STATEMENT;
      90             :   }
      91             : 
      92             :   bool HasBreakPoint(Handle<DebugInfo> debug_info) const;
      93             : 
      94             :   inline int position() const { return position_; }
      95             : 
      96             :   debug::BreakLocationType type() const;
      97             : 
      98             :  private:
      99             :   BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
     100             :                 int code_offset, int position)
     101             :       : abstract_code_(abstract_code),
     102             :         code_offset_(code_offset),
     103             :         type_(type),
     104      390986 :         position_(position) {
     105             :     DCHECK_NE(NOT_DEBUG_BREAK, type_);
     106             :   }
     107             : 
     108             :   static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
     109             :                                       Handle<AbstractCode> abstract_code,
     110             :                                       int offset);
     111             : 
     112             :   void SetDebugBreak();
     113             :   void ClearDebugBreak();
     114             : 
     115             :   Handle<AbstractCode> abstract_code_;
     116             :   int code_offset_;
     117             :   DebugBreakType type_;
     118             :   int position_;
     119             : 
     120             :   friend class CodeBreakIterator;
     121             :   friend class BytecodeArrayBreakIterator;
     122             : };
     123             : 
     124             : class BreakIterator {
     125             :  public:
     126             :   static std::unique_ptr<BreakIterator> GetIterator(
     127             :       Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code);
     128             : 
     129     1053942 :   virtual ~BreakIterator() {}
     130             : 
     131             :   virtual BreakLocation GetBreakLocation() = 0;
     132             :   virtual bool Done() const = 0;
     133             :   virtual void Next() = 0;
     134             : 
     135             :   void SkipTo(int count) {
     136    13949858 :     while (count-- > 0) Next();
     137             :   }
     138             : 
     139             :   virtual int code_offset() = 0;
     140             :   int break_index() const { return break_index_; }
     141             :   inline int position() const { return 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             : 
     151             :   int BreakIndexFromPosition(int position, BreakPositionAlignment alignment);
     152             : 
     153             :   Isolate* isolate() { return debug_info_->GetIsolate(); }
     154             : 
     155             :   Handle<DebugInfo> debug_info_;
     156             :   int break_index_;
     157             :   int position_;
     158             :   int statement_position_;
     159             : 
     160             :  private:
     161             :   DisallowHeapAllocation no_gc_;
     162             :   DISALLOW_COPY_AND_ASSIGN(BreakIterator);
     163             : };
     164             : 
     165             : class CodeBreakIterator : public BreakIterator {
     166             :  public:
     167             :   explicit CodeBreakIterator(Handle<DebugInfo> debug_info);
     168      610439 :   ~CodeBreakIterator() override {}
     169             : 
     170             :   BreakLocation GetBreakLocation() override;
     171    38049174 :   bool Done() const override { return reloc_iterator_.done(); }
     172             :   void Next() override;
     173             : 
     174             :   bool IsDebugBreak() override;
     175             :   void ClearDebugBreak() override;
     176             :   void SetDebugBreak() override;
     177             : 
     178             :   void SkipToPosition(int position, BreakPositionAlignment alignment);
     179             : 
     180    40797937 :   int code_offset() override {
     181    81599152 :     return static_cast<int>(rinfo()->pc() -
     182    81599152 :                             debug_info_->DebugCode()->instruction_start());
     183             :   }
     184             : 
     185             :  private:
     186             :   int GetModeMask();
     187             :   DebugBreakType GetDebugBreakType();
     188             : 
     189     2308338 :   RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
     190             :   RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
     191             : 
     192             :   RelocIterator reloc_iterator_;
     193             :   SourcePositionTableIterator source_position_iterator_;
     194             :   DISALLOW_COPY_AND_ASSIGN(CodeBreakIterator);
     195             : };
     196             : 
     197             : class BytecodeArrayBreakIterator : public BreakIterator {
     198             :  public:
     199             :   explicit BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info);
     200     1215023 :   ~BytecodeArrayBreakIterator() override {}
     201             : 
     202             :   BreakLocation GetBreakLocation() override;
     203   249673157 :   bool Done() const override { return source_position_iterator_.done(); }
     204             :   void Next() override;
     205             : 
     206             :   bool IsDebugBreak() override;
     207             :   void ClearDebugBreak() override;
     208             :   void SetDebugBreak() override;
     209             : 
     210             :   void SkipToPosition(int position, BreakPositionAlignment alignment);
     211             : 
     212   125513651 :   int code_offset() override { return source_position_iterator_.code_offset(); }
     213             : 
     214             :  private:
     215             :   DebugBreakType GetDebugBreakType();
     216             : 
     217             :   SourcePositionTableIterator source_position_iterator_;
     218             :   DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBreakIterator);
     219             : };
     220             : 
     221             : // Linked list holding debug info objects. The debug info objects are kept as
     222             : // weak handles to avoid a debug info object to keep a function alive.
     223             : class DebugInfoListNode {
     224             :  public:
     225             :   explicit DebugInfoListNode(DebugInfo* debug_info);
     226             :   ~DebugInfoListNode();
     227             : 
     228             :   DebugInfoListNode* next() { return next_; }
     229       12351 :   void set_next(DebugInfoListNode* next) { next_ = next; }
     230             :   Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }
     231             : 
     232             :  private:
     233             :   // Global (weak) handle to the debug info object.
     234             :   DebugInfo** debug_info_;
     235             : 
     236             :   // Next pointer for linked list.
     237             :   DebugInfoListNode* next_;
     238             : };
     239             : 
     240             : class DebugFeatureTracker {
     241             :  public:
     242             :   enum Feature {
     243             :     kActive = 1,
     244             :     kBreakPoint = 2,
     245             :     kStepping = 3,
     246             :     kHeapSnapshot = 4,
     247             :     kAllocationTracking = 5,
     248             :     kProfiler = 6,
     249             :     kLiveEdit = 7,
     250             :   };
     251             : 
     252             :   explicit DebugFeatureTracker(Isolate* isolate)
     253       60782 :       : isolate_(isolate), bitfield_(0) {}
     254             :   void Track(Feature feature);
     255             : 
     256             :  private:
     257             :   Isolate* isolate_;
     258             :   uint32_t bitfield_;
     259             : };
     260             : 
     261             : 
     262             : // This class contains the debugger support. The main purpose is to handle
     263             : // setting break points in the code.
     264             : //
     265             : // This class controls the debug info for all functions which currently have
     266             : // active breakpoints in them. This debug info is held in the heap root object
     267             : // debug_info which is a FixedArray. Each entry in this list is of class
     268             : // DebugInfo.
     269             : class Debug {
     270             :  public:
     271             :   // Debug event triggers.
     272             :   void OnDebugBreak(Handle<Object> break_points_hit);
     273             : 
     274             :   void OnThrow(Handle<Object> exception);
     275             :   void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
     276             :   void OnCompileError(Handle<Script> script);
     277             :   void OnAfterCompile(Handle<Script> script);
     278             :   void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
     279             :                         int parent_id);
     280             : 
     281             :   MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
     282             :                                            Handle<Object> data);
     283             :   Handle<Context> GetDebugContext();
     284             :   void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);
     285             : 
     286             :   // Internal logic
     287             :   bool Load();
     288             :   void Break(JavaScriptFrame* frame);
     289             : 
     290             :   // Scripts handling.
     291             :   Handle<FixedArray> GetLoadedScripts();
     292             : 
     293             :   // Break point handling.
     294             :   bool SetBreakPoint(Handle<JSFunction> function,
     295             :                      Handle<Object> break_point_object,
     296             :                      int* source_position);
     297             :   bool SetBreakPointForScript(Handle<Script> script,
     298             :                               Handle<Object> break_point_object,
     299             :                               int* source_position,
     300             :                               BreakPositionAlignment alignment);
     301             :   void ClearBreakPoint(Handle<Object> break_point_object);
     302             :   void ChangeBreakOnException(ExceptionBreakType type, bool enable);
     303             :   bool IsBreakOnException(ExceptionBreakType type);
     304             : 
     305             :   // The parameter is either a BreakPointInfo object, or a FixedArray of
     306             :   // BreakPointInfo objects.
     307             :   // Returns an empty handle if no breakpoint is hit, or a FixedArray with all
     308             :   // hit breakpoints.
     309             :   MaybeHandle<FixedArray> GetHitBreakPointObjects(
     310             :       Handle<Object> break_point_objects);
     311             : 
     312             :   // Stepping handling.
     313             :   void PrepareStep(StepAction step_action);
     314             :   void PrepareStepIn(Handle<JSFunction> function);
     315             :   void PrepareStepInSuspendedGenerator();
     316             :   void PrepareStepOnThrow();
     317             :   void ClearStepping();
     318             :   void ClearStepOut();
     319             : 
     320             :   bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
     321             :   bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
     322             :                               int end_position, bool restrict_to_function,
     323             :                               std::vector<BreakLocation>* locations);
     324             : 
     325             :   void RecordGenerator(Handle<JSGeneratorObject> generator_object);
     326             : 
     327             :   void RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
     328             :                       Handle<Object> parent);
     329             : 
     330             :   int NextAsyncTaskId(Handle<JSObject> promise);
     331             : 
     332             :   bool IsBlackboxed(Handle<SharedFunctionInfo> shared);
     333             : 
     334             :   void SetDebugDelegate(debug::DebugDelegate* delegate, bool pass_ownership);
     335             : 
     336             :   // Returns whether the operation succeeded.
     337             :   bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
     338             :   void CreateDebugInfo(Handle<SharedFunctionInfo> shared);
     339             :   static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
     340             : 
     341             :   template <typename C>
     342             :   bool CompileToRevealInnerFunctions(C* compilable);
     343             : 
     344             :   // This function is used in FunctionNameUsing* tests.
     345             :   Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
     346             :                                                 int position);
     347             : 
     348             :   static Handle<Object> GetSourceBreakLocations(
     349             :       Handle<SharedFunctionInfo> shared,
     350             :       BreakPositionAlignment position_aligment);
     351             : 
     352             :   // Check whether a global object is the debug global object.
     353             :   bool IsDebugGlobal(JSGlobalObject* global);
     354             : 
     355             :   // Check whether this frame is just about to return.
     356             :   bool IsBreakAtReturn(JavaScriptFrame* frame);
     357             : 
     358             :   // Support for LiveEdit
     359             :   void ScheduleFrameRestart(StackFrame* frame);
     360             : 
     361             :   bool AllFramesOnStackAreBlackboxed();
     362             : 
     363             :   // Threading support.
     364             :   char* ArchiveDebug(char* to);
     365             :   char* RestoreDebug(char* from);
     366             :   static int ArchiveSpacePerThread();
     367             :   void FreeThreadResources() { }
     368             :   void Iterate(RootVisitor* v);
     369             : 
     370    12815742 :   bool CheckExecutionState(int id) {
     371    12815742 :     return CheckExecutionState() && break_id() == id;
     372             :   }
     373             : 
     374    12941522 :   bool CheckExecutionState() {
     375    12941522 :     return is_active() && !debug_context().is_null() && break_id() != 0;
     376             :   }
     377             : 
     378             :   bool PerformSideEffectCheck(Handle<JSFunction> function);
     379             :   bool PerformSideEffectCheckForCallback(Address function);
     380             : 
     381             :   // Flags and states.
     382     5375801 :   DebugScope* debugger_entry() {
     383             :     return reinterpret_cast<DebugScope*>(
     384    11641878 :         base::NoBarrier_Load(&thread_local_.current_debug_scope_));
     385             :   }
     386      229547 :   inline Handle<Context> debug_context() { return debug_context_; }
     387             : 
     388        4146 :   void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
     389       13998 :   bool live_edit_enabled() const {
     390       13998 :     return FLAG_enable_liveedit && live_edit_enabled_;
     391             :   }
     392             : 
     393       44765 :   inline bool is_active() const { return is_active_; }
     394             :   inline bool is_loaded() const { return !debug_context_.is_null(); }
     395     5376029 :   inline bool in_debug_scope() const {
     396    13695331 :     return !!base::NoBarrier_Load(&thread_local_.current_debug_scope_);
     397             :   }
     398        4519 :   void set_break_points_active(bool v) { break_points_active_ = v; }
     399       12034 :   bool break_points_active() const { return break_points_active_; }
     400             : 
     401      692965 :   StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
     402             :   int break_id() { return thread_local_.break_id_; }
     403             : 
     404       90822 :   Handle<Object> return_value_handle() {
     405      181644 :     return handle(thread_local_.return_value_, isolate_);
     406             :   }
     407       35553 :   Object* return_value() { return thread_local_.return_value_; }
     408      181644 :   void set_return_value(Object* value) { thread_local_.return_value_ = value; }
     409             : 
     410             :   // Support for embedding into generated code.
     411             :   Address is_active_address() {
     412             :     return reinterpret_cast<Address>(&is_active_);
     413             :   }
     414             : 
     415             :   Address hook_on_function_call_address() {
     416             :     return reinterpret_cast<Address>(&hook_on_function_call_);
     417             :   }
     418             : 
     419             :   Address last_step_action_address() {
     420             :     return reinterpret_cast<Address>(&thread_local_.last_step_action_);
     421             :   }
     422             : 
     423             :   Address suspended_generator_address() {
     424             :     return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
     425             :   }
     426             : 
     427             :   Address restart_fp_address() {
     428             :     return reinterpret_cast<Address>(&thread_local_.restart_fp_);
     429             :   }
     430             : 
     431     1377910 :   StepAction last_step_action() { return thread_local_.last_step_action_; }
     432             : 
     433         802 :   DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
     434             : 
     435             :  private:
     436             :   explicit Debug(Isolate* isolate);
     437             :   ~Debug() { DCHECK_NULL(debug_delegate_); }
     438             : 
     439             :   void UpdateState();
     440             :   void UpdateHookOnFunctionCall();
     441             :   void RemoveDebugDelegate();
     442             :   void Unload();
     443             :   void SetNextBreakId() {
     444      332085 :     thread_local_.break_id_ = ++thread_local_.break_count_;
     445             :   }
     446             : 
     447             :   // Return the number of virtual frames below debugger entry.
     448             :   int CurrentFrameCount();
     449             : 
     450             :   inline bool ignore_events() const {
     451     9085130 :     return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check();
     452             :   }
     453             :   inline bool break_disabled() const { return break_disabled_; }
     454             : 
     455             :   void clear_suspended_generator() {
     456      195603 :     thread_local_.suspended_generator_ = Smi::kZero;
     457             :   }
     458             : 
     459             :   bool has_suspended_generator() const {
     460             :     return thread_local_.suspended_generator_ != Smi::kZero;
     461             :   }
     462             : 
     463             :   bool IsExceptionBlackboxed(bool uncaught);
     464             : 
     465             :   void OnException(Handle<Object> exception, Handle<Object> promise);
     466             : 
     467             :   // Constructors for debug event objects.
     468             :   MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
     469             :   MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
     470             :       Handle<Object> break_points_hit);
     471             :   MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
     472             :       Handle<Object> exception,
     473             :       bool uncaught,
     474             :       Handle<Object> promise);
     475             :   MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
     476             :       Handle<Script> script, v8::DebugEvent type);
     477             :   MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(
     478             :       v8::debug::PromiseDebugActionType type, int id);
     479             : 
     480             :   void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
     481             :   void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
     482             : 
     483             :   // Find the closest source position for a break point for a given position.
     484             :   int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position,
     485             :                             BreakPositionAlignment alignment);
     486             :   // Instrument code to break at break points.
     487             :   void ApplyBreakPoints(Handle<DebugInfo> debug_info);
     488             :   // Clear code from instrumentation.
     489             :   void ClearBreakPoints(Handle<DebugInfo> debug_info);
     490             :   // Clear all code from instrumentation.
     491             :   void ClearAllBreakPoints();
     492             :   // Instrument a function with one-shots.
     493             :   void FloodWithOneShot(Handle<SharedFunctionInfo> function,
     494             :                         bool returns_only = false);
     495             :   // Clear all one-shot instrumentations, but restore break points.
     496             :   void ClearOneShot();
     497             : 
     498             :   bool IsFrameBlackboxed(JavaScriptFrame* frame);
     499             : 
     500             :   void ActivateStepOut(StackFrame* frame);
     501             :   void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info);
     502             :   MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
     503             :                                            BreakLocation* location,
     504             :                                            bool* has_break_points = nullptr);
     505             :   bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
     506             :   bool CheckBreakPoint(Handle<Object> break_point_object);
     507             :   MaybeHandle<Object> CallFunction(const char* name, int argc,
     508             :                                    Handle<Object> args[]);
     509             : 
     510             :   inline void AssertDebugContext() {
     511             :     DCHECK(isolate_->context() == *debug_context());
     512             :     DCHECK(in_debug_scope());
     513             :   }
     514             : 
     515             :   void ThreadInit();
     516             : 
     517             :   void PrintBreakLocation();
     518             : 
     519             :   // Global handles.
     520             :   Handle<Context> debug_context_;
     521             : 
     522             :   debug::DebugDelegate* debug_delegate_ = nullptr;
     523             :   bool owns_debug_delegate_ = false;
     524             : 
     525             :   // Debugger is active, i.e. there is a debug event listener attached.
     526             :   bool is_active_;
     527             :   // Debugger needs to be notified on every new function call.
     528             :   // Used for stepping and read-only checks
     529             :   bool hook_on_function_call_;
     530             :   // Suppress debug events.
     531             :   bool is_suppressed_;
     532             :   // LiveEdit is enabled.
     533             :   bool live_edit_enabled_;
     534             :   // Do not trigger debug break events.
     535             :   bool break_disabled_;
     536             :   // Do not break on break points.
     537             :   bool break_points_active_;
     538             :   // Trigger debug break events for all exceptions.
     539             :   bool break_on_exception_;
     540             :   // Trigger debug break events for uncaught exceptions.
     541             :   bool break_on_uncaught_exception_;
     542             :   // Termination exception because side effect check has failed.
     543             :   bool side_effect_check_failed_;
     544             : 
     545             :   // List of active debug info objects.
     546             :   DebugInfoListNode* debug_info_list_;
     547             : 
     548             :   // Used to collect histogram data on debugger feature usage.
     549             :   DebugFeatureTracker feature_tracker_;
     550             : 
     551             :   // Per-thread data.
     552             :   class ThreadLocal {
     553             :    public:
     554             :     // Top debugger entry.
     555             :     base::AtomicWord current_debug_scope_;
     556             : 
     557             :     // Counter for generating next break id.
     558             :     int break_count_;
     559             : 
     560             :     // Current break id.
     561             :     int break_id_;
     562             : 
     563             :     // Frame id for the frame of the current break.
     564             :     StackFrame::Id break_frame_id_;
     565             : 
     566             :     // Step action for last step performed.
     567             :     StepAction last_step_action_;
     568             : 
     569             :     // If set, next PrepareStepIn will ignore this function until stepped into
     570             :     // another function, at which point this will be cleared.
     571             :     Object* ignore_step_into_function_;
     572             : 
     573             :     // If set then we need to repeat StepOut action at return.
     574             :     bool fast_forward_to_return_;
     575             : 
     576             :     // Source statement position from last step next action.
     577             :     int last_statement_position_;
     578             : 
     579             :     // Frame pointer from last step next or step frame action.
     580             :     int last_frame_count_;
     581             : 
     582             :     // Frame pointer of the target frame we want to arrive at.
     583             :     int target_frame_count_;
     584             : 
     585             :     // Value of the accumulator at the point of entering the debugger.
     586             :     Object* return_value_;
     587             : 
     588             :     // The suspended generator object to track when stepping.
     589             :     Object* suspended_generator_;
     590             : 
     591             :     // The new frame pointer to drop to when restarting a frame.
     592             :     Address restart_fp_;
     593             : 
     594             :     int async_task_count_;
     595             :   };
     596             : 
     597             :   // Storage location for registers when handling debug break calls
     598             :   ThreadLocal thread_local_;
     599             : 
     600             :   Isolate* isolate_;
     601             : 
     602             :   friend class Isolate;
     603             :   friend class DebugScope;
     604             :   friend class DisableBreak;
     605             :   friend class LiveEdit;
     606             :   friend class SuppressDebug;
     607             :   friend class NoSideEffectScope;
     608             :   friend class LegacyDebugDelegate;
     609             : 
     610             :   friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
     611             :   friend void CheckDebuggerUnloaded(bool check_functions);  // In test-debug.cc
     612             : 
     613             :   DISALLOW_COPY_AND_ASSIGN(Debug);
     614             : };
     615             : 
     616         753 : class LegacyDebugDelegate : public v8::debug::DebugDelegate {
     617             :  public:
     618         753 :   explicit LegacyDebugDelegate(Isolate* isolate) : isolate_(isolate) {}
     619             :   void PromiseEventOccurred(v8::debug::PromiseDebugActionType type, int id,
     620             :                             int parent_id, bool created_by_user) override;
     621             :   void ScriptCompiled(v8::Local<v8::debug::Script> script,
     622             :                       bool has_compile_error) override;
     623             :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
     624             :                              v8::Local<v8::Object> exec_state,
     625             :                              v8::Local<v8::Value> break_points_hit) override;
     626             :   void ExceptionThrown(v8::Local<v8::Context> paused_context,
     627             :                        v8::Local<v8::Object> exec_state,
     628             :                        v8::Local<v8::Value> exception,
     629             :                        v8::Local<v8::Value> promise, bool is_uncaught) override;
     630        3066 :   bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
     631             :                             const v8::debug::Location& start,
     632             :                             const v8::debug::Location& end) override {
     633        3066 :     return false;
     634             :   }
     635             : 
     636             :  protected:
     637             :   Isolate* isolate_;
     638             : 
     639             :  private:
     640             :   void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
     641             :   virtual void ProcessDebugEvent(v8::DebugEvent event,
     642             :                                  Handle<JSObject> event_data,
     643             :                                  Handle<JSObject> exec_state) = 0;
     644             : };
     645             : 
     646             : class JavaScriptDebugDelegate : public LegacyDebugDelegate {
     647             :  public:
     648             :   JavaScriptDebugDelegate(Isolate* isolate, Handle<JSFunction> listener,
     649             :                           Handle<Object> data);
     650             :   virtual ~JavaScriptDebugDelegate();
     651             : 
     652             :  private:
     653             :   void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
     654             :                          Handle<JSObject> exec_state) override;
     655             : 
     656             :   Handle<JSFunction> listener_;
     657             :   Handle<Object> data_;
     658             : };
     659             : 
     660             : class NativeDebugDelegate : public LegacyDebugDelegate {
     661             :  public:
     662             :   NativeDebugDelegate(Isolate* isolate, v8::Debug::EventCallback callback,
     663             :                       Handle<Object> data);
     664             :   virtual ~NativeDebugDelegate();
     665             : 
     666             :  private:
     667             :   // Details of the debug event delivered to the debug event listener.
     668           0 :   class EventDetails : public v8::Debug::EventDetails {
     669             :    public:
     670             :     EventDetails(DebugEvent event, Handle<JSObject> exec_state,
     671             :                  Handle<JSObject> event_data, Handle<Object> callback_data);
     672             :     virtual DebugEvent GetEvent() const;
     673             :     virtual v8::Local<v8::Object> GetExecutionState() const;
     674             :     virtual v8::Local<v8::Object> GetEventData() const;
     675             :     virtual v8::Local<v8::Context> GetEventContext() const;
     676             :     virtual v8::Local<v8::Value> GetCallbackData() const;
     677           0 :     virtual v8::Debug::ClientData* GetClientData() const { return nullptr; }
     678             :     virtual v8::Isolate* GetIsolate() const;
     679             : 
     680             :    private:
     681             :     DebugEvent event_;              // Debug event causing the break.
     682             :     Handle<JSObject> exec_state_;   // Current execution state.
     683             :     Handle<JSObject> event_data_;   // Data associated with the event.
     684             :     Handle<Object> callback_data_;  // User data passed with the callback
     685             :                                     // when it was registered.
     686             :   };
     687             : 
     688             :   void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
     689             :                          Handle<JSObject> exec_state) override;
     690             : 
     691             :   v8::Debug::EventCallback callback_;
     692             :   Handle<Object> data_;
     693             : };
     694             : 
     695             : // This scope is used to load and enter the debug context and create a new
     696             : // break state.  Leaving the scope will restore the previous state.
     697             : // On failure to load, FailedToEnter returns true.
     698             : class DebugScope BASE_EMBEDDED {
     699             :  public:
     700             :   explicit DebugScope(Debug* debug);
     701             :   ~DebugScope();
     702             : 
     703             :   // Check whether loading was successful.
     704        6089 :   inline bool failed() { return failed_; }
     705             : 
     706             :   // Get the active context from before entering the debugger.
     707     5375801 :   inline Handle<Context> GetContext() { return save_.context(); }
     708             : 
     709             :  private:
     710      662570 :   Isolate* isolate() { return debug_->isolate_; }
     711             : 
     712             :   Debug* debug_;
     713             :   DebugScope* prev_;               // Previous scope if entered recursively.
     714             :   StackFrame::Id break_frame_id_;  // Previous break frame id.
     715             :   int break_id_;                   // Previous break id.
     716             :   bool failed_;                    // Did the debug context fail to load?
     717             :   SaveContext save_;               // Saves previous context.
     718             :   PostponeInterruptsScope no_termination_exceptons_;
     719             : };
     720             : 
     721             : // This scope is used to handle return values in nested debug break points.
     722             : // When there are nested debug breaks, we use this to restore the return
     723             : // value to the previous state. This is not merged with DebugScope because
     724             : // return_value_ will not be cleared when we use DebugScope.
     725             : class ReturnValueScope {
     726             :  public:
     727             :   explicit ReturnValueScope(Debug* debug);
     728             :   ~ReturnValueScope();
     729             : 
     730             :  private:
     731             :   Debug* debug_;
     732             :   Handle<Object> return_value_;  // Previous result.
     733             : };
     734             : 
     735             : // Stack allocated class for disabling break.
     736             : class DisableBreak BASE_EMBEDDED {
     737             :  public:
     738             :   explicit DisableBreak(Debug* debug)
     739      394682 :       : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
     740      394682 :     debug_->break_disabled_ = true;
     741             :   }
     742             :   ~DisableBreak() {
     743      394682 :     debug_->break_disabled_ = previous_break_disabled_;
     744             :   }
     745             : 
     746             :  private:
     747             :   Debug* debug_;
     748             :   bool previous_break_disabled_;
     749             :   DISALLOW_COPY_AND_ASSIGN(DisableBreak);
     750             : };
     751             : 
     752             : 
     753             : class SuppressDebug BASE_EMBEDDED {
     754             :  public:
     755             :   explicit SuppressDebug(Debug* debug)
     756      187113 :       : debug_(debug), old_state_(debug->is_suppressed_) {
     757      194083 :     debug_->is_suppressed_ = true;
     758             :   }
     759      194083 :   ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
     760             : 
     761             :  private:
     762             :   Debug* debug_;
     763             :   bool old_state_;
     764             :   DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
     765             : };
     766             : 
     767             : class NoSideEffectScope {
     768             :  public:
     769       61876 :   NoSideEffectScope(Isolate* isolate, bool disallow_side_effects)
     770             :       : isolate_(isolate),
     771       30938 :         old_needs_side_effect_check_(isolate->needs_side_effect_check()) {
     772       15469 :     isolate->set_needs_side_effect_check(old_needs_side_effect_check_ ||
     773             :                                          disallow_side_effects);
     774       15469 :     isolate->debug()->UpdateHookOnFunctionCall();
     775       15469 :     isolate->debug()->side_effect_check_failed_ = false;
     776       15469 :   }
     777             :   ~NoSideEffectScope();
     778             : 
     779             :  private:
     780             :   Isolate* isolate_;
     781             :   bool old_needs_side_effect_check_;
     782             :   DISALLOW_COPY_AND_ASSIGN(NoSideEffectScope);
     783             : };
     784             : 
     785             : // Code generator routines.
     786             : class DebugCodegen : public AllStatic {
     787             :  public:
     788             :   enum DebugBreakCallHelperMode {
     789             :     SAVE_RESULT_REGISTER,
     790             :     IGNORE_RESULT_REGISTER
     791             :   };
     792             : 
     793             :   static void GenerateDebugBreakStub(MacroAssembler* masm,
     794             :                                      DebugBreakCallHelperMode mode);
     795             : 
     796             :   static void GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode);
     797             : 
     798             :   // Builtin to drop frames to restart function.
     799             :   static void GenerateFrameDropperTrampoline(MacroAssembler* masm);
     800             : 
     801             :   // Builtin to atomically (wrt deopts) handle debugger statement and
     802             :   // drop frames to restart function if necessary.
     803             :   static void GenerateHandleDebuggerStatement(MacroAssembler* masm);
     804             : 
     805             :   static void PatchDebugBreakSlot(Isolate* isolate, Address pc,
     806             :                                   Handle<Code> code);
     807             :   static bool DebugBreakSlotIsPatched(Address pc);
     808             :   static void ClearDebugBreakSlot(Isolate* isolate, Address pc);
     809             : };
     810             : 
     811             : 
     812             : }  // namespace internal
     813             : }  // namespace v8
     814             : 
     815             : #endif  // V8_DEBUG_DEBUG_H_

Generated by: LCOV version 1.10