// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_DEBUGGER_H_
#define RUNTIME_VM_DEBUGGER_H_

#include <memory>

#include "include/dart_tools_api.h"

#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/port.h"
#include "vm/scopes.h"
#include "vm/service_event.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stack_trace.h"

#if !defined(PRODUCT)

DECLARE_FLAG(bool, verbose_debug);

// 'Trace Debugger' TD_Print.
#if defined(_MSC_VER)
#define TD_Print(format, ...)                                                  \
  if (FLAG_verbose_debug) Log::Current()->Print(format, __VA_ARGS__)
#else
#define TD_Print(format, ...)                                                  \
  if (FLAG_verbose_debug) Log::Current()->Print(format, ##__VA_ARGS__)
#endif

namespace dart {

class CodeBreakpoint;
class Isolate;
class JSONArray;
class JSONStream;
class ObjectPointerVisitor;
class BreakpointLocation;
class StackFrame;

// A user-defined breakpoint, which either fires once, for a particular closure,
// or always. The API's notion of a breakpoint corresponds to this object.
class Breakpoint {
 public:
  Breakpoint(intptr_t id, BreakpointLocation* bpt_location)
      : id_(id),
        kind_(Breakpoint::kNone),
        next_(NULL),
        closure_(Instance::null()),
        bpt_location_(bpt_location),
        is_synthetic_async_(false) {}

  intptr_t id() const { return id_; }
  Breakpoint* next() const { return next_; }
  void set_next(Breakpoint* n) { next_ = n; }

  BreakpointLocation* bpt_location() const { return bpt_location_; }
  void set_bpt_location(BreakpointLocation* new_bpt_location);

  bool IsRepeated() const { return kind_ == kRepeated; }
  bool IsSingleShot() const { return kind_ == kSingleShot; }
  bool IsPerClosure() const { return kind_ == kPerClosure; }
  InstancePtr closure() const { return closure_; }

  void SetIsRepeated() {
    ASSERT(kind_ == kNone);
    kind_ = kRepeated;
  }

  void SetIsSingleShot() {
    ASSERT(kind_ == kNone);
    kind_ = kSingleShot;
  }

  void SetIsPerClosure(const Instance& closure) {
    ASSERT(kind_ == kNone);
    kind_ = kPerClosure;
    closure_ = closure.ptr();
  }

  void Enable() {
    ASSERT(!enabled_);
    enabled_ = true;
  }

  void Disable() {
    ASSERT(enabled_);
    enabled_ = false;
  }

  bool is_enabled() const { return enabled_; }

  // Mark that this breakpoint is a result of a step OverAwait request.
  void set_is_synthetic_async(bool is_synthetic_async) {
    is_synthetic_async_ = is_synthetic_async;
  }
  bool is_synthetic_async() const { return is_synthetic_async_; }

  void PrintJSON(JSONStream* stream);

 private:
  void VisitObjectPointers(ObjectPointerVisitor* visitor);

  enum ConditionKind {
    kNone,
    kRepeated,
    kSingleShot,
    kPerClosure,
  };

  intptr_t id_;
  ConditionKind kind_;
  Breakpoint* next_;
  InstancePtr closure_;
  BreakpointLocation* bpt_location_;
  bool is_synthetic_async_;
  bool enabled_ = false;

  friend class BreakpointLocation;
  DISALLOW_COPY_AND_ASSIGN(Breakpoint);
};

// BreakpointLocation represents a collection of breakpoint conditions at the
// same token position in Dart source. There may be more than one CodeBreakpoint
// object per BreakpointLocation.
// An unresolved breakpoint is one where the underlying code has not
// been compiled yet. Since the code has not been compiled, we don't know
// the definitive source location yet. The requested source location may
// change when the underlying code gets compiled.
// A latent breakpoint represents a breakpoint location in Dart source
// that is not loaded in the VM when the breakpoint is requested.
// When a script with matching url is loaded, a latent breakpoint
// becomes an unresolved breakpoint.
class BreakpointLocation {
 public:
  // Create a new unresolved breakpoint.
  BreakpointLocation(Debugger* debugger,
                     const Script& script,
                     TokenPosition token_pos,
                     TokenPosition end_token_pos,
                     intptr_t requested_line_number,
                     intptr_t requested_column_number);
  // Create a new latent breakpoint.
  BreakpointLocation(Debugger* debugger,
                     const String& url,
                     intptr_t requested_line_number,
                     intptr_t requested_column_number);

  ~BreakpointLocation();

  TokenPosition token_pos() const { return token_pos_; }
  intptr_t line_number();
  TokenPosition end_token_pos() const { return end_token_pos_; }

  ScriptPtr script() const { return script_; }
  StringPtr url() const { return url_; }

  intptr_t requested_line_number() const { return requested_line_number_; }
  intptr_t requested_column_number() const { return requested_column_number_; }

  void GetCodeLocation(Script* script, TokenPosition* token_pos) const;

  Breakpoint* AddRepeated(Debugger* dbg);
  Breakpoint* AddSingleShot(Debugger* dbg);
  Breakpoint* AddPerClosure(Debugger* dbg,
                            const Instance& closure,
                            bool for_over_await);

  bool AnyEnabled() const;
  bool IsResolved() const { return code_token_pos_.IsReal(); }
  bool IsLatent() const { return !token_pos_.IsReal(); }

  bool EnsureIsResolved(const Function& target_function,
                        TokenPosition exact_token_pos);

  Debugger* debugger() { return debugger_; }

 private:
  void VisitObjectPointers(ObjectPointerVisitor* visitor);

  void SetResolved(const Function& func, TokenPosition token_pos);

  BreakpointLocation* next() const { return this->next_; }
  void set_next(BreakpointLocation* value) { next_ = value; }

  void AddBreakpoint(Breakpoint* bpt, Debugger* dbg);

  Breakpoint* breakpoints() const { return this->conditions_; }
  void set_breakpoints(Breakpoint* head) { this->conditions_ = head; }

  // Finds the breakpoint we hit at |location|.
  Breakpoint* FindHitBreakpoint(ActivationFrame* top_frame);

  SafepointRwLock* line_number_lock() { return line_number_lock_.get(); }

  Debugger* debugger_;
  ScriptPtr script_;
  StringPtr url_;
  std::unique_ptr<SafepointRwLock> line_number_lock_;
  intptr_t line_number_;  // lazily computed for token_pos_
  TokenPosition token_pos_;
  TokenPosition end_token_pos_;
  BreakpointLocation* next_;
  Breakpoint* conditions_;
  intptr_t requested_line_number_;
  intptr_t requested_column_number_;

  // Valid for resolved breakpoints:
  TokenPosition code_token_pos_;

  friend class Debugger;
  friend class GroupDebugger;
  DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
};

// CodeBreakpoint represents a location in compiled code.
// There may be more than one CodeBreakpoint for one BreakpointLocation,
// e.g. when a function gets compiled as a regular function and as a closure.
// There may be more than one BreakpointLocation associated with CodeBreakpoint,
// one for for every isolate in a group that sets a breakpoint at particular
// code location represented by the CodeBreakpoint.
// Each BreakpointLocation might be enabled/disabled based on whether it has
// any actual breakpoints associated with it.
// The CodeBreakpoint is enabled if it has any such BreakpointLocations
// associated with it.
// The class is not thread-safe - users of this class need to ensure the access
// is synchronized, guarded by mutexes or run inside of a safepoint scope.
class CodeBreakpoint {
 public:
  // Unless CodeBreakpoint is unlinked and is no longer used there should be at
  // least one BreakpointLocation associated with CodeBreakpoint. If there are
  // more BreakpointLocation added assumption is is that all of them point to
  // the same source so have the same token pos.
  CodeBreakpoint(const Code& code,
                 BreakpointLocation* loc,
                 uword pc,
                 UntaggedPcDescriptors::Kind kind);
  ~CodeBreakpoint();

  // Used by GroupDebugger to find CodeBreakpoint associated with
  // particular function.
  FunctionPtr function() const { return Code::Handle(code_).function(); }

  uword pc() const { return pc_; }
  bool HasBreakpointLocation(BreakpointLocation* breakpoint_location);
  bool FindAndDeleteBreakpointLocation(BreakpointLocation* breakpoint_location);
  bool HasNoBreakpointLocations() {
    return breakpoint_locations_.length() == 0;
  }

  void Enable();
  void Disable();
  bool IsEnabled() const { return enabled_count_ > 0; }

  CodePtr OrigStubAddress() const;

  const char* ToCString() const;

 private:
  void VisitObjectPointers(ObjectPointerVisitor* visitor);

  // Finds right BreakpointLocation for a given Isolate's debugger.
  BreakpointLocation* FindBreakpointForDebugger(Debugger* debugger);
  // Adds new BreakpointLocation for another isolate that wants to
  // break at the same function/code location that this CodeBreakpoint
  // represents.
  void AddBreakpointLocation(BreakpointLocation* breakpoint_location) {
    ASSERT(breakpoint_locations_.length() == 0 ||
           (breakpoint_location->token_pos() ==
                breakpoint_locations_.At(0)->token_pos() &&
            breakpoint_location->script() ==
                breakpoint_locations_.At(0)->script()));
    breakpoint_locations_.Add(breakpoint_location);
  }

  void set_next(CodeBreakpoint* value) { next_ = value; }
  CodeBreakpoint* next() const { return this->next_; }

  void PatchCode();
  void RestoreCode();

  CodePtr code_;
  uword pc_;
  int enabled_count_;  // incremented for every enabled breakpoint location

  // Breakpoint locations from different debuggers/isolates that
  // point to this code breakpoint.
  MallocGrowableArray<BreakpointLocation*> breakpoint_locations_;
  CodeBreakpoint* next_;

  UntaggedPcDescriptors::Kind breakpoint_kind_;
  CodePtr saved_value_;

  friend class Debugger;
  friend class GroupDebugger;
  DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint);
};

// ActivationFrame represents one dart function activation frame
// on the call stack.
class ActivationFrame : public ZoneAllocated {
 public:
  enum Kind {
    kRegular,
    kAsyncSuspensionMarker,
    kAsyncCausal,
    kAsyncActivation,
  };

  ActivationFrame(uword pc,
                  uword fp,
                  uword sp,
                  const Code& code,
                  const Array& deopt_frame,
                  intptr_t deopt_frame_offset,
                  Kind kind = kRegular);

  ActivationFrame(uword pc, const Code& code);

  explicit ActivationFrame(Kind kind);

  explicit ActivationFrame(const Closure& async_activation);

  uword pc() const { return pc_; }
  uword fp() const { return fp_; }
  uword sp() const { return sp_; }

  uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }

  const Function& function() const {
    return function_;
  }
  const Code& code() const {
    ASSERT(!code_.IsNull());
    return code_;
  }

  enum Relation {
    kCallee,
    kSelf,
    kCaller,
  };

  Relation CompareTo(uword other_fp) const;

  StringPtr QualifiedFunctionName();
  StringPtr SourceUrl();
  ScriptPtr SourceScript();
  LibraryPtr Library();
  TokenPosition TokenPos();
  intptr_t LineNumber();
  intptr_t ColumnNumber();

  // Returns true if this frame is for a function that is visible
  // to the user and can be debugged.
  bool IsDebuggable() const;

  // Returns true if it is possible to rewind the debugger to this frame.
  bool IsRewindable() const;

  // The context level of a frame is the context level at the
  // PC/token index of the frame. It determines the depth of the context
  // chain that belongs to the function of this activation frame.
  intptr_t ContextLevel();

  const char* ToCString();

  intptr_t NumLocalVariables();

  void VariableAt(intptr_t i,
                  String* name,
                  TokenPosition* declaration_token_pos,
                  TokenPosition* visible_start_token_pos,
                  TokenPosition* visible_end_token_pos,
                  Object* value);

  ArrayPtr GetLocalVariables();
  ObjectPtr GetParameter(intptr_t index);
  ClosurePtr GetClosure();
  ObjectPtr GetReceiver();

  const Context& GetSavedCurrentContext();
  ObjectPtr GetAsyncOperation();

  TypeArgumentsPtr BuildParameters(
      const GrowableObjectArray& param_names,
      const GrowableObjectArray& param_values,
      const GrowableObjectArray& type_params_names);

  ObjectPtr EvaluateCompiledExpression(const ExternalTypedData& kernel_data,
                                       const Array& arguments,
                                       const Array& type_definitions,
                                       const TypeArguments& type_arguments);

  void PrintToJSONObject(JSONObject* jsobj);

  // Get Closure that await'ed this async frame.
  ObjectPtr GetAsyncAwaiter(CallerClosureFinder* caller_closure_finder);

  bool HandlesException(const Instance& exc_obj);

 private:
  void PrintToJSONObjectRegular(JSONObject* jsobj);
  void PrintToJSONObjectAsyncCausal(JSONObject* jsobj);
  void PrintToJSONObjectAsyncSuspensionMarker(JSONObject* jsobj);
  void PrintContextMismatchError(intptr_t ctx_slot,
                                 intptr_t frame_ctx_level,
                                 intptr_t var_ctx_level);
  void PrintDescriptorsError(const char* message);

  intptr_t TryIndex();
  intptr_t DeoptId();
  void GetPcDescriptors();
  void GetVarDescriptors();
  void GetDescIndices();

  ObjectPtr GetAsyncContextVariable(const String& name);

  // Get the current continuation index in the :await_jump_var pulled from the
  // context.
  intptr_t GetAwaitJumpVariable();

  void ExtractTokenPositionFromAsyncClosure();

  bool IsAsyncMachinery() const;

  static const char* KindToCString(Kind kind) {
    switch (kind) {
      case kRegular:
        return "Regular";
      case kAsyncCausal:
        return "AsyncCausal";
      case kAsyncSuspensionMarker:
        return "AsyncSuspensionMarker";
      case kAsyncActivation:
        return "AsyncActivation";
      default:
        UNREACHABLE();
        return "";
    }
  }

  ObjectPtr GetStackVar(VariableIndex var_index);
  ObjectPtr GetRelativeContextVar(intptr_t ctxt_level,
                                  intptr_t slot_index,
                                  intptr_t frame_ctx_level);
  ObjectPtr GetContextVar(intptr_t ctxt_level, intptr_t slot_index);

  uword pc_;
  uword fp_;
  uword sp_;

  // The anchor of the context chain for this function.
  Context& ctx_;
  Code& code_;
  Function& function_;
  bool live_frame_;  // Is this frame a live frame?
  bool token_pos_initialized_;
  TokenPosition token_pos_;
  intptr_t try_index_;
  intptr_t deopt_id_;

  intptr_t line_number_;
  intptr_t column_number_;
  intptr_t context_level_;

  // Some frames are deoptimized into a side array in order to inspect them.
  const Array& deopt_frame_;
  const intptr_t deopt_frame_offset_;

  Kind kind_;

  bool vars_initialized_;
  LocalVarDescriptors& var_descriptors_;
  ZoneGrowableArray<intptr_t> desc_indices_;
  PcDescriptors& pc_desc_;

  friend class Debugger;
  friend class DebuggerStackTrace;
  DISALLOW_COPY_AND_ASSIGN(ActivationFrame);
};

// Array of function activations on the call stack.
class DebuggerStackTrace : public ZoneAllocated {
 public:
  explicit DebuggerStackTrace(int capacity) : trace_(capacity) {}

  intptr_t Length() const { return trace_.length(); }

  ActivationFrame* FrameAt(int i) const { return trace_[i]; }

  ActivationFrame* GetHandlerFrame(const Instance& exc_obj) const;

  static DebuggerStackTrace* CollectAwaiterReturn();
  static DebuggerStackTrace* Collect();
  // Returns a debugger stack trace corresponding to a dart.core.StackTrace.
  // Frames corresponding to invisible functions are omitted. It is not valid
  // to query local variables in the returned stack.
  static DebuggerStackTrace* From(const class StackTrace& ex_trace);

 private:
  void AddActivation(ActivationFrame* frame);
  void AddMarker(ActivationFrame::Kind marker);
  void AddAsyncCausalFrame(uword pc, const Code& code);

  void AppendCodeFrames(Thread* thread,
                        Isolate* isolate,
                        Zone* zone,
                        StackFrame* frame,
                        Code* code,
                        Code* inlined_code,
                        Array* deopt_frame);

  static DebuggerStackTrace* CollectAsyncCausal();
  static DebuggerStackTrace* CollectAsyncLazy();

  ZoneGrowableArray<ActivationFrame*> trace_;

  friend class Debugger;

  DISALLOW_COPY_AND_ASSIGN(DebuggerStackTrace);
};

// On which exceptions to pause.
typedef enum {
  kNoPauseOnExceptions = 1,
  kPauseOnUnhandledExceptions,
  kPauseOnAllExceptions,
  kInvalidExceptionPauseInfo
} Dart_ExceptionPauseInfo;

class DebuggerKeyValueTrait : public AllStatic {
 public:
  typedef const Debugger* Key;
  typedef bool Value;

  struct Pair {
    Key key;
    Value value;
    Pair() : key(NULL), value(false) {}
    Pair(const Key key, const Value& value) : key(key), value(value) {}
    Pair(const Pair& other) : key(other.key), value(other.value) {}
    Pair& operator=(const Pair&) = default;
  };

  static Key KeyOf(Pair kv) { return kv.key; }
  static Value ValueOf(Pair kv) { return kv.value; }
  static intptr_t Hashcode(Key key) { return reinterpret_cast<intptr_t>(key); }
  static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
};

class DebuggerSet : public MallocDirectChainedHashMap<DebuggerKeyValueTrait> {
 public:
  typedef DebuggerKeyValueTrait::Key Key;
  typedef DebuggerKeyValueTrait::Value Value;
  typedef DebuggerKeyValueTrait::Pair Pair;

  virtual ~DebuggerSet() { Clear(); }

  void Insert(const Key& key) {
    Pair pair(key, /*value=*/true);
    MallocDirectChainedHashMap<DebuggerKeyValueTrait>::Insert(pair);
  }

  void Remove(const Key& key) {
    MallocDirectChainedHashMap<DebuggerKeyValueTrait>::Remove(key);
  }
};

class BoolCallable : public ValueObject {
 public:
  BoolCallable() {}
  virtual ~BoolCallable() {}

  virtual bool Call() = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(BoolCallable);
};

template <typename T>
class LambdaBoolCallable : public BoolCallable {
 public:
  explicit LambdaBoolCallable(T& lambda) : lambda_(lambda) {}
  bool Call() { return lambda_(); }

 private:
  T& lambda_;
  DISALLOW_COPY_AND_ASSIGN(LambdaBoolCallable);
};

class GroupDebugger {
 public:
  explicit GroupDebugger(IsolateGroup* isolate_group);
  ~GroupDebugger();

  void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);

  // Returns [nullptr] if no breakpoint exists for the given address.
  CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
  BreakpointLocation* GetBreakpointLocationFor(Debugger* debugger,
                                               uword breakpoint_address,
                                               CodeBreakpoint** pcbpt);
  CodePtr GetPatchedStubAddress(uword breakpoint_address);

  void RegisterBreakpointLocation(BreakpointLocation* location);
  void UnregisterBreakpointLocation(BreakpointLocation* location);

  void RemoveBreakpointLocation(BreakpointLocation* bpt_location);
  void UnlinkCodeBreakpoints(BreakpointLocation* bpt_location);

  // Returns true if the call at address pc is patched to point to
  // a debugger stub.
  bool HasActiveBreakpoint(uword pc);
  bool HasCodeBreakpointInFunction(const Function& func);
  bool HasCodeBreakpointInCode(const Code& code);

  bool HasBreakpointInFunction(const Function& func);
  bool HasBreakpointInCode(const Code& code);

  void SyncBreakpointLocation(BreakpointLocation* loc);

  void Pause();

  bool EnsureLocationIsInFunction(Zone* zone,
                                  const Function& function,
                                  BreakpointLocation* location);
  void NotifyCompilation(const Function& func);

  void VisitObjectPointers(ObjectPointerVisitor* visitor);

  SafepointRwLock* code_breakpoints_lock() {
    return code_breakpoints_lock_.get();
  }

  SafepointRwLock* breakpoint_locations_lock() {
    return breakpoint_locations_lock_.get();
  }

  SafepointRwLock* single_stepping_set_lock() {
    return single_stepping_set_lock_.get();
  }
  void RegisterSingleSteppingDebugger(Thread* thread, const Debugger* debugger);
  void UnregisterSingleSteppingDebugger(Thread* thread,
                                        const Debugger* debugger);

  bool RunUnderReadLockIfNeededCallable(Thread* thread,
                                        SafepointRwLock* rw_lock,
                                        BoolCallable* callable);

  template <typename T>
  bool RunUnderReadLockIfNeeded(Thread* thread,
                                SafepointRwLock* rw_lock,
                                T function) {
    LambdaBoolCallable<T> callable(function);
    return RunUnderReadLockIfNeededCallable(thread, rw_lock, &callable);
  }

  // Returns [true] if there is at least one breakpoint set in function or code.
  // Checks for both user-defined and internal temporary breakpoints.
  bool HasBreakpoint(Thread* thread, const Function& function);
  bool IsDebugging(Thread* thread, const Function& function);

 private:
  IsolateGroup* isolate_group_;

  std::unique_ptr<SafepointRwLock> code_breakpoints_lock_;
  CodeBreakpoint* code_breakpoints_;

  // Secondary list of all breakpoint_locations_(primary is in Debugger class).
  // This list is kept in sync with all the lists in Isolate Debuggers and is
  // used to quickly scan BreakpointLocations when new Function is compiled.
  std::unique_ptr<SafepointRwLock> breakpoint_locations_lock_;
  MallocGrowableArray<BreakpointLocation*> breakpoint_locations_;

  std::unique_ptr<SafepointRwLock> single_stepping_set_lock_;
  DebuggerSet single_stepping_set_;

  void RemoveUnlinkedCodeBreakpoints();
  void RegisterCodeBreakpoint(CodeBreakpoint* bpt);

  bool needs_breakpoint_cleanup_;
};

class Debugger {
 public:
  enum ResumeAction {
    kContinue,
    kStepInto,
    kStepOver,
    kStepOut,
    kStepRewind,
    kStepOverAsyncSuspension,
  };

  explicit Debugger(Isolate* isolate);
  ~Debugger();

  void NotifyIsolateCreated();
  void Shutdown();

  void NotifyDoneLoading();

  // Set breakpoint at closest location to function entry.
  Breakpoint* SetBreakpointAtEntry(const Function& target_function,
                                   bool single_shot);
  Breakpoint* SetBreakpointAtActivation(const Instance& closure,
                                        bool for_over_await);
  Breakpoint* BreakpointAtActivation(const Instance& closure);

  // TODO(turnidge): script_url may no longer be specific enough.
  Breakpoint* SetBreakpointAtLine(const String& script_url,
                                  intptr_t line_number);
  Breakpoint* SetBreakpointAtLineCol(const String& script_url,
                                     intptr_t line_number,
                                     intptr_t column_number);

  // Sets synthetic breakpoint at async_op to step over the synthetic part of
  // the stack trace.
  Breakpoint* SetBreakpointAtAsyncOp(const Function& async_op);

  BreakpointLocation* BreakpointLocationAtLineCol(const String& script_url,
                                                  intptr_t line_number,
                                                  intptr_t column_number);

  // Returns true if the breakpoint's state changed.
  bool SetBreakpointState(Breakpoint* bpt, bool enable);

  void RemoveBreakpoint(intptr_t bp_id);
  Breakpoint* GetBreakpointById(intptr_t id);

  void MaybeAsyncStepInto(const Closure& async_op);
  void AsyncStepInto(const Closure& async_op);

  void Continue();

  bool SetResumeAction(ResumeAction action,
                       intptr_t frame_index = 1,
                       const char** error = NULL);

  bool IsStepping() const { return resume_action_ != kContinue; }

  bool IsSingleStepping() const { return resume_action_ == kStepInto; }

  bool IsPaused() const { return pause_event_ != NULL; }

  bool ignore_breakpoints() const { return ignore_breakpoints_; }
  void set_ignore_breakpoints(bool ignore_breakpoints) {
    ignore_breakpoints_ = ignore_breakpoints;
  }

  // Put the isolate into single stepping mode when Dart code next runs.
  //
  // This is used by the vm service to allow the user to step while
  // paused at isolate start.
  void EnterSingleStepMode();

  // Indicates why the debugger is currently paused.  If the debugger
  // is not paused, this returns NULL.  Note that the debugger can be
  // paused for breakpoints, isolate interruption, and (sometimes)
  // exceptions.
  const ServiceEvent* PauseEvent() const { return pause_event_; }

  void SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info);
  Dart_ExceptionPauseInfo GetExceptionPauseInfo() const;

  void VisitObjectPointers(ObjectPointerVisitor* visitor);

  // Returns a stack trace with frames corresponding to invisible functions
  // omitted. CurrentStackTrace always returns a new trace on the current stack.
  // The trace returned by StackTrace may have been cached; it is suitable for
  // use when stepping, but otherwise may be out of sync with the current stack.
  DebuggerStackTrace* StackTrace();

  DebuggerStackTrace* AsyncCausalStackTrace();

  DebuggerStackTrace* AwaiterStackTrace();

  // Pause execution for a breakpoint.  Called from generated code.
  ErrorPtr PauseBreakpoint();

  // Pause execution due to stepping.  Called from generated code.
  ErrorPtr PauseStepping();

  // Pause execution due to isolate interrupt.
  ErrorPtr PauseInterrupted();

  // Pause after a reload request.
  ErrorPtr PausePostRequest();

  // Pause execution due to an uncaught exception.
  void PauseException(const Instance& exc);

  // Pause execution due to a call to the debugger() function from
  // Dart.
  void PauseDeveloper(const String& msg);

  void PrintBreakpointsToJSONArray(JSONArray* jsarr) const;
  void PrintSettingsToJSONObject(JSONObject* jsobj) const;

  static bool IsDebuggable(const Function& func);

  intptr_t limitBreakpointId() { return next_id_; }

  // Callback to the debugger to continue frame rewind, post-deoptimization.
  void RewindPostDeopt();

 private:
  ErrorPtr PauseRequest(ServiceEvent::EventKind kind);

  // Will return false if we are not at an await.
  bool SetupStepOverAsyncSuspension(const char** error);

  bool NeedsIsolateEvents();
  bool NeedsDebugEvents();

  void SendBreakpointEvent(ServiceEvent::EventKind kind, Breakpoint* bpt);

  void FindCompiledFunctions(const Script& script,
                             TokenPosition start_pos,
                             TokenPosition end_pos,
                             GrowableObjectArray* code_function_list);
  bool FindBestFit(const Script& script,
                   TokenPosition token_pos,
                   TokenPosition last_token_pos,
                   Function* best_fit);
  void DeoptimizeWorld();
  void NotifySingleStepping(bool value) const;
  BreakpointLocation* SetCodeBreakpoints(const Script& script,
                                         TokenPosition token_pos,
                                         TokenPosition last_token_pos,
                                         intptr_t requested_line,
                                         intptr_t requested_column,
                                         TokenPosition exact_token_pos,
                                         const GrowableObjectArray& functions);
  BreakpointLocation* SetBreakpoint(const Script& script,
                                    TokenPosition token_pos,
                                    TokenPosition last_token_pos,
                                    intptr_t requested_line,
                                    intptr_t requested_column,
                                    const Function& function);
  bool RemoveBreakpointFromTheList(intptr_t bp_id, BreakpointLocation** list);
  Breakpoint* GetBreakpointByIdInTheList(intptr_t id, BreakpointLocation* list);
  BreakpointLocation* GetLatentBreakpoint(const String& url,
                                          intptr_t line,
                                          intptr_t column);
  void RegisterBreakpointLocation(BreakpointLocation* bpt);
  BreakpointLocation* GetResolvedBreakpointLocation(
      const Script& script,
      TokenPosition code_token_pos);
  BreakpointLocation* GetBreakpointLocation(
      const Script& script,
      TokenPosition token_pos,
      intptr_t requested_line,
      intptr_t requested_column,
      TokenPosition code_token_pos = TokenPosition::kNoSource);

  void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
                                       JSONArray* jsarr) const;

  void SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt);

  intptr_t nextId() { return next_id_++; }

  bool ShouldPauseOnException(DebuggerStackTrace* stack_trace,
                              const Instance& exc);

  // Handles any events which pause vm execution.  Breakpoints,
  // interrupts, etc.
  void Pause(ServiceEvent* event);

  void HandleSteppingRequest(DebuggerStackTrace* stack_trace,
                             bool skip_next_step = false);

  void CacheStackTraces(DebuggerStackTrace* stack_trace,
                        DebuggerStackTrace* async_causal_stack_trace,
                        DebuggerStackTrace* awaiter_stack_trace);
  void ClearCachedStackTraces();

  void RewindToFrame(intptr_t frame_index);
  void RewindToUnoptimizedFrame(StackFrame* frame, const Code& code);
  void RewindToOptimizedFrame(StackFrame* frame,
                              const Code& code,
                              intptr_t post_deopt_frame_index);

  void ResetSteppingFramePointers();
  bool SteppedForSyntheticAsyncBreakpoint() const;
  void CleanupSyntheticAsyncBreakpoint();
  void RememberTopFrameAwaiter();
  void SetAsyncSteppingFramePointer(DebuggerStackTrace* stack_trace);
  void SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace);

  GroupDebugger* group_debugger() { return isolate_->group()->debugger(); }

  Isolate* isolate_;

  // ID number generator.
  intptr_t next_id_;

  BreakpointLocation* latent_locations_;
  BreakpointLocation* breakpoint_locations_;

  // Tells debugger what to do when resuming execution after a breakpoint.
  ResumeAction resume_action_;
  void set_resume_action(ResumeAction action);
  intptr_t resume_frame_index_;
  intptr_t post_deopt_frame_index_;

  // Do not call back to breakpoint handler if this flag is set.
  // Effectively this means ignoring breakpoints. Set when Dart code may
  // be run as a side effect of getting values of fields.
  bool ignore_breakpoints_;

  // Indicates why the debugger is currently paused.  If the debugger
  // is not paused, this is NULL.  Note that the debugger can be
  // paused for breakpoints, isolate interruption, and (sometimes)
  // exceptions.
  ServiceEvent* pause_event_;

  // Current stack trace. Valid only while IsPaused().
  DebuggerStackTrace* stack_trace_;
  DebuggerStackTrace* async_causal_stack_trace_;
  DebuggerStackTrace* awaiter_stack_trace_;

  // When stepping through code, only pause the program if the top
  // frame corresponds to this fp value, or if the top frame is
  // lower on the stack.
  uword stepping_fp_;

  // When stepping through code, do not stop more than once in the same
  // token position range.
  uword last_stepping_fp_;
  TokenPosition last_stepping_pos_;

  // Used to track the current async/async* function.
  uword async_stepping_fp_;
  ObjectPtr top_frame_awaiter_;

  // If we step while at a breakpoint, we would hit the same pc twice.
  // We use this field to let us skip the next single-step after a
  // breakpoint.
  bool skip_next_step_;

  // We keep this breakpoint alive until after the debugger does the step over
  // async continuation machinery so that we can report that we've stopped
  // at the breakpoint.
  Breakpoint* synthetic_async_breakpoint_;

  Dart_ExceptionPauseInfo exc_pause_info_;

  friend class Isolate;
  friend class BreakpointLocation;
  DISALLOW_COPY_AND_ASSIGN(Debugger);
};

class DisableBreakpointsScope : public ValueObject {
 public:
  DisableBreakpointsScope(Debugger* debugger, bool disable)
      : debugger_(debugger) {
    ASSERT(debugger_ != NULL);
    initial_state_ = debugger_->ignore_breakpoints();
    debugger_->set_ignore_breakpoints(disable);
  }

  ~DisableBreakpointsScope() {
    debugger_->set_ignore_breakpoints(initial_state_);
  }

 private:
  Debugger* debugger_;
  bool initial_state_;

  DISALLOW_COPY_AND_ASSIGN(DisableBreakpointsScope);
};

}  // namespace dart

#endif  // !defined(PRODUCT)

#endif  // RUNTIME_VM_DEBUGGER_H_
