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