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