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