debug.h 24.8 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_DEBUG_DEBUG_H_
#define V8_DEBUG_DEBUG_H_
7

8 9
#include <vector>

10 11
#include "src/allocation.h"
#include "src/assembler.h"
12
#include "src/base/atomicops.h"
lpy's avatar
lpy committed
13
#include "src/base/hashmap.h"
14
#include "src/base/platform/platform.h"
15
#include "src/debug/debug-interface.h"
16
#include "src/debug/interface-types.h"
17 18 19
#include "src/execution.h"
#include "src/factory.h"
#include "src/flags.h"
20
#include "src/frames.h"
21
#include "src/globals.h"
22
#include "src/objects/debug-objects.h"
23
#include "src/runtime/runtime.h"
24
#include "src/source-position-table.h"
25 26 27 28
#include "src/string-stream.h"
#include "src/v8threads.h"

#include "include/v8-debug.h"
29

30 31
namespace v8 {
namespace internal {
32

33 34

// Forward declarations.
35
class DebugScope;
36 37


38
// Step actions. NOTE: These values are in macros.py as well.
39
enum StepAction : int8_t {
40
  StepNone = -1,  // Stepping not prepared.
41 42 43 44
  StepOut = 0,    // Step out of the current function.
  StepNext = 1,   // Step to the next statement in the current function.
  StepIn = 2,     // Step into new functions invoked or the next statement
                  // in the current function.
45
  LastStepAction = StepIn
46
};
47 48 49 50 51 52 53 54

// Type of exception break. NOTE: These values are in macros.py as well.
enum ExceptionBreakType {
  BreakException = 0,
  BreakUncaughtException = 1
};


55 56 57 58 59 60 61
enum DebugBreakType {
  NOT_DEBUG_BREAK,
  DEBUGGER_STATEMENT,
  DEBUG_BREAK_SLOT,
  DEBUG_BREAK_SLOT_AT_CALL,
  DEBUG_BREAK_SLOT_AT_RETURN,
};
62

63 64 65 66 67
enum IgnoreBreakMode {
  kIgnoreIfAllFramesBlackboxed,
  kIgnoreIfTopFrameBlackboxed
};

68
class BreakLocation {
69
 public:
70 71
  static BreakLocation FromFrame(Handle<DebugInfo> debug_info,
                                 JavaScriptFrame* frame);
72

73 74
  static void AllAtCurrentStatement(Handle<DebugInfo> debug_info,
                                    JavaScriptFrame* frame,
75
                                    std::vector<BreakLocation>* result_out);
76

77 78
  inline bool IsReturn() const { return type_ == DEBUG_BREAK_SLOT_AT_RETURN; }
  inline bool IsCall() const { return type_ == DEBUG_BREAK_SLOT_AT_CALL; }
79 80 81 82
  inline bool IsDebugBreakSlot() const { return type_ >= DEBUG_BREAK_SLOT; }
  inline bool IsDebuggerStatement() const {
    return type_ == DEBUGGER_STATEMENT;
  }
83

84
  bool HasBreakPoint(Handle<DebugInfo> debug_info) const;
85

86
  inline int position() const { return position_; }
87

88 89
  debug::BreakLocationType type() const;

90 91 92 93 94 95 96 97 98
 private:
  BreakLocation(Handle<AbstractCode> abstract_code, DebugBreakType type,
                int code_offset, int position)
      : abstract_code_(abstract_code),
        code_offset_(code_offset),
        type_(type),
        position_(position) {
    DCHECK_NE(NOT_DEBUG_BREAK, type_);
  }
99

100 101 102
  static int BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
                                      Handle<AbstractCode> abstract_code,
                                      int offset);
103

104 105 106 107 108 109 110 111
  void SetDebugBreak();
  void ClearDebugBreak();

  Handle<AbstractCode> abstract_code_;
  int code_offset_;
  DebugBreakType type_;
  int position_;

112
  friend class BreakIterator;
113
};
114

115 116
class BreakIterator {
 public:
117
  explicit BreakIterator(Handle<DebugInfo> debug_info);
118

119 120 121
  BreakLocation GetBreakLocation();
  bool Done() const { return source_position_iterator_.done(); }
  void Next();
122

123
  void SkipToPosition(int position);
124 125
  void SkipTo(int count) {
    while (count-- > 0) Next();
126
  }
127

128
  int code_offset() { return source_position_iterator_.code_offset(); }
129 130 131
  int break_index() const { return break_index_; }
  inline int position() const { return position_; }
  inline int statement_position() const { return statement_position_; }
132

133 134
  void ClearDebugBreak();
  void SetDebugBreak();
135

136
 private:
137
  int BreakIndexFromPosition(int position);
138

139
  Isolate* isolate() { return debug_info_->GetIsolate(); }
140

141 142
  DebugBreakType GetDebugBreakType();

143 144 145 146 147
  Handle<DebugInfo> debug_info_;
  int break_index_;
  int position_;
  int statement_position_;
  SourcePositionTableIterator source_position_iterator_;
148
  DisallowHeapAllocation no_gc_;
149

150
  DISALLOW_COPY_AND_ASSIGN(BreakIterator);
151
};
152 153 154 155 156 157

// Linked list holding debug info objects. The debug info objects are kept as
// weak handles to avoid a debug info object to keep a function alive.
class DebugInfoListNode {
 public:
  explicit DebugInfoListNode(DebugInfo* debug_info);
158
  ~DebugInfoListNode();
159 160 161

  DebugInfoListNode* next() { return next_; }
  void set_next(DebugInfoListNode* next) { next_ = next; }
dcarney's avatar
dcarney committed
162 163
  Handle<DebugInfo> debug_info() { return Handle<DebugInfo>(debug_info_); }

164 165
 private:
  // Global (weak) handle to the debug info object.
dcarney's avatar
dcarney committed
166
  DebugInfo** debug_info_;
167 168 169 170 171

  // Next pointer for linked list.
  DebugInfoListNode* next_;
};

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
class DebugFeatureTracker {
 public:
  enum Feature {
    kActive = 1,
    kBreakPoint = 2,
    kStepping = 3,
    kHeapSnapshot = 4,
    kAllocationTracking = 5,
    kProfiler = 6,
    kLiveEdit = 7,
  };

  explicit DebugFeatureTracker(Isolate* isolate)
      : isolate_(isolate), bitfield_(0) {}
  void Track(Feature feature);

 private:
  Isolate* isolate_;
  uint32_t bitfield_;
};


194 195 196 197 198 199 200 201 202
// This class contains the debugger support. The main purpose is to handle
// setting break points in the code.
//
// This class controls the debug info for all functions which currently have
// active breakpoints in them. This debug info is held in the heap root object
// debug_info which is a FixedArray. Each entry in this list is of class
// DebugInfo.
class Debug {
 public:
203
  // Debug event triggers.
204
  void OnDebugBreak(Handle<FixedArray> break_points_hit);
205

206
  void OnThrow(Handle<Object> exception);
207
  void OnPromiseReject(Handle<Object> promise, Handle<Object> value);
208
  void OnCompileError(Handle<Script> script);
209
  void OnAfterCompile(Handle<Script> script);
210 211
  void OnAsyncTaskEvent(debug::PromiseDebugActionType type, int id,
                        int parent_id);
212

213
  MUST_USE_RESULT MaybeHandle<Object> Call(Handle<Object> fun,
214 215
                                           Handle<Object> data);
  Handle<Context> GetDebugContext();
216
  void HandleDebugBreak(IgnoreBreakMode ignore_break_mode);
217

218
  // Internal logic
219
  bool Load();
220
  void Break(JavaScriptFrame* frame);
221

222 223 224 225
  // Scripts handling.
  Handle<FixedArray> GetLoadedScripts();

  // Break point handling.
226
  bool SetBreakPoint(Handle<JSFunction> function,
227 228
                     Handle<Object> break_point_object,
                     int* source_position);
229 230
  bool SetBreakPointForScript(Handle<Script> script,
                              Handle<Object> break_point_object,
231
                              int* source_position);
232 233 234
  void ClearBreakPoint(Handle<Object> break_point_object);
  void ChangeBreakOnException(ExceptionBreakType type, bool enable);
  bool IsBreakOnException(ExceptionBreakType type);
235

236 237 238 239
  bool SetBreakpoint(Handle<Script> script, Handle<String> condition,
                     int* offset, int* id);
  void RemoveBreakpoint(int id);

240 241 242 243 244 245 246
  // The parameter is either a BreakPointInfo object, or a FixedArray of
  // BreakPointInfo objects.
  // Returns an empty handle if no breakpoint is hit, or a FixedArray with all
  // hit breakpoints.
  MaybeHandle<FixedArray> GetHitBreakPointObjects(
      Handle<Object> break_point_objects);

247
  // Stepping handling.
248
  void PrepareStep(StepAction step_action);
249
  void PrepareStepIn(Handle<JSFunction> function);
250
  void PrepareStepInSuspendedGenerator();
251
  void PrepareStepOnThrow();
252
  void ClearStepping();
253
  void ClearStepOut();
254

255 256
  void DeoptimizeFunction(Handle<SharedFunctionInfo> shared);
  void PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared);
257
  bool GetPossibleBreakpoints(Handle<Script> script, int start_position,
258
                              int end_position, bool restrict_to_function,
259
                              std::vector<BreakLocation>* locations);
260

261
  void RecordGenerator(Handle<JSGeneratorObject> generator_object);
262

263 264 265
  void RunPromiseHook(PromiseHookType type, Handle<JSPromise> promise,
                      Handle<Object> parent);

266 267
  int NextAsyncTaskId(Handle<JSObject> promise);

268 269
  bool IsBlackboxed(Handle<SharedFunctionInfo> shared);

270
  void SetDebugDelegate(debug::DebugDelegate* delegate, bool pass_ownership);
271

272
  // Returns whether the operation succeeded.
273 274 275
  bool EnsureBreakInfo(Handle<SharedFunctionInfo> shared);
  void CreateBreakInfo(Handle<SharedFunctionInfo> shared);
  Handle<DebugInfo> GetOrCreateDebugInfo(Handle<SharedFunctionInfo> shared);
276

277 278 279 280
  void InstallCoverageInfo(Handle<SharedFunctionInfo> shared,
                           Handle<CoverageInfo> coverage_info);
  void RemoveAllCoverageInfos();

281 282 283
  template <typename C>
  bool CompileToRevealInnerFunctions(C* compilable);

284
  // This function is used in FunctionNameUsing* tests.
285 286
  Handle<Object> FindSharedFunctionInfoInScript(Handle<Script> script,
                                                int position);
287

288
  static Handle<Object> GetSourceBreakLocations(
289
      Handle<SharedFunctionInfo> shared);
290 291

  // Check whether a global object is the debug global object.
292
  bool IsDebugGlobal(JSGlobalObject* global);
293

294
  // Check whether this frame is just about to return.
295
  bool IsBreakAtReturn(JavaScriptFrame* frame);
296

297
  // Support for LiveEdit
298
  void ScheduleFrameRestart(StackFrame* frame);
299

300
  bool AllFramesOnStackAreBlackboxed();
301

302 303 304 305 306 307 308
  // Set new script source, throw an exception if error occurred. When preview
  // is true: try to set source, throw exception if any without actual script
  // change. stack_changed is true if after editing script on pause stack is
  // changed and client should request stack trace again.
  bool SetScriptSource(Handle<Script> script, Handle<String> source,
                       bool preview, bool* stack_changed);

309
  // Threading support.
310 311
  char* ArchiveDebug(char* to);
  char* RestoreDebug(char* from);
312
  static int ArchiveSpacePerThread();
313
  void FreeThreadResources() { }
314
  void Iterate(RootVisitor* v);
315

316
  bool CheckExecutionState(int id) {
317 318 319 320 321
    return CheckExecutionState() && break_id() == id;
  }

  bool CheckExecutionState() {
    return is_active() && !debug_context().is_null() && break_id() != 0;
322 323
  }

324 325 326
  bool PerformSideEffectCheck(Handle<JSFunction> function);
  bool PerformSideEffectCheckForCallback(Address function);

327
  // Flags and states.
328 329
  DebugScope* debugger_entry() {
    return reinterpret_cast<DebugScope*>(
330
        base::Relaxed_Load(&thread_local_.current_debug_scope_));
331
  }
332
  inline Handle<Context> debug_context() { return debug_context_; }
333

334 335
  void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
  bool live_edit_enabled() const {
336
    return FLAG_enable_liveedit && live_edit_enabled_;
337 338 339 340
  }

  inline bool is_active() const { return is_active_; }
  inline bool is_loaded() const { return !debug_context_.is_null(); }
341
  inline bool in_debug_scope() const {
342
    return !!base::Relaxed_Load(&thread_local_.current_debug_scope_);
343
  }
344
  void set_break_points_active(bool v) { break_points_active_ = v; }
345
  bool break_points_active() const { return break_points_active_; }
346 347 348 349

  StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
  int break_id() { return thread_local_.break_id_; }

350 351 352
  Handle<Object> return_value_handle() {
    return handle(thread_local_.return_value_, isolate_);
  }
353 354
  Object* return_value() { return thread_local_.return_value_; }
  void set_return_value(Object* value) { thread_local_.return_value_ = value; }
355

356
  // Support for embedding into generated code.
357 358 359 360
  Address is_active_address() {
    return reinterpret_cast<Address>(&is_active_);
  }

361 362 363 364
  Address hook_on_function_call_address() {
    return reinterpret_cast<Address>(&hook_on_function_call_);
  }

365 366
  Address last_step_action_address() {
    return reinterpret_cast<Address>(&thread_local_.last_step_action_);
367 368
  }

369 370 371 372
  Address suspended_generator_address() {
    return reinterpret_cast<Address>(&thread_local_.suspended_generator_);
  }

373 374 375 376
  Address restart_fp_address() {
    return reinterpret_cast<Address>(&thread_local_.restart_fp_);
  }

377 378
  StepAction last_step_action() { return thread_local_.last_step_action_; }

379 380
  DebugFeatureTracker* feature_tracker() { return &feature_tracker_; }

381
 private:
382
  explicit Debug(Isolate* isolate);
383
  ~Debug() { DCHECK_NULL(debug_delegate_); }
384

385
  void UpdateState();
386
  void UpdateHookOnFunctionCall();
387
  void RemoveDebugDelegate();
388 389 390 391 392
  void Unload();
  void SetNextBreakId() {
    thread_local_.break_id_ = ++thread_local_.break_count_;
  }

393 394 395
  // Return the number of virtual frames below debugger entry.
  int CurrentFrameCount();

396 397 398
  inline bool ignore_events() const {
    return is_suppressed_ || !is_active_ || isolate_->needs_side_effect_check();
  }
399
  inline bool break_disabled() const { return break_disabled_; }
400

401
  void clear_suspended_generator() {
402
    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

413
  // Constructors for debug event objects.
414 415 416 417 418 419 420 421
  MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
  MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
      Handle<Object> break_points_hit);
  MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
      Handle<Object> exception,
      bool uncaught,
      Handle<Object> promise);
  MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
422
      Handle<Script> script, v8::DebugEvent type);
423 424
  MUST_USE_RESULT MaybeHandle<Object> MakeAsyncTaskEvent(
      v8::debug::PromiseDebugActionType type, int id);
425

426
  void ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script);
427
  void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
428

429
  // Find the closest source position for a break point for a given position.
430
  int FindBreakablePosition(Handle<DebugInfo> debug_info, int source_position);
431 432 433 434 435 436 437
  // Instrument code to break at break points.
  void ApplyBreakPoints(Handle<DebugInfo> debug_info);
  // Clear code from instrumentation.
  void ClearBreakPoints(Handle<DebugInfo> debug_info);
  // Clear all code from instrumentation.
  void ClearAllBreakPoints();
  // Instrument a function with one-shots.
438 439
  void FloodWithOneShot(Handle<SharedFunctionInfo> function,
                        bool returns_only = false);
440
  // Clear all one-shot instrumentations, but restore break points.
441
  void ClearOneShot();
442

443 444
  bool IsFrameBlackboxed(JavaScriptFrame* frame);

445
  void ActivateStepOut(StackFrame* frame);
446 447 448
  MaybeHandle<FixedArray> CheckBreakPoints(Handle<DebugInfo> debug_info,
                                           BreakLocation* location,
                                           bool* has_break_points = nullptr);
449
  bool IsMutedAtCurrentLocation(JavaScriptFrame* frame);
450
  bool CheckBreakPoint(Handle<Object> break_point_object);
451
  MaybeHandle<Object> CallFunction(const char* name, int argc,
452 453
                                   Handle<Object> args[],
                                   bool catch_exceptions = true);
454

455
  inline void AssertDebugContext() {
456 457
    DCHECK(isolate_->context() == *debug_context());
    DCHECK(in_debug_scope());
458 459
  }

460
  void ThreadInit();
461

462 463
  void PrintBreakLocation();

464 465 466 467
  // Wraps logic for clearing and maybe freeing all debug infos.
  typedef std::function<bool(Handle<DebugInfo>)> DebugInfoClearFunction;
  void ClearAllDebugInfos(DebugInfoClearFunction clear_function);

468 469 470 471 472
  void RemoveBreakInfoAndMaybeFree(Handle<DebugInfo> debug_info);
  void FindDebugInfo(Handle<DebugInfo> debug_info, DebugInfoListNode** prev,
                     DebugInfoListNode** curr);
  void FreeDebugInfoListNode(DebugInfoListNode* prev, DebugInfoListNode* node);

473 474 475
  // Global handles.
  Handle<Context> debug_context_;

476
  debug::DebugDelegate* debug_delegate_ = nullptr;
477
  bool owns_debug_delegate_ = false;
478

479
  // Debugger is active, i.e. there is a debug event listener attached.
480
  bool is_active_;
481 482 483 484
  // Debugger needs to be notified on every new function call.
  // Used for stepping and read-only checks
  bool hook_on_function_call_;
  // Suppress debug events.
485
  bool is_suppressed_;
486
  // LiveEdit is enabled.
487
  bool live_edit_enabled_;
488
  // Do not trigger debug break events.
489
  bool break_disabled_;
490
  // Do not break on break points.
491
  bool break_points_active_;
492
  // Trigger debug break events for all exceptions.
493
  bool break_on_exception_;
494
  // Trigger debug break events for uncaught exceptions.
495
  bool break_on_uncaught_exception_;
496 497
  // Termination exception because side effect check has failed.
  bool side_effect_check_failed_;
498

499 500
  // List of active debug info objects.
  DebugInfoListNode* debug_info_list_;
501

502 503 504
  // Used to collect histogram data on debugger feature usage.
  DebugFeatureTracker feature_tracker_;

505
  // Per-thread data.
506 507
  class ThreadLocal {
   public:
508
    // Top debugger entry.
509
    base::AtomicWord current_debug_scope_;
510

511 512 513 514 515 516 517 518 519
    // Counter for generating next break id.
    int break_count_;

    // Current break id.
    int break_id_;

    // Frame id for the frame of the current break.
    StackFrame::Id break_frame_id_;

520 521 522
    // Step action for last step performed.
    StepAction last_step_action_;

523 524
    // If set, next PrepareStepIn will ignore this function until stepped into
    // another function, at which point this will be cleared.
525 526 527 528 529
    Object* ignore_step_into_function_;

    // If set then we need to repeat StepOut action at return.
    bool fast_forward_to_return_;

530 531 532
    // Source statement position from last step next action.
    int last_statement_position_;

533
    // Frame pointer from last step next or step frame action.
534
    int last_frame_count_;
535

536
    // Frame pointer of the target frame we want to arrive at.
537
    int target_frame_count_;
538

539 540
    // Value of the accumulator at the point of entering the debugger.
    Object* return_value_;
541

542
    // The suspended generator object to track when stepping.
543
    Object* suspended_generator_;
544

545 546 547
    // The new frame pointer to drop to when restarting a frame.
    Address restart_fp_;

548
    int async_task_count_;
549 550 551

    // Last used inspector breakpoint id.
    int last_breakpoint_id_;
552 553 554
  };

  // Storage location for registers when handling debug break calls
555
  ThreadLocal thread_local_;
556

557 558 559
  Isolate* isolate_;

  friend class Isolate;
560
  friend class DebugScope;
561
  friend class DisableBreak;
562
  friend class LiveEdit;
563
  friend class SuppressDebug;
564
  friend class NoSideEffectScope;
565
  friend class LegacyDebugDelegate;
566

567
  friend Handle<FixedArray> GetDebuggedFunctions();  // In test-debug.cc
568
  friend void CheckDebuggerUnloaded();               // In test-debug.cc
569

570
  DISALLOW_COPY_AND_ASSIGN(Debug);
571 572
};

573 574 575
class LegacyDebugDelegate : public v8::debug::DebugDelegate {
 public:
  explicit LegacyDebugDelegate(Isolate* isolate) : isolate_(isolate) {}
576
  void PromiseEventOccurred(v8::debug::PromiseDebugActionType type, int id,
577
                            int parent_id, bool created_by_user) override;
578
  void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
579 580 581
                      bool has_compile_error) override;
  void BreakProgramRequested(v8::Local<v8::Context> paused_context,
                             v8::Local<v8::Object> exec_state,
582 583
                             v8::Local<v8::Value> break_points_hit,
                             const std::vector<debug::BreakpointId>&) override;
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
  void ExceptionThrown(v8::Local<v8::Context> paused_context,
                       v8::Local<v8::Object> exec_state,
                       v8::Local<v8::Value> exception,
                       v8::Local<v8::Value> promise, bool is_uncaught) override;
  bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
                            const v8::debug::Location& start,
                            const v8::debug::Location& end) override {
    return false;
  }

 protected:
  Isolate* isolate_;

 private:
  void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data);
  virtual void ProcessDebugEvent(v8::DebugEvent event,
                                 Handle<JSObject> event_data,
                                 Handle<JSObject> exec_state) = 0;
};

class JavaScriptDebugDelegate : public LegacyDebugDelegate {
 public:
  JavaScriptDebugDelegate(Isolate* isolate, Handle<JSFunction> listener,
                          Handle<Object> data);
  virtual ~JavaScriptDebugDelegate();

 private:
  void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
                         Handle<JSObject> exec_state) override;

  Handle<JSFunction> listener_;
  Handle<Object> data_;
};

class NativeDebugDelegate : public LegacyDebugDelegate {
 public:
  NativeDebugDelegate(Isolate* isolate, v8::Debug::EventCallback callback,
                      Handle<Object> data);
  virtual ~NativeDebugDelegate();

 private:
  // Details of the debug event delivered to the debug event listener.
  class EventDetails : public v8::Debug::EventDetails {
   public:
    EventDetails(DebugEvent event, Handle<JSObject> exec_state,
                 Handle<JSObject> event_data, Handle<Object> callback_data);
    virtual DebugEvent GetEvent() const;
    virtual v8::Local<v8::Object> GetExecutionState() const;
    virtual v8::Local<v8::Object> GetEventData() const;
    virtual v8::Local<v8::Context> GetEventContext() const;
    virtual v8::Local<v8::Value> GetCallbackData() const;
    virtual v8::Debug::ClientData* GetClientData() const { return nullptr; }
    virtual v8::Isolate* GetIsolate() const;

   private:
    DebugEvent event_;              // Debug event causing the break.
    Handle<JSObject> exec_state_;   // Current execution state.
    Handle<JSObject> event_data_;   // Data associated with the event.
    Handle<Object> callback_data_;  // User data passed with the callback
                                    // when it was registered.
  };

  void ProcessDebugEvent(v8::DebugEvent event, Handle<JSObject> event_data,
                         Handle<JSObject> exec_state) override;

  v8::Debug::EventCallback callback_;
  Handle<Object> data_;
};
652

653 654 655 656
// This scope is used to load and enter the debug context and create a new
// break state.  Leaving the scope will restore the previous state.
// On failure to load, FailedToEnter returns true.
class DebugScope BASE_EMBEDDED {
657
 public:
658 659
  explicit DebugScope(Debug* debug);
  ~DebugScope();
660

661 662
  // Check whether loading was successful.
  inline bool failed() { return failed_; }
663

664 665 666
  // Get the active context from before entering the debugger.
  inline Handle<Context> GetContext() { return save_.context(); }

667
 private:
668 669 670 671
  Isolate* isolate() { return debug_->isolate_; }

  Debug* debug_;
  DebugScope* prev_;               // Previous scope if entered recursively.
672
  StackFrame::Id break_frame_id_;  // Previous break frame id.
673 674 675
  int break_id_;                   // Previous break id.
  bool failed_;                    // Did the debug context fail to load?
  SaveContext save_;               // Saves previous context.
676
  PostponeInterruptsScope no_termination_exceptons_;
677 678
};

679 680 681 682 683 684 685 686 687 688 689 690 691
// This scope is used to handle return values in nested debug break points.
// When there are nested debug breaks, we use this to restore the return
// value to the previous state. This is not merged with DebugScope because
// return_value_ will not be cleared when we use DebugScope.
class ReturnValueScope {
 public:
  explicit ReturnValueScope(Debug* debug);
  ~ReturnValueScope();

 private:
  Debug* debug_;
  Handle<Object> return_value_;  // Previous result.
};
692

693 694 695
// Stack allocated class for disabling break.
class DisableBreak BASE_EMBEDDED {
 public:
696
  explicit DisableBreak(Debug* debug)
697
      : debug_(debug), previous_break_disabled_(debug->break_disabled_) {
698
    debug_->break_disabled_ = true;
699 700 701
  }
  ~DisableBreak() {
    debug_->break_disabled_ = previous_break_disabled_;
702
  }
703 704 705

 private:
  Debug* debug_;
706
  bool previous_break_disabled_;
707 708 709 710 711 712 713 714 715
  DISALLOW_COPY_AND_ASSIGN(DisableBreak);
};


class SuppressDebug BASE_EMBEDDED {
 public:
  explicit SuppressDebug(Debug* debug)
      : debug_(debug), old_state_(debug->is_suppressed_) {
    debug_->is_suppressed_ = true;
716
  }
717
  ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
718 719

 private:
720 721 722
  Debug* debug_;
  bool old_state_;
  DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
723 724
};

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
class NoSideEffectScope {
 public:
  NoSideEffectScope(Isolate* isolate, bool disallow_side_effects)
      : isolate_(isolate),
        old_needs_side_effect_check_(isolate->needs_side_effect_check()) {
    isolate->set_needs_side_effect_check(old_needs_side_effect_check_ ||
                                         disallow_side_effects);
    isolate->debug()->UpdateHookOnFunctionCall();
    isolate->debug()->side_effect_check_failed_ = false;
  }
  ~NoSideEffectScope();

 private:
  Isolate* isolate_;
  bool old_needs_side_effect_check_;
  DISALLOW_COPY_AND_ASSIGN(NoSideEffectScope);
};
742 743 744 745

// Code generator routines.
class DebugCodegen : public AllStatic {
 public:
746 747 748
  enum DebugBreakCallHelperMode {
    SAVE_RESULT_REGISTER,
    IGNORE_RESULT_REGISTER
749 750
  };

751 752
  // Builtin to drop frames to restart function.
  static void GenerateFrameDropperTrampoline(MacroAssembler* masm);
753

754 755 756
  // Builtin to atomically (wrt deopts) handle debugger statement and
  // drop frames to restart function if necessary.
  static void GenerateHandleDebuggerStatement(MacroAssembler* masm);
757 758
};

759

760 761
}  // namespace internal
}  // namespace v8
762

763
#endif  // V8_DEBUG_DEBUG_H_