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 "src/allocation.h"
9 : #include "src/assembler.h"
10 : #include "src/base/atomicops.h"
11 : #include "src/base/hashmap.h"
12 : #include "src/base/platform/platform.h"
13 : #include "src/debug/debug-interface.h"
14 : #include "src/debug/interface-types.h"
15 : #include "src/execution.h"
16 : #include "src/factory.h"
17 : #include "src/flags.h"
18 : #include "src/frames.h"
19 : #include "src/globals.h"
20 : #include "src/runtime/runtime.h"
21 : #include "src/source-position-table.h"
22 : #include "src/string-stream.h"
23 : #include "src/v8threads.h"
24 :
25 : #include "include/v8-debug.h"
26 :
27 : namespace v8 {
28 : namespace internal {
29 :
30 :
31 : // Forward declarations.
32 : class DebugScope;
33 :
34 :
35 : // Step actions. NOTE: These values are in macros.py as well.
36 : enum StepAction : int8_t {
37 : StepNone = -1, // Stepping not prepared.
38 : StepOut = 0, // Step out of the current function.
39 : StepNext = 1, // Step to the next statement in the current function.
40 : StepIn = 2, // Step into new functions invoked or the next statement
41 : // in the current function.
42 : LastStepAction = StepIn
43 : };
44 :
45 : // Type of exception break. NOTE: These values are in macros.py as well.
46 : enum ExceptionBreakType {
47 : BreakException = 0,
48 : BreakUncaughtException = 1
49 : };
50 :
51 :
52 : // The different types of breakpoint position alignments.
53 : // Must match Debug.BreakPositionAlignment in debug.js
54 : enum BreakPositionAlignment {
55 : STATEMENT_ALIGNED = 0,
56 : BREAK_POSITION_ALIGNED = 1
57 : };
58 :
59 : enum DebugBreakType {
60 : NOT_DEBUG_BREAK,
61 : DEBUGGER_STATEMENT,
62 : DEBUG_BREAK_SLOT,
63 : DEBUG_BREAK_SLOT_AT_CALL,
64 : DEBUG_BREAK_SLOT_AT_RETURN,
65 : DEBUG_BREAK_SLOT_AT_TAIL_CALL,
66 : };
67 :
68 : enum IgnoreBreakMode {
69 : kIgnoreIfAllFramesBlackboxed,
70 : kIgnoreIfTopFrameBlackboxed
71 : };
72 :
73 : class BreakLocation {
74 : public:
75 : static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
76 : JavaScriptFrame* frame);
77 :
78 : static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
79 : JavaScriptFrame* frame,
80 : List<BreakLocation>* result_out);
81 :
82 116702 : inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
83 : inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
84 : inline bool IsTailCall() const {
85 13398 : return type_ == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
86 : }
87 : inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
88 : inline bool IsDebuggerStatement() const {
89 : return type_ == DEBUGGER_STATEMENT;
90 : }
91 :
92 : bool HasBreakPoint(Handle<DebugInfo> debug_info) const;
93 :
94 : inline int position() const { return position_; }
95 :
96 : debug::BreakLocationType type() const;
97 :
98 : private:
99 : BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
100 : int code_offset, int position)
101 : : abstract_code_(abstract_code),
102 : code_offset_(code_offset),
103 : type_(type),
104 390986 : position_(position) {
105 : DCHECK_NE(NOT_DEBUG_BREAK, type_);
106 : }
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 :
120 : friend class CodeBreakIterator;
121 : friend class BytecodeArrayBreakIterator;
122 : };
123 :
124 : class BreakIterator {
125 : public:
126 : static std::unique_ptr<BreakIterator> GetIterator(
127 : Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code);
128 :
129 1053942 : virtual ~BreakIterator() {}
130 :
131 : virtual BreakLocation GetBreakLocation() = 0;
132 : virtual bool Done() const = 0;
133 : virtual void Next() = 0;
134 :
135 : void SkipTo(int count) {
136 13949858 : while (count-- > 0) Next();
137 : }
138 :
139 : virtual int code_offset() = 0;
140 : int break_index() const { return break_index_; }
141 : inline int position() const { return position_; }
142 : inline int statement_position() const { return statement_position_; }
143 :
144 : virtual bool IsDebugBreak() = 0;
145 : virtual void ClearDebugBreak() = 0;
146 : virtual void SetDebugBreak() = 0;
147 :
148 : protected:
149 : explicit BreakIterator(Handle<DebugInfo> debug_info);
150 :
151 : int BreakIndexFromPosition(int position, BreakPositionAlignment alignment);
152 :
153 : Isolate* isolate() { return debug_info_->GetIsolate(); }
154 :
155 : Handle<DebugInfo> debug_info_;
156 : int break_index_;
157 : int position_;
158 : int statement_position_;
159 :
160 : private:
161 : DisallowHeapAllocation no_gc_;
162 : DISALLOW_COPY_AND_ASSIGN(BreakIterator);
163 : };
164 :
165 : class CodeBreakIterator : public BreakIterator {
166 : public:
167 : explicit CodeBreakIterator(Handle<DebugInfo> debug_info);
168 610439 : ~CodeBreakIterator() override {}
169 :
170 : BreakLocation GetBreakLocation() override;
171 38049174 : bool Done() const override { return reloc_iterator_.done(); }
172 : void Next() override;
173 :
174 : bool IsDebugBreak() override;
175 : void ClearDebugBreak() override;
176 : void SetDebugBreak() override;
177 :
178 : void SkipToPosition(int position, BreakPositionAlignment alignment);
179 :
180 40797937 : int code_offset() override {
181 81599152 : return static_cast<int>(rinfo()->pc() -
182 81599152 : debug_info_->DebugCode()->instruction_start());
183 : }
184 :
185 : private:
186 : int GetModeMask();
187 : DebugBreakType GetDebugBreakType();
188 :
189 2308338 : RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
190 : RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
191 :
192 : RelocIterator reloc_iterator_;
193 : SourcePositionTableIterator source_position_iterator_;
194 : DISALLOW_COPY_AND_ASSIGN(CodeBreakIterator);
195 : };
196 :
197 : class BytecodeArrayBreakIterator : public BreakIterator {
198 : public:
199 : explicit BytecodeArrayBreakIterator(Handle<DebugInfo> debug_info);
200 1215023 : ~BytecodeArrayBreakIterator() override {}
201 :
202 : BreakLocation GetBreakLocation() override;
203 249673157 : bool Done() const override { return source_position_iterator_.done(); }
204 : void Next() override;
205 :
206 : bool IsDebugBreak() override;
207 : void ClearDebugBreak() override;
208 : void SetDebugBreak() override;
209 :
210 : void SkipToPosition(int position, BreakPositionAlignment alignment);
211 :
212 125513651 : int code_offset() override { return source_position_iterator_.code_offset(); }
213 :
214 : private:
215 : DebugBreakType GetDebugBreakType();
216 :
217 : SourcePositionTableIterator source_position_iterator_;
218 : DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBreakIterator);
219 : };
220 :
221 : // Linked list holding debug info objects. The debug info objects are kept as
222 : // weak handles to avoid a debug info object to keep a function alive.
223 : class DebugInfoListNode {
224 : public:
225 : explicit DebugInfoListNode(DebugInfo* debug_info);
226 : ~DebugInfoListNode();
227 :
228 : DebugInfoListNode* next() { return next_; }
229 12351 : void set_next(DebugInfoListNode* next) { next_ = next; }
230 : Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }
231 :
232 : private:
233 : // Global (weak) handle to the debug info object.
234 : DebugInfo** debug_info_;
235 :
236 : // Next pointer for linked list.
237 : DebugInfoListNode* next_;
238 : };
239 :
240 : class DebugFeatureTracker {
241 : public:
242 : enum Feature {
243 : kActive = 1,
244 : kBreakPoint = 2,
245 : kStepping = 3,
246 : kHeapSnapshot = 4,
247 : kAllocationTracking = 5,
248 : kProfiler = 6,
249 : kLiveEdit = 7,
250 : };
251 :
252 : explicit DebugFeatureTracker(Isolate* isolate)
253 60782 : : isolate_(isolate), bitfield_(0) {}
254 : void Track(Feature feature);
255 :
256 : private:
257 : Isolate* isolate_;
258 : uint32_t bitfield_;
259 : };
260 :
261 :
262 : // This class contains the debugger support. The main purpose is to handle
263 : // setting break points in the code.
264 : //
265 : // This class controls the debug info for all functions which currently have
266 : // active breakpoints in them. This debug info is held in the heap root object
267 : // debug_info which is a FixedArray. Each entry in this list is of class
268 : // DebugInfo.
269 : class Debug {
270 : public:
271 : // Debug event triggers.
272 : void OnDebugBreak(Handle<Object> break_points_hit);
273 :
274 : void OnThrow(Handle<Object> exception);
275 : void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
276 : void OnCompileError(Handle<Script> script);
277 : void OnAfterCompile(Handle<Script> script);
278 : void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
279 : int parent_id);
280 :
281 : MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
282 : Handle<Object> data);
283 : Handle<Context> GetDebugContext();
284 : void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);
285 :
286 : // Internal logic
287 : bool Load();
288 : void Break(JavaScriptFrame* frame);
289 :
290 : // Scripts handling.
291 : Handle<FixedArray> GetLoadedScripts();
292 :
293 : // Break point handling.
294 : bool SetBreakPoint(Handle<JSFunction> function,
295 : Handle<Object> break_point_object,
296 : int* source_position);
297 : bool SetBreakPointForScript(Handle<Script> script,
298 : Handle<Object> break_point_object,
299 : int* source_position,
300 : BreakPositionAlignment alignment);
301 : void ClearBreakPoint(Handle<Object> break_point_object);
302 : void ChangeBreakOnException(ExceptionBreakType type, bool enable);
303 : bool IsBreakOnException(ExceptionBreakType type);
304 :
305 : // The parameter is either a BreakPointInfo object, or a FixedArray of
306 : // BreakPointInfo objects.
307 : // Returns an empty handle if no breakpoint is hit, or a FixedArray with all
308 : // hit breakpoints.
309 : MaybeHandle<FixedArray> GetHitBreakPointObjects(
310 : Handle<Object> break_point_objects);
311 :
312 : // Stepping handling.
313 : void PrepareStep(StepAction step_action);
314 : void PrepareStepIn(Handle<JSFunction> function);
315 : void PrepareStepInSuspendedGenerator();
316 : void PrepareStepOnThrow();
317 : void ClearStepping();
318 : void ClearStepOut();
319 :
320 : bool PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
321 : bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
322 : int end_position, bool restrict_to_function,
323 : std::vector<BreakLocation>* locations);
324 :
325 : void RecordGenerator(Handle<JSGeneratorObject> generator_object);
326 :
327 : void RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
328 : Handle<Object> parent);
329 :
330 : int NextAsyncTaskId(Handle<JSObject> promise);
331 :
332 : bool IsBlackboxed(Handle<SharedFunctionInfo> shared);
333 :
334 : void SetDebugDelegate(debug::DebugDelegate* delegate, bool pass_ownership);
335 :
336 : // Returns whether the operation succeeded.
337 : bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
338 : void CreateDebugInfo(Handle<SharedFunctionInfo> shared);
339 : static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
340 :
341 : template <typename C>
342 : bool CompileToRevealInnerFunctions(C* compilable);
343 :
344 : // This function is used in FunctionNameUsing* tests.
345 : Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
346 : int position);
347 :
348 : static Handle<Object> GetSourceBreakLocations(
349 : Handle<SharedFunctionInfo> shared,
350 : BreakPositionAlignment position_aligment);
351 :
352 : // Check whether a global object is the debug global object.
353 : bool IsDebugGlobal(JSGlobalObject* global);
354 :
355 : // Check whether this frame is just about to return.
356 : bool IsBreakAtReturn(JavaScriptFrame* frame);
357 :
358 : // Support for LiveEdit
359 : void ScheduleFrameRestart(StackFrame* frame);
360 :
361 : bool AllFramesOnStackAreBlackboxed();
362 :
363 : // Threading support.
364 : char* ArchiveDebug(char* to);
365 : char* RestoreDebug(char* from);
366 : static int ArchiveSpacePerThread();
367 : void FreeThreadResources() { }
368 : void Iterate(RootVisitor* v);
369 :
370 12815742 : bool CheckExecutionState(int id) {
371 12815742 : return CheckExecutionState() && break_id() == id;
372 : }
373 :
374 12941522 : bool CheckExecutionState() {
375 12941522 : return is_active() && !debug_context().is_null() && break_id() != 0;
376 : }
377 :
378 : bool PerformSideEffectCheck(Handle<JSFunction> function);
379 : bool PerformSideEffectCheckForCallback(Address function);
380 :
381 : // Flags and states.
382 5375801 : DebugScope* debugger_entry() {
383 : return reinterpret_cast<DebugScope*>(
384 11641878 : base::NoBarrier_Load(&thread_local_.current_debug_scope_));
385 : }
386 229547 : inline Handle<Context> debug_context() { return debug_context_; }
387 :
388 4146 : void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
389 13998 : bool live_edit_enabled() const {
390 13998 : return FLAG_enable_liveedit && live_edit_enabled_;
391 : }
392 :
393 44765 : inline bool is_active() const { return is_active_; }
394 : inline bool is_loaded() const { return !debug_context_.is_null(); }
395 5376029 : inline bool in_debug_scope() const {
396 13695331 : return !!base::NoBarrier_Load(&thread_local_.current_debug_scope_);
397 : }
398 4519 : void set_break_points_active(bool v) { break_points_active_ = v; }
399 12034 : bool break_points_active() const { return break_points_active_; }
400 :
401 692965 : StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
402 : int break_id() { return thread_local_.break_id_; }
403 :
404 90822 : Handle<Object> return_value_handle() {
405 181644 : return handle(thread_local_.return_value_, isolate_);
406 : }
407 35553 : Object* return_value() { return thread_local_.return_value_; }
408 181644 : void set_return_value(Object* value) { thread_local_.return_value_ = value; }
409 :
410 : // Support for embedding into generated code.
411 : Address is_active_address() {
412 : return reinterpret_cast<Address>(&is_active_);
413 : }
414 :
415 : Address hook_on_function_call_address() {
416 : return reinterpret_cast<Address>(&hook_on_function_call_);
417 : }
418 :
419 : Address last_step_action_address() {
420 : return reinterpret_cast<Address>(&thread_local_.last_step_action_);
421 : }
422 :
423 : Address suspended_generator_address() {
424 : return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
425 : }
426 :
427 : Address restart_fp_address() {
428 : return reinterpret_cast<Address>(&thread_local_.restart_fp_);
429 : }
430 :
431 1377910 : StepAction last_step_action() { return thread_local_.last_step_action_; }
432 :
433 802 : DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }
434 :
435 : private:
436 : explicit Debug(Isolate* isolate);
437 : ~Debug() { DCHECK_NULL(debug_delegate_); }
438 :
439 : void UpdateState();
440 : void UpdateHookOnFunctionCall();
441 : void RemoveDebugDelegate();
442 : void Unload();
443 : void SetNextBreakId() {
444 332085 : thread_local_.break_id_ = ++thread_local_.break_count_;
445 : }
446 :
447 : // Return the number of virtual frames below debugger entry.
448 : int CurrentFrameCount();
449 :
450 : inline bool ignore_events() const {
451 9085130 : return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check();
452 : }
453 : inline bool break_disabled() const { return break_disabled_; }
454 :
455 : void clear_suspended_generator() {
456 195603 : thread_local_.suspended_generator_ = Smi::kZero;
457 : }
458 :
459 : bool has_suspended_generator() const {
460 : return thread_local_.suspended_generator_ != Smi::kZero;
461 : }
462 :
463 : bool IsExceptionBlackboxed(bool uncaught);
464 :
465 : void OnException(Handle<Object> exception, Handle<Object> promise);
466 :
467 : // Constructors for debug event objects.
468 : MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
469 : MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
470 : Handle<Object> break_points_hit);
471 : MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
472 : Handle<Object> exception,
473 : bool uncaught,
474 : Handle<Object> promise);
475 : MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
476 : Handle<Script> script, v8::DebugEvent type);
477 : MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(
478 : v8::debug::PromiseDebugActionType type, int id);
479 :
480 : void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
481 : void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
482 :
483 : // Find the closest source position for a break point for a given position.
484 : int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position,
485 : BreakPositionAlignment alignment);
486 : // Instrument code to break at break points.
487 : void ApplyBreakPoints(Handle<DebugInfo> debug_info);
488 : // Clear code from instrumentation.
489 : void ClearBreakPoints(Handle<DebugInfo> debug_info);
490 : // Clear all code from instrumentation.
491 : void ClearAllBreakPoints();
492 : // Instrument a function with one-shots.
493 : void FloodWithOneShot(Handle<SharedFunctionInfo> function,
494 : bool returns_only = false);
495 : // Clear all one-shot instrumentations, but restore break points.
496 : void ClearOneShot();
497 :
498 : bool IsFrameBlackboxed(JavaScriptFrame* frame);
499 :
500 : void ActivateStepOut(StackFrame* frame);
501 : void RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info);
502 : MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
503 : BreakLocation* location,
504 : bool* has_break_points = nullptr);
505 : bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
506 : bool CheckBreakPoint(Handle<Object> break_point_object);
507 : MaybeHandle<Object> CallFunction(const char* name, int argc,
508 : Handle<Object> args[]);
509 :
510 : inline void AssertDebugContext() {
511 : DCHECK(isolate_->context() == *debug_context());
512 : DCHECK(in_debug_scope());
513 : }
514 :
515 : void ThreadInit();
516 :
517 : void PrintBreakLocation();
518 :
519 : // Global handles.
520 : Handle<Context> debug_context_;
521 :
522 : debug::DebugDelegate* debug_delegate_ = nullptr;
523 : bool owns_debug_delegate_ = false;
524 :
525 : // Debugger is active, i.e. there is a debug event listener attached.
526 : bool is_active_;
527 : // Debugger needs to be notified on every new function call.
528 : // Used for stepping and read-only checks
529 : bool hook_on_function_call_;
530 : // Suppress debug events.
531 : bool is_suppressed_;
532 : // LiveEdit is enabled.
533 : bool live_edit_enabled_;
534 : // Do not trigger debug break events.
535 : bool break_disabled_;
536 : // Do not break on break points.
537 : bool break_points_active_;
538 : // Trigger debug break events for all exceptions.
539 : bool break_on_exception_;
540 : // Trigger debug break events for uncaught exceptions.
541 : bool break_on_uncaught_exception_;
542 : // Termination exception because side effect check has failed.
543 : bool side_effect_check_failed_;
544 :
545 : // List of active debug info objects.
546 : DebugInfoListNode* debug_info_list_;
547 :
548 : // Used to collect histogram data on debugger feature usage.
549 : DebugFeatureTracker feature_tracker_;
550 :
551 : // Per-thread data.
552 : class ThreadLocal {
553 : public:
554 : // Top debugger entry.
555 : base::AtomicWord current_debug_scope_;
556 :
557 : // Counter for generating next break id.
558 : int break_count_;
559 :
560 : // Current break id.
561 : int break_id_;
562 :
563 : // Frame id for the frame of the current break.
564 : StackFrame::Id break_frame_id_;
565 :
566 : // Step action for last step performed.
567 : StepAction last_step_action_;
568 :
569 : // If set, next PrepareStepIn will ignore this function until stepped into
570 : // another function, at which point this will be cleared.
571 : Object* ignore_step_into_function_;
572 :
573 : // If set then we need to repeat StepOut action at return.
574 : bool fast_forward_to_return_;
575 :
576 : // Source statement position from last step next action.
577 : int last_statement_position_;
578 :
579 : // Frame pointer from last step next or step frame action.
580 : int last_frame_count_;
581 :
582 : // Frame pointer of the target frame we want to arrive at.
583 : int target_frame_count_;
584 :
585 : // Value of the accumulator at the point of entering the debugger.
586 : Object* return_value_;
587 :
588 : // The suspended generator object to track when stepping.
589 : Object* suspended_generator_;
590 :
591 : // The new frame pointer to drop to when restarting a frame.
592 : Address restart_fp_;
593 :
594 : int async_task_count_;
595 : };
596 :
597 : // Storage location for registers when handling debug break calls
598 : ThreadLocal thread_local_;
599 :
600 : Isolate* isolate_;
601 :
602 : friend class Isolate;
603 : friend class DebugScope;
604 : friend class DisableBreak;
605 : friend class LiveEdit;
606 : friend class SuppressDebug;
607 : friend class NoSideEffectScope;
608 : friend class LegacyDebugDelegate;
609 :
610 : friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
611 : friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
612 :
613 : DISALLOW_COPY_AND_ASSIGN(Debug);
614 : };
615 :
616 753 : class LegacyDebugDelegate : public v8::debug::DebugDelegate {
617 : public:
618 753 : explicit LegacyDebugDelegate(Isolate* isolate) : isolate_(isolate) {}
619 : void PromiseEventOccurred(v8::debug::PromiseDebugActionType type, int id,
620 : int parent_id, bool created_by_user) override;
621 : void ScriptCompiled(v8::Local<v8::debug::Script> script,
622 : bool has_compile_error) override;
623 : void BreakProgramRequested(v8::Local<v8::Context> paused_context,
624 : v8::Local<v8::Object> exec_state,
625 : v8::Local<v8::Value> break_points_hit) override;
626 : void ExceptionThrown(v8::Local<v8::Context> paused_context,
627 : v8::Local<v8::Object> exec_state,
628 : v8::Local<v8::Value> exception,
629 : v8::Local<v8::Value> promise, bool is_uncaught) override;
630 3066 : bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
631 : const v8::debug::Location& start,
632 : const v8::debug::Location& end) override {
633 3066 : return false;
634 : }
635 :
636 : protected:
637 : Isolate* isolate_;
638 :
639 : private:
640 : void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
641 : virtual void ProcessDebugEvent(v8::DebugEvent event,
642 : Handle<JSObject> event_data,
643 : Handle<JSObject> exec_state) = 0;
644 : };
645 :
646 : class JavaScriptDebugDelegate : public LegacyDebugDelegate {
647 : public:
648 : JavaScriptDebugDelegate(Isolate* isolate, Handle<JSFunction> listener,
649 : Handle<Object> data);
650 : virtual ~JavaScriptDebugDelegate();
651 :
652 : private:
653 : void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
654 : Handle<JSObject> exec_state) override;
655 :
656 : Handle<JSFunction> listener_;
657 : Handle<Object> data_;
658 : };
659 :
660 : class NativeDebugDelegate : public LegacyDebugDelegate {
661 : public:
662 : NativeDebugDelegate(Isolate* isolate, v8::Debug::EventCallback callback,
663 : Handle<Object> data);
664 : virtual ~NativeDebugDelegate();
665 :
666 : private:
667 : // Details of the debug event delivered to the debug event listener.
668 0 : class EventDetails : public v8::Debug::EventDetails {
669 : public:
670 : EventDetails(DebugEvent event, Handle<JSObject> exec_state,
671 : Handle<JSObject> event_data, Handle<Object> callback_data);
672 : virtual DebugEvent GetEvent() const;
673 : virtual v8::Local<v8::Object> GetExecutionState() const;
674 : virtual v8::Local<v8::Object> GetEventData() const;
675 : virtual v8::Local<v8::Context> GetEventContext() const;
676 : virtual v8::Local<v8::Value> GetCallbackData() const;
677 0 : virtual v8::Debug::ClientData* GetClientData() const { return nullptr; }
678 : virtual v8::Isolate* GetIsolate() const;
679 :
680 : private:
681 : DebugEvent event_; // Debug event causing the break.
682 : Handle<JSObject> exec_state_; // Current execution state.
683 : Handle<JSObject> event_data_; // Data associated with the event.
684 : Handle<Object> callback_data_; // User data passed with the callback
685 : // when it was registered.
686 : };
687 :
688 : void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
689 : Handle<JSObject> exec_state) override;
690 :
691 : v8::Debug::EventCallback callback_;
692 : Handle<Object> data_;
693 : };
694 :
695 : // This scope is used to load and enter the debug context and create a new
696 : // break state. Leaving the scope will restore the previous state.
697 : // On failure to load, FailedToEnter returns true.
698 : class DebugScope BASE_EMBEDDED {
699 : public:
700 : explicit DebugScope(Debug* debug);
701 : ~DebugScope();
702 :
703 : // Check whether loading was successful.
704 6089 : inline bool failed() { return failed_; }
705 :
706 : // Get the active context from before entering the debugger.
707 5375801 : inline Handle<Context> GetContext() { return save_.context(); }
708 :
709 : private:
710 662570 : Isolate* isolate() { return debug_->isolate_; }
711 :
712 : Debug* debug_;
713 : DebugScope* prev_; // Previous scope if entered recursively.
714 : StackFrame::Id break_frame_id_; // Previous break frame id.
715 : int break_id_; // Previous break id.
716 : bool failed_; // Did the debug context fail to load?
717 : SaveContext save_; // Saves previous context.
718 : PostponeInterruptsScope no_termination_exceptons_;
719 : };
720 :
721 : // This scope is used to handle return values in nested debug break points.
722 : // When there are nested debug breaks, we use this to restore the return
723 : // value to the previous state. This is not merged with DebugScope because
724 : // return_value_ will not be cleared when we use DebugScope.
725 : class ReturnValueScope {
726 : public:
727 : explicit ReturnValueScope(Debug* debug);
728 : ~ReturnValueScope();
729 :
730 : private:
731 : Debug* debug_;
732 : Handle<Object> return_value_; // Previous result.
733 : };
734 :
735 : // Stack allocated class for disabling break.
736 : class DisableBreak BASE_EMBEDDED {
737 : public:
738 : explicit DisableBreak(Debug* debug)
739 394682 : : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
740 394682 : debug_->break_disabled_ = true;
741 : }
742 : ~DisableBreak() {
743 394682 : debug_->break_disabled_ = previous_break_disabled_;
744 : }
745 :
746 : private:
747 : Debug* debug_;
748 : bool previous_break_disabled_;
749 : DISALLOW_COPY_AND_ASSIGN(DisableBreak);
750 : };
751 :
752 :
753 : class SuppressDebug BASE_EMBEDDED {
754 : public:
755 : explicit SuppressDebug(Debug* debug)
756 187113 : : debug_(debug), old_state_(debug->is_suppressed_) {
757 194083 : debug_->is_suppressed_ = true;
758 : }
759 194083 : ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
760 :
761 : private:
762 : Debug* debug_;
763 : bool old_state_;
764 : DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
765 : };
766 :
767 : class NoSideEffectScope {
768 : public:
769 61876 : NoSideEffectScope(Isolate* isolate, bool disallow_side_effects)
770 : : isolate_(isolate),
771 30938 : old_needs_side_effect_check_(isolate->needs_side_effect_check()) {
772 15469 : isolate->set_needs_side_effect_check(old_needs_side_effect_check_ ||
773 : disallow_side_effects);
774 15469 : isolate->debug()->UpdateHookOnFunctionCall();
775 15469 : isolate->debug()->side_effect_check_failed_ = false;
776 15469 : }
777 : ~NoSideEffectScope();
778 :
779 : private:
780 : Isolate* isolate_;
781 : bool old_needs_side_effect_check_;
782 : DISALLOW_COPY_AND_ASSIGN(NoSideEffectScope);
783 : };
784 :
785 : // Code generator routines.
786 : class DebugCodegen : public AllStatic {
787 : public:
788 : enum DebugBreakCallHelperMode {
789 : SAVE_RESULT_REGISTER,
790 : IGNORE_RESULT_REGISTER
791 : };
792 :
793 : static void GenerateDebugBreakStub(MacroAssembler* masm,
794 : DebugBreakCallHelperMode mode);
795 :
796 : static void GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode);
797 :
798 : // Builtin to drop frames to restart function.
799 : static void GenerateFrameDropperTrampoline(MacroAssembler* masm);
800 :
801 : // Builtin to atomically (wrt deopts) handle debugger statement and
802 : // drop frames to restart function if necessary.
803 : static void GenerateHandleDebuggerStatement(MacroAssembler* masm);
804 :
805 : static void PatchDebugBreakSlot(Isolate* isolate, Address pc,
806 : Handle<Code> code);
807 : static bool DebugBreakSlotIsPatched(Address pc);
808 : static void ClearDebugBreakSlot(Isolate* isolate, Address pc);
809 : };
810 :
811 :
812 : } // namespace internal
813 : } // namespace v8
814 :
815 : #endif // V8_DEBUG_DEBUG_H_
|