LCOV - code coverage report
Current view: top level - src/debug - debug.h (source / functions) Hit Total Coverage
Test: app.info Lines: 52 54 96.3 %
Date: 2017-10-20 Functions: 19 26 73.1 %

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

Generated by: LCOV version 1.10