LCOV - code coverage report
Current view: top level - src/debug - debug.h (source / functions) Hit Total Coverage
Test: app.info Lines: 40 40 100.0 %
Date: 2019-01-20 Functions: 9 9 100.0 %

          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/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/debug/interface-types.h"
      16             : #include "src/execution.h"
      17             : #include "src/flags.h"
      18             : #include "src/frames.h"
      19             : #include "src/globals.h"
      20             : #include "src/heap/factory.h"
      21             : #include "src/objects/debug-objects.h"
      22             : #include "src/runtime/runtime.h"
      23             : #include "src/source-position-table.h"
      24             : #include "src/string-stream.h"
      25             : #include "src/v8threads.h"
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30             : // Forward declarations.
      31             : class DebugScope;
      32             : class JSGeneratorObject;
      33             : 
      34             : // Step actions. NOTE: These values are in macros.py as well.
      35             : enum StepAction : int8_t {
      36             :   StepNone = -1,  // Stepping not prepared.
      37             :   StepOut = 0,    // Step out of the current function.
      38             :   StepNext = 1,   // Step to the next statement in the current function.
      39             :   StepIn = 2,     // Step into new functions invoked or the next statement
      40             :                   // in the current function.
      41             :   LastStepAction = StepIn
      42             : };
      43             : 
      44             : // Type of exception break. NOTE: These values are in macros.py as well.
      45             : enum ExceptionBreakType {
      46             :   BreakException = 0,
      47             :   BreakUncaughtException = 1
      48             : };
      49             : 
      50             : enum DebugBreakType {
      51             :   NOT_DEBUG_BREAK,
      52             :   DEBUGGER_STATEMENT,
      53             :   DEBUG_BREAK_SLOT,
      54             :   DEBUG_BREAK_SLOT_AT_CALL,
      55             :   DEBUG_BREAK_SLOT_AT_RETURN,
      56             :   DEBUG_BREAK_SLOT_AT_SUSPEND,
      57             :   DEBUG_BREAK_AT_ENTRY,
      58             : };
      59             : 
      60             : enum IgnoreBreakMode {
      61             :   kIgnoreIfAllFramesBlackboxed,
      62             :   kIgnoreIfTopFrameBlackboxed
      63             : };
      64             : 
      65             : class BreakLocation {
      66             :  public:
      67             :   static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
      68             :                                  JavaScriptFrame* frame);
      69             : 
      70             :   static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
      71             :                                     JavaScriptFrame* frame,
      72             :                                     std::vector<BreakLocation>* result_out);
      73             : 
      74             :   inline bool IsSuspend() const { return type_ == DEBUG_BREAK_SLOT_AT_SUSPEND; }
      75      180763 :   inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
      76             :   inline bool IsReturnOrSuspend() const {
      77        7969 :     return type_ >= DEBUG_BREAK_SLOT_AT_RETURN;
      78             :   }
      79             :   inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
      80           5 :   inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
      81             :   inline bool IsDebuggerStatement() const {
      82             :     return type_ == DEBUGGER_STATEMENT;
      83             :   }
      84             :   inline bool IsDebugBreakAtEntry() const {
      85             :     bool result = type_ == DEBUG_BREAK_AT_ENTRY;
      86             :     return result;
      87             :   }
      88             : 
      89             :   bool HasBreakPoint(Isolate* isolate, Handle<DebugInfo> debug_info) const;
      90             : 
      91             :   inline int position() const { return position_; }
      92             : 
      93             :   debug::BreakLocationType type() const;
      94             : 
      95             :   JSGeneratorObject GetGeneratorObjectForSuspendedFrame(
      96             :       JavaScriptFrame* frame) const;
      97             : 
      98             :  private:
      99             :   BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
     100             :                 int code_offset, int position, int generator_obj_reg_index)
     101             :       : abstract_code_(abstract_code),
     102             :         code_offset_(code_offset),
     103             :         type_(type),
     104             :         position_(position),
     105      436045 :         generator_obj_reg_index_(generator_obj_reg_index) {
     106             :     DCHECK_NE(NOT_DEBUG_BREAK, type_);
     107             :   }
     108             : 
     109             :   BreakLocation(int position, DebugBreakType type)
     110             :       : code_offset_(0),
     111             :         type_(type),
     112             :         position_(position),
     113         470 :         generator_obj_reg_index_(0) {}
     114             : 
     115             :   static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
     116             :                                       Handle<AbstractCode> abstract_code,
     117             :                                       int offset);
     118             : 
     119             :   void SetDebugBreak();
     120             :   void ClearDebugBreak();
     121             : 
     122             :   Handle<AbstractCode> abstract_code_;
     123             :   int code_offset_;
     124             :   DebugBreakType type_;
     125             :   int position_;
     126             :   int generator_obj_reg_index_;
     127             : 
     128             :   friend class BreakIterator;
     129             : };
     130             : 
     131             : class BreakIterator {
     132             :  public:
     133             :   explicit BreakIterator(Handle<DebugInfo> debug_info);
     134             : 
     135             :   BreakLocation GetBreakLocation();
     136   148735461 :   bool Done() const { return source_position_iterator_.done(); }
     137             :   void Next();
     138             : 
     139             :   void SkipToPosition(int position);
     140             :   void SkipTo(int count) {
     141    11874710 :     while (count-- > 0) Next();
     142             :   }
     143             : 
     144   100924350 :   int code_offset() { return source_position_iterator_.code_offset(); }
     145             :   int break_index() const { return break_index_; }
     146             :   inline int position() const { return position_; }
     147             :   inline int statement_position() const { return statement_position_; }
     148             : 
     149             :   void ClearDebugBreak();
     150             :   void SetDebugBreak();
     151             : 
     152             :  private:
     153             :   int BreakIndexFromPosition(int position);
     154             : 
     155             :   Isolate* isolate();
     156             : 
     157             :   DebugBreakType GetDebugBreakType();
     158             : 
     159             :   Handle<DebugInfo> debug_info_;
     160             :   int break_index_;
     161             :   int position_;
     162             :   int statement_position_;
     163             :   SourcePositionTableIterator source_position_iterator_;
     164             :   DisallowHeapAllocation no_gc_;
     165             : 
     166             :   DISALLOW_COPY_AND_ASSIGN(BreakIterator);
     167             : };
     168             : 
     169             : // Linked list holding debug info objects. The debug info objects are kept as
     170             : // weak handles to avoid a debug info object to keep a function alive.
     171             : class DebugInfoListNode {
     172             :  public:
     173             :   DebugInfoListNode(Isolate* isolate, DebugInfo debug_info);
     174             :   ~DebugInfoListNode();
     175             : 
     176             :   DebugInfoListNode* next() { return next_; }
     177       30939 :   void set_next(DebugInfoListNode* next) { next_ = next; }
     178             :   Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }
     179             : 
     180             :  private:
     181             :   // Global (weak) handle to the debug info object.
     182             :   Address* debug_info_;
     183             : 
     184             :   // Next pointer for linked list.
     185             :   DebugInfoListNode* next_;
     186             : };
     187             : 
     188             : class DebugFeatureTracker {
     189             :  public:
     190             :   enum Feature {
     191             :     kActive = 1,
     192             :     kBreakPoint = 2,
     193             :     kStepping = 3,
     194             :     kHeapSnapshot = 4,
     195             :     kAllocationTracking = 5,
     196             :     kProfiler = 6,
     197             :     kLiveEdit = 7,
     198             :   };
     199             : 
     200             :   explicit DebugFeatureTracker(Isolate* isolate)
     201       62883 :       : isolate_(isolate), bitfield_(0) {}
     202             :   void Track(Feature feature);
     203             : 
     204             :  private:
     205             :   Isolate* isolate_;
     206             :   uint32_t bitfield_;
     207             : };
     208             : 
     209             : 
     210             : // This class contains the debugger support. The main purpose is to handle
     211             : // setting break points in the code.
     212             : //
     213             : // This class controls the debug info for all functions which currently have
     214             : // active breakpoints in them. This debug info is held in the heap root object
     215             : // debug_info which is a FixedArray. Each entry in this list is of class
     216             : // DebugInfo.
     217             : class Debug {
     218             :  public:
     219             :   // Debug event triggers.
     220             :   void OnDebugBreak(Handle<FixedArray> break_points_hit);
     221             : 
     222             :   void OnThrow(Handle<Object> exception);
     223             :   void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
     224             :   void OnCompileError(Handle<Script> script);
     225             :   void OnAfterCompile(Handle<Script> script);
     226             : 
     227             :   void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);
     228             : 
     229             :   // The break target may not be the top-most frame, since we may be
     230             :   // breaking before entering a function that cannot contain break points.
     231             :   void Break(JavaScriptFrame* frame, Handle<JSFunction> break_target);
     232             : 
     233             :   // Scripts handling.
     234             :   Handle<FixedArray> GetLoadedScripts();
     235             : 
     236             :   // Break point handling.
     237             :   bool SetBreakPoint(Handle<JSFunction> function,
     238             :                      Handle<BreakPoint> break_point, int* source_position);
     239             :   void ClearBreakPoint(Handle<BreakPoint> break_point);
     240             :   void ChangeBreakOnException(ExceptionBreakType type, bool enable);
     241             :   bool IsBreakOnException(ExceptionBreakType type);
     242             : 
     243             :   bool SetBreakPointForScript(Handle<Script> script, Handle<String> condition,
     244             :                               int* source_position, int* id);
     245             :   bool SetBreakpointForFunction(Handle<JSFunction> function,
     246             :                                 Handle<String> condition, int* id);
     247             :   void RemoveBreakpoint(int id);
     248             : 
     249             :   // Find breakpoints from the debug info and the break location and check
     250             :   // whether they are hit. Return an empty handle if not, or a FixedArray with
     251             :   // hit BreakPoint objects.
     252             :   MaybeHandle<FixedArray> GetHitBreakPoints(Handle<DebugInfo> debug_info,
     253             :                                             int position);
     254             : 
     255             :   // Stepping handling.
     256             :   void PrepareStep(StepAction step_action);
     257             :   void PrepareStepIn(Handle<JSFunction> function);
     258             :   void PrepareStepInSuspendedGenerator();
     259             :   void PrepareStepOnThrow();
     260             :   void ClearStepping();
     261             : 
     262             :   void SetBreakOnNextFunctionCall();
     263             :   void ClearBreakOnNextFunctionCall();
     264             : 
     265             :   void DeoptimizeFunction(Handle<SharedFunctionInfo> shared);
     266             :   void PrepareFunctionForDebugExecution(Handle<SharedFunctionInfo> shared);
     267             :   void InstallDebugBreakTrampoline();
     268             :   bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
     269             :                               int end_position, bool restrict_to_function,
     270             :                               std::vector<BreakLocation>* locations);
     271             : 
     272             :   bool IsBlackboxed(Handle<SharedFunctionInfo> shared);
     273             : 
     274             :   bool CanBreakAtEntry(Handle<SharedFunctionInfo> shared);
     275             : 
     276             :   void SetDebugDelegate(debug::DebugDelegate* delegate);
     277             : 
     278             :   // Returns whether the operation succeeded.
     279             :   bool EnsureBreakInfo(Handle<SharedFunctionInfo> shared);
     280             :   void CreateBreakInfo(Handle<SharedFunctionInfo> shared);
     281             :   Handle<DebugInfo> GetOrCreateDebugInfo(Handle<SharedFunctionInfo> shared);
     282             : 
     283             :   void InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
     284             :                            Handle<CoverageInfo> coverage_info);
     285             :   void RemoveAllCoverageInfos();
     286             : 
     287             :   // This function is used in FunctionNameUsing* tests.
     288             :   Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
     289             :                                                 int position);
     290             : 
     291             :   static Handle<Object> GetSourceBreakLocations(
     292             :       Isolate* isolate, Handle<SharedFunctionInfo> shared);
     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, debug::LiveEditResult* result);
     308             : 
     309             :   int GetFunctionDebuggingId(Handle<JSFunction> function);
     310             : 
     311             :   // Threading support.
     312             :   char* ArchiveDebug(char* to);
     313             :   char* RestoreDebug(char* from);
     314             :   static int ArchiveSpacePerThread();
     315             :   void FreeThreadResources() { }
     316             :   void Iterate(RootVisitor* v);
     317       11836 :   void InitThread(const ExecutionAccess& lock) { ThreadInit(); }
     318             : 
     319       44519 :   bool CheckExecutionState() { return is_active(); }
     320             : 
     321             :   void StartSideEffectCheckMode();
     322             :   void StopSideEffectCheckMode();
     323             : 
     324             :   void ApplySideEffectChecks(Handle<DebugInfo> debug_info);
     325             :   void ClearSideEffectChecks(Handle<DebugInfo> debug_info);
     326             : 
     327             :   bool PerformSideEffectCheck(Handle<JSFunction> function,
     328             :                               Handle<Object> receiver);
     329             : 
     330             :   enum AccessorKind { kNotAccessor, kGetter, kSetter };
     331             :   bool PerformSideEffectCheckForCallback(Handle<Object> callback_info,
     332             :                                          Handle<Object> receiver,
     333             :                                          AccessorKind accessor_kind);
     334             :   bool PerformSideEffectCheckAtBytecode(InterpretedFrame* frame);
     335             :   bool PerformSideEffectCheckForObject(Handle<Object> object);
     336             : 
     337             :   // Flags and states.
     338       29069 :   inline bool is_active() const { return is_active_; }
     339             :   inline bool in_debug_scope() const {
     340     1937287 :     return !!base::Relaxed_Load(&thread_local_.current_debug_scope_);
     341             :   }
     342      537714 :   inline bool needs_check_on_function_call() const {
     343      537714 :     return hook_on_function_call_;
     344             :   }
     345             : 
     346        7039 :   void set_break_points_active(bool v) { break_points_active_ = v; }
     347        8481 :   bool break_points_active() const { return break_points_active_; }
     348             : 
     349             :   StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
     350             : 
     351             :   Handle<Object> return_value_handle();
     352       66515 :   Object return_value() { return thread_local_.return_value_; }
     353      133432 :   void set_return_value(Object value) { thread_local_.return_value_ = value; }
     354             : 
     355             :   // Support for embedding into generated code.
     356             :   Address is_active_address() {
     357       63285 :     return reinterpret_cast<Address>(&is_active_);
     358             :   }
     359             : 
     360             :   Address hook_on_function_call_address() {
     361       63275 :     return reinterpret_cast<Address>(&hook_on_function_call_);
     362             :   }
     363             : 
     364             :   Address suspended_generator_address() {
     365       62938 :     return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
     366             :   }
     367             : 
     368             :   Address restart_fp_address() {
     369       64114 :     return reinterpret_cast<Address>(&thread_local_.restart_fp_);
     370             :   }
     371       66711 :   bool will_restart() const {
     372       66711 :     return thread_local_.restart_fp_ != kNullAddress;
     373             :   }
     374             : 
     375      537714 :   StepAction last_step_action() { return thread_local_.last_step_action_; }
     376       16456 :   bool break_on_next_function_call() const {
     377       16456 :     return thread_local_.break_on_next_function_call_;
     378             :   }
     379             : 
     380             :   DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
     381             : 
     382             :   // For functions in which we cannot set a break point, use a canonical
     383             :   // source position for break points.
     384             :   static const int kBreakAtEntryPosition = 0;
     385             : 
     386             :   void RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info);
     387             : 
     388             :  private:
     389             :   explicit Debug(Isolate* isolate);
     390             :   ~Debug();
     391             : 
     392             :   void UpdateDebugInfosForExecutionMode();
     393             :   void UpdateState();
     394             :   void UpdateHookOnFunctionCall();
     395             :   void Unload();
     396             : 
     397             :   // Return the number of virtual frames below debugger entry.
     398             :   int CurrentFrameCount();
     399             : 
     400             :   inline bool ignore_events() const {
     401     7016593 :     return is_suppressed_ || !is_active_ ||
     402      685939 :            isolate_->debug_execution_mode() == DebugInfo::kSideEffects;
     403             :   }
     404             :   inline bool break_disabled() const { return break_disabled_; }
     405             : 
     406             :   void clear_suspended_generator() {
     407      136342 :     thread_local_.suspended_generator_ = Smi::kZero;
     408             :   }
     409             : 
     410             :   bool has_suspended_generator() const {
     411             :     return thread_local_.suspended_generator_ != Smi::kZero;
     412             :   }
     413             : 
     414             :   bool IsExceptionBlackboxed(bool uncaught);
     415             : 
     416             :   void OnException(Handle<Object> exception, Handle<Object> promise,
     417             :                    v8::debug::ExceptionType exception_type);
     418             : 
     419             :   void ProcessCompileEvent(bool has_compile_error, Handle<Script> script);
     420             : 
     421             :   // Find the closest source position for a break point for a given position.
     422             :   int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position);
     423             :   // Instrument code to break at break points.
     424             :   void ApplyBreakPoints(Handle<DebugInfo> debug_info);
     425             :   // Clear code from instrumentation.
     426             :   void ClearBreakPoints(Handle<DebugInfo> debug_info);
     427             :   // Clear all code from instrumentation.
     428             :   void ClearAllBreakPoints();
     429             :   // Instrument a function with one-shots.
     430             :   void FloodWithOneShot(Handle<SharedFunctionInfo> function,
     431             :                         bool returns_only = false);
     432             :   // Clear all one-shot instrumentations, but restore break points.
     433             :   void ClearOneShot();
     434             : 
     435             :   bool IsFrameBlackboxed(JavaScriptFrame* frame);
     436             : 
     437             :   void ActivateStepOut(StackFrame* frame);
     438             :   MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
     439             :                                            BreakLocation* location,
     440             :                                            bool* has_break_points = nullptr);
     441             :   bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
     442             :   // Check whether a BreakPoint object is hit. Evaluate condition depending
     443             :   // on whether this is a regular break location or a break at function entry.
     444             :   bool CheckBreakPoint(Handle<BreakPoint> break_point, bool is_break_at_entry);
     445             : 
     446             :   inline void AssertDebugContext() {
     447             :     DCHECK(in_debug_scope());
     448             :   }
     449             : 
     450             :   void ThreadInit();
     451             : 
     452             :   void PrintBreakLocation();
     453             : 
     454             :   void ClearAllDebuggerHints();
     455             : 
     456             :   // Wraps logic for clearing and maybe freeing all debug infos.
     457             :   typedef std::function<void(Handle<DebugInfo>)> DebugInfoClearFunction;
     458             :   void ClearAllDebugInfos(const DebugInfoClearFunction& clear_function);
     459             : 
     460             :   void FindDebugInfo(Handle<DebugInfo> debug_info, DebugInfoListNode** prev,
     461             :                      DebugInfoListNode** curr);
     462             :   void FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node);
     463             : 
     464             :   debug::DebugDelegate* debug_delegate_ = nullptr;
     465             : 
     466             :   // Debugger is active, i.e. there is a debug event listener attached.
     467             :   bool is_active_;
     468             :   // Debugger needs to be notified on every new function call.
     469             :   // Used for stepping and read-only checks
     470             :   bool hook_on_function_call_;
     471             :   // Suppress debug events.
     472             :   bool is_suppressed_;
     473             :   // Running liveedit.
     474             :   bool running_live_edit_ = false;
     475             :   // Do not trigger debug break events.
     476             :   bool break_disabled_;
     477             :   // Do not break on break points.
     478             :   bool break_points_active_;
     479             :   // Trigger debug break events for all exceptions.
     480             :   bool break_on_exception_;
     481             :   // Trigger debug break events for uncaught exceptions.
     482             :   bool break_on_uncaught_exception_;
     483             :   // Termination exception because side effect check has failed.
     484             :   bool side_effect_check_failed_;
     485             : 
     486             :   // List of active debug info objects.
     487             :   DebugInfoListNode* debug_info_list_;
     488             : 
     489             :   // Used for side effect check to mark temporary objects.
     490             :   class TemporaryObjectsTracker;
     491             :   std::unique_ptr<TemporaryObjectsTracker> temporary_objects_;
     492             : 
     493             :   Handle<RegExpMatchInfo> regexp_match_info_;
     494             : 
     495             :   // Used to collect histogram data on debugger feature usage.
     496             :   DebugFeatureTracker feature_tracker_;
     497             : 
     498             :   // Per-thread data.
     499       62883 :   class ThreadLocal {
     500             :    public:
     501             :     // Top debugger entry.
     502             :     base::AtomicWord current_debug_scope_;
     503             : 
     504             :     // Frame id for the frame of the current break.
     505             :     StackFrame::Id break_frame_id_;
     506             : 
     507             :     // Step action for last step performed.
     508             :     StepAction last_step_action_;
     509             : 
     510             :     // If set, next PrepareStepIn will ignore this function until stepped into
     511             :     // another function, at which point this will be cleared.
     512             :     Object ignore_step_into_function_;
     513             : 
     514             :     // If set then we need to repeat StepOut action at return.
     515             :     bool fast_forward_to_return_;
     516             : 
     517             :     // Source statement position from last step next action.
     518             :     int last_statement_position_;
     519             : 
     520             :     // Frame pointer from last step next or step frame action.
     521             :     int last_frame_count_;
     522             : 
     523             :     // Frame pointer of the target frame we want to arrive at.
     524             :     int target_frame_count_;
     525             : 
     526             :     // Value of the accumulator at the point of entering the debugger.
     527             :     Object return_value_;
     528             : 
     529             :     // The suspended generator object to track when stepping.
     530             :     Object suspended_generator_;
     531             : 
     532             :     // The new frame pointer to drop to when restarting a frame.
     533             :     Address restart_fp_;
     534             : 
     535             :     // Last used inspector breakpoint id.
     536             :     int last_breakpoint_id_;
     537             : 
     538             :     // This flag is true when SetBreakOnNextFunctionCall is called and it forces
     539             :     // debugger to break on next function call.
     540             :     bool break_on_next_function_call_;
     541             :   };
     542             : 
     543             :   // Storage location for registers when handling debug break calls
     544             :   ThreadLocal thread_local_;
     545             : 
     546             :   Isolate* isolate_;
     547             : 
     548             :   friend class Isolate;
     549             :   friend class DebugScope;
     550             :   friend class DisableBreak;
     551             :   friend class LiveEdit;
     552             :   friend class SuppressDebug;
     553             : 
     554             :   friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
     555             :   friend void CheckDebuggerUnloaded();               // In test-debug.cc
     556             : 
     557             :   DISALLOW_COPY_AND_ASSIGN(Debug);
     558             : };
     559             : 
     560             : // This scope is used to load and enter the debug context and create a new
     561             : // break state.  Leaving the scope will restore the previous state.
     562             : class DebugScope {
     563             :  public:
     564             :   explicit DebugScope(Debug* debug);
     565             :   ~DebugScope();
     566             : 
     567             :  private:
     568      252806 :   Isolate* isolate() { return debug_->isolate_; }
     569             : 
     570             :   Debug* debug_;
     571             :   DebugScope* prev_;               // Previous scope if entered recursively.
     572             :   StackFrame::Id break_frame_id_;  // Previous break frame id.
     573             :   PostponeInterruptsScope no_interrupts_;
     574             : };
     575             : 
     576             : // This scope is used to handle return values in nested debug break points.
     577             : // When there are nested debug breaks, we use this to restore the return
     578             : // value to the previous state. This is not merged with DebugScope because
     579             : // return_value_ will not be cleared when we use DebugScope.
     580             : class ReturnValueScope {
     581             :  public:
     582             :   explicit ReturnValueScope(Debug* debug);
     583             :   ~ReturnValueScope();
     584             : 
     585             :  private:
     586             :   Debug* debug_;
     587             :   Handle<Object> return_value_;  // Previous result.
     588             : };
     589             : 
     590             : // Stack allocated class for disabling break.
     591             : class DisableBreak {
     592             :  public:
     593             :   explicit DisableBreak(Debug* debug, bool disable = true)
     594      258374 :       : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
     595      258374 :     debug_->break_disabled_ = disable;
     596             :   }
     597             :   ~DisableBreak() {
     598      258374 :     debug_->break_disabled_ = previous_break_disabled_;
     599             :   }
     600             : 
     601             :  private:
     602             :   Debug* debug_;
     603             :   bool previous_break_disabled_;
     604             :   DISALLOW_COPY_AND_ASSIGN(DisableBreak);
     605             : };
     606             : 
     607             : class SuppressDebug {
     608             :  public:
     609             :   explicit SuppressDebug(Debug* debug)
     610       42768 :       : debug_(debug), old_state_(debug->is_suppressed_) {
     611       42768 :     debug_->is_suppressed_ = true;
     612             :   }
     613       42768 :   ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
     614             : 
     615             :  private:
     616             :   Debug* debug_;
     617             :   bool old_state_;
     618             :   DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
     619             : };
     620             : 
     621             : // Code generator routines.
     622             : class DebugCodegen : public AllStatic {
     623             :  public:
     624             :   enum DebugBreakCallHelperMode {
     625             :     SAVE_RESULT_REGISTER,
     626             :     IGNORE_RESULT_REGISTER
     627             :   };
     628             : 
     629             :   // Builtin to drop frames to restart function.
     630             :   static void GenerateFrameDropperTrampoline(MacroAssembler* masm);
     631             : 
     632             :   // Builtin to atomically (wrt deopts) handle debugger statement and
     633             :   // drop frames to restart function if necessary.
     634             :   static void GenerateHandleDebuggerStatement(MacroAssembler* masm);
     635             : 
     636             :   // Builtin to trigger a debug break before entering the function.
     637             :   static void GenerateDebugBreakTrampoline(MacroAssembler* masm);
     638             : };
     639             : 
     640             : 
     641             : }  // namespace internal
     642             : }  // namespace v8
     643             : 
     644             : #endif  // V8_DEBUG_DEBUG_H_

Generated by: LCOV version 1.10