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 180070 : inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
69 : inline bool IsReturnOrSuspend() const {
70 7984 : 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 435313 : 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 470 : 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 BreakIterator {
125 : public:
126 : explicit BreakIterator(Handle<DebugInfo> debug_info);
127 :
128 : BreakLocation GetBreakLocation();
129 148220036 : bool Done() const { return source_position_iterator_.done(); }
130 : void Next();
131 :
132 : void SkipToPosition(int position);
133 : void SkipTo(int count) {
134 11824837 : while (count-- > 0) Next();
135 : }
136 :
137 100621193 : 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 30749 : 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 61048 : : 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 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 : bool IsBlackboxed(Handle<SharedFunctionInfo> shared);
266 :
267 : bool CanBreakAtEntry(Handle<SharedFunctionInfo> shared);
268 :
269 : void SetDebugDelegate(debug::DebugDelegate* delegate);
270 :
271 : // Returns whether the operation succeeded.
272 : bool EnsureBreakInfo(Handle<SharedFunctionInfo> shared);
273 : void CreateBreakInfo(Handle<SharedFunctionInfo> shared);
274 : Handle<DebugInfo> GetOrCreateDebugInfo(Handle<SharedFunctionInfo> shared);
275 :
276 : void InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
277 : Handle<CoverageInfo> coverage_info);
278 : void RemoveAllCoverageInfos();
279 :
280 : // This function is used in FunctionNameUsing* tests.
281 : Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
282 : int position);
283 :
284 : static Handle<Object> GetSourceBreakLocations(
285 : Isolate* isolate, Handle<SharedFunctionInfo> shared);
286 :
287 : // Check whether this frame is just about to return.
288 : bool IsBreakAtReturn(JavaScriptFrame* frame);
289 :
290 : // Support for LiveEdit
291 : void ScheduleFrameRestart(StackFrame* frame);
292 :
293 : bool AllFramesOnStackAreBlackboxed();
294 :
295 : // Set new script source, throw an exception if error occurred. When preview
296 : // is true: try to set source, throw exception if any without actual script
297 : // change. stack_changed is true if after editing script on pause stack is
298 : // changed and client should request stack trace again.
299 : bool SetScriptSource(Handle<Script> script, Handle<String> source,
300 : bool preview, debug::LiveEditResult* result);
301 :
302 : int GetFunctionDebuggingId(Handle<JSFunction> function);
303 :
304 : // Threading support.
305 : char* ArchiveDebug(char* to);
306 : char* RestoreDebug(char* from);
307 : static int ArchiveSpacePerThread();
308 : void FreeThreadResources() { }
309 : void Iterate(RootVisitor* v);
310 11812 : void InitThread(const ExecutionAccess& lock) { ThreadInit(); }
311 :
312 44423 : bool CheckExecutionState() { return is_active(); }
313 :
314 : void StartSideEffectCheckMode();
315 : void StopSideEffectCheckMode();
316 :
317 : void ApplySideEffectChecks(Handle<DebugInfo> debug_info);
318 : void ClearSideEffectChecks(Handle<DebugInfo> debug_info);
319 :
320 : bool PerformSideEffectCheck(Handle<JSFunction> function,
321 : Handle<Object> receiver);
322 :
323 : enum AccessorKind { kNotAccessor, kGetter, kSetter };
324 : bool PerformSideEffectCheckForCallback(Handle<Object> callback_info,
325 : Handle<Object> receiver,
326 : AccessorKind accessor_kind);
327 : bool PerformSideEffectCheckAtBytecode(InterpretedFrame* frame);
328 : bool PerformSideEffectCheckForObject(Handle<Object> object);
329 :
330 : // Flags and states.
331 29072 : inline bool is_active() const { return is_active_; }
332 : inline bool in_debug_scope() const {
333 1929691 : return !!base::Relaxed_Load(&thread_local_.current_debug_scope_);
334 : }
335 538837 : inline bool needs_check_on_function_call() const {
336 538837 : return hook_on_function_call_;
337 : }
338 :
339 7041 : void set_break_points_active(bool v) { break_points_active_ = v; }
340 8493 : bool break_points_active() const { return break_points_active_; }
341 :
342 : StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
343 :
344 : Handle<Object> return_value_handle();
345 66470 : Object return_value() { return thread_local_.return_value_; }
346 133342 : void set_return_value(Object value) { thread_local_.return_value_ = value; }
347 :
348 : // Support for embedding into generated code.
349 : Address is_active_address() {
350 61449 : return reinterpret_cast<Address>(&is_active_);
351 : }
352 :
353 : Address hook_on_function_call_address() {
354 61441 : return reinterpret_cast<Address>(&hook_on_function_call_);
355 : }
356 :
357 : Address suspended_generator_address() {
358 61105 : return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
359 : }
360 :
361 : Address restart_fp_address() {
362 62281 : return reinterpret_cast<Address>(&thread_local_.restart_fp_);
363 : }
364 66666 : bool will_restart() const {
365 66666 : return thread_local_.restart_fp_ != kNullAddress;
366 : }
367 :
368 538837 : StepAction last_step_action() { return thread_local_.last_step_action_; }
369 17452 : bool break_on_next_function_call() const {
370 17452 : return thread_local_.break_on_next_function_call_;
371 : }
372 :
373 : DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
374 :
375 : // For functions in which we cannot set a break point, use a canonical
376 : // source position for break points.
377 : static const int kBreakAtEntryPosition = 0;
378 :
379 : void RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info);
380 :
381 : private:
382 : explicit Debug(Isolate* isolate);
383 : ~Debug();
384 :
385 : void UpdateDebugInfosForExecutionMode();
386 : void UpdateState();
387 : void UpdateHookOnFunctionCall();
388 : void Unload();
389 :
390 : // Return the number of virtual frames below debugger entry.
391 : int CurrentFrameCount();
392 :
393 : inline bool ignore_events() const {
394 7001953 : return is_suppressed_ || !is_active_ ||
395 686834 : isolate_->debug_execution_mode() == DebugInfo::kSideEffects;
396 : }
397 : inline bool break_disabled() const { return break_disabled_; }
398 :
399 : void clear_suspended_generator() {
400 134451 : thread_local_.suspended_generator_ = Smi::kZero;
401 : }
402 :
403 : bool has_suspended_generator() const {
404 : return thread_local_.suspended_generator_ != Smi::kZero;
405 : }
406 :
407 : bool IsExceptionBlackboxed(bool uncaught);
408 :
409 : void OnException(Handle<Object> exception, Handle<Object> promise,
410 : v8::debug::ExceptionType exception_type);
411 :
412 : void ProcessCompileEvent(bool has_compile_error, Handle<Script> script);
413 :
414 : // Find the closest source position for a break point for a given position.
415 : int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position);
416 : // Instrument code to break at break points.
417 : void ApplyBreakPoints(Handle<DebugInfo> debug_info);
418 : // Clear code from instrumentation.
419 : void ClearBreakPoints(Handle<DebugInfo> debug_info);
420 : // Clear all code from instrumentation.
421 : void ClearAllBreakPoints();
422 : // Instrument a function with one-shots.
423 : void FloodWithOneShot(Handle<SharedFunctionInfo> function,
424 : bool returns_only = false);
425 : // Clear all one-shot instrumentations, but restore break points.
426 : void ClearOneShot();
427 :
428 : bool IsFrameBlackboxed(JavaScriptFrame* frame);
429 :
430 : void ActivateStepOut(StackFrame* frame);
431 : MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
432 : BreakLocation* location,
433 : bool* has_break_points = nullptr);
434 : bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
435 : // Check whether a BreakPoint object is hit. Evaluate condition depending
436 : // on whether this is a regular break location or a break at function entry.
437 : bool CheckBreakPoint(Handle<BreakPoint> break_point, bool is_break_at_entry);
438 :
439 : inline void AssertDebugContext() {
440 : DCHECK(in_debug_scope());
441 : }
442 :
443 : void ThreadInit();
444 :
445 : void PrintBreakLocation();
446 :
447 : void ClearAllDebuggerHints();
448 :
449 : // Wraps logic for clearing and maybe freeing all debug infos.
450 : typedef std::function<void(Handle<DebugInfo>)> DebugInfoClearFunction;
451 : void ClearAllDebugInfos(const DebugInfoClearFunction& clear_function);
452 :
453 : void FindDebugInfo(Handle<DebugInfo> debug_info, DebugInfoListNode** prev,
454 : DebugInfoListNode** curr);
455 : void FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node);
456 :
457 : debug::DebugDelegate* debug_delegate_ = nullptr;
458 :
459 : // Debugger is active, i.e. there is a debug event listener attached.
460 : bool is_active_;
461 : // Debugger needs to be notified on every new function call.
462 : // Used for stepping and read-only checks
463 : bool hook_on_function_call_;
464 : // Suppress debug events.
465 : bool is_suppressed_;
466 : // Running liveedit.
467 : bool running_live_edit_ = false;
468 : // Do not trigger debug break events.
469 : bool break_disabled_;
470 : // Do not break on break points.
471 : bool break_points_active_;
472 : // Trigger debug break events for all exceptions.
473 : bool break_on_exception_;
474 : // Trigger debug break events for uncaught exceptions.
475 : bool break_on_uncaught_exception_;
476 : // Termination exception because side effect check has failed.
477 : bool side_effect_check_failed_;
478 :
479 : // List of active debug info objects.
480 : DebugInfoListNode* debug_info_list_;
481 :
482 : // Used for side effect check to mark temporary objects.
483 : class TemporaryObjectsTracker;
484 : std::unique_ptr<TemporaryObjectsTracker> temporary_objects_;
485 :
486 : Handle<RegExpMatchInfo> regexp_match_info_;
487 :
488 : // Used to collect histogram data on debugger feature usage.
489 : DebugFeatureTracker feature_tracker_;
490 :
491 : // Per-thread data.
492 61048 : class ThreadLocal {
493 : public:
494 : // Top debugger entry.
495 : base::AtomicWord current_debug_scope_;
496 :
497 : // Frame id for the frame of the current break.
498 : StackFrame::Id break_frame_id_;
499 :
500 : // Step action for last step performed.
501 : StepAction last_step_action_;
502 :
503 : // If set, next PrepareStepIn will ignore this function until stepped into
504 : // another function, at which point this will be cleared.
505 : Object ignore_step_into_function_;
506 :
507 : // If set then we need to repeat StepOut action at return.
508 : bool fast_forward_to_return_;
509 :
510 : // Source statement position from last step next action.
511 : int last_statement_position_;
512 :
513 : // Frame pointer from last step next or step frame action.
514 : int last_frame_count_;
515 :
516 : // Frame pointer of the target frame we want to arrive at.
517 : int target_frame_count_;
518 :
519 : // Value of the accumulator at the point of entering the debugger.
520 : Object return_value_;
521 :
522 : // The suspended generator object to track when stepping.
523 : Object suspended_generator_;
524 :
525 : // The new frame pointer to drop to when restarting a frame.
526 : Address restart_fp_;
527 :
528 : // Last used inspector breakpoint id.
529 : int last_breakpoint_id_;
530 :
531 : // This flag is true when SetBreakOnNextFunctionCall is called and it forces
532 : // debugger to break on next function call.
533 : bool break_on_next_function_call_;
534 : };
535 :
536 : // Storage location for registers when handling debug break calls
537 : ThreadLocal thread_local_;
538 :
539 : Isolate* isolate_;
540 :
541 : friend class Isolate;
542 : friend class DebugScope;
543 : friend class DisableBreak;
544 : friend class LiveEdit;
545 : friend class SuppressDebug;
546 :
547 : friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
548 : friend void CheckDebuggerUnloaded(); // In test-debug.cc
549 :
550 : DISALLOW_COPY_AND_ASSIGN(Debug);
551 : };
552 :
553 : // This scope is used to load and enter the debug context and create a new
554 : // break state. Leaving the scope will restore the previous state.
555 : class DebugScope {
556 : public:
557 : explicit DebugScope(Debug* debug);
558 : ~DebugScope();
559 :
560 : private:
561 251707 : Isolate* isolate() { return debug_->isolate_; }
562 :
563 : Debug* debug_;
564 : DebugScope* prev_; // Previous scope if entered recursively.
565 : StackFrame::Id break_frame_id_; // Previous break frame id.
566 : PostponeInterruptsScope no_interrupts_;
567 : };
568 :
569 : // This scope is used to handle return values in nested debug break points.
570 : // When there are nested debug breaks, we use this to restore the return
571 : // value to the previous state. This is not merged with DebugScope because
572 : // return_value_ will not be cleared when we use DebugScope.
573 : class ReturnValueScope {
574 : public:
575 : explicit ReturnValueScope(Debug* debug);
576 : ~ReturnValueScope();
577 :
578 : private:
579 : Debug* debug_;
580 : Handle<Object> return_value_; // Previous result.
581 : };
582 :
583 : // Stack allocated class for disabling break.
584 : class DisableBreak {
585 : public:
586 : explicit DisableBreak(Debug* debug, bool disable = true)
587 258085 : : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
588 258085 : debug_->break_disabled_ = disable;
589 : }
590 : ~DisableBreak() {
591 258085 : debug_->break_disabled_ = previous_break_disabled_;
592 : }
593 :
594 : private:
595 : Debug* debug_;
596 : bool previous_break_disabled_;
597 : DISALLOW_COPY_AND_ASSIGN(DisableBreak);
598 : };
599 :
600 : class SuppressDebug {
601 : public:
602 : explicit SuppressDebug(Debug* debug)
603 42732 : : debug_(debug), old_state_(debug->is_suppressed_) {
604 42732 : debug_->is_suppressed_ = true;
605 : }
606 42732 : ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
607 :
608 : private:
609 : Debug* debug_;
610 : bool old_state_;
611 : DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
612 : };
613 :
614 : // Code generator routines.
615 : class DebugCodegen : public AllStatic {
616 : public:
617 : enum DebugBreakCallHelperMode {
618 : SAVE_RESULT_REGISTER,
619 : IGNORE_RESULT_REGISTER
620 : };
621 :
622 : // Builtin to drop frames to restart function.
623 : static void GenerateFrameDropperTrampoline(MacroAssembler* masm);
624 :
625 : // Builtin to atomically (wrt deopts) handle debugger statement and
626 : // drop frames to restart function if necessary.
627 : static void GenerateHandleDebuggerStatement(MacroAssembler* masm);
628 :
629 : // Builtin to trigger a debug break before entering the function.
630 : static void GenerateDebugBreakTrampoline(MacroAssembler* masm);
631 : };
632 :
633 :
634 : } // namespace internal
635 : } // namespace v8
636 :
637 : #endif // V8_DEBUG_DEBUG_H_
|