// 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.

#include "vm/debugger.h"

#include "include/dart_api.h"

#include "platform/address_sanitizer.h"

#include "vm/code_patcher.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/deopt_instructions.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/interpreter.h"
#include "vm/json_stream.h"
#include "vm/kernel.h"
#include "vm/longjump.h"
#include "vm/message_handler.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
#include "vm/port.h"
#include "vm/runtime_entry.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
#include "vm/stack_frame.h"
#include "vm/stack_trace.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/thread_interrupter.h"
#include "vm/timeline.h"
#include "vm/token_position.h"
#include "vm/visitor.h"

namespace dart {

DEFINE_FLAG(bool,
            show_invisible_frames,
            false,
            "Show invisible frames in debugger stack traces");
DEFINE_FLAG(bool,
            trace_debugger_stacktrace,
            false,
            "Trace debugger stacktrace collection");
DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind");
DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");

DECLARE_FLAG(bool, enable_interpreter);
DECLARE_FLAG(bool, trace_deoptimization);
DECLARE_FLAG(bool, warn_on_pause_with_no_debugger);

#ifndef PRODUCT

// Create an unresolved breakpoint in given token range and script.
BreakpointLocation::BreakpointLocation(const Script& script,
                                       TokenPosition token_pos,
                                       TokenPosition end_token_pos,
                                       intptr_t requested_line_number,
                                       intptr_t requested_column_number)
    : script_(script.raw()),
      url_(script.url()),
      token_pos_(token_pos),
      end_token_pos_(end_token_pos),
      next_(NULL),
      conditions_(NULL),
      requested_line_number_(requested_line_number),
      requested_column_number_(requested_column_number),
      function_(Function::null()),
      bytecode_token_pos_(TokenPosition::kNoSource),
      code_token_pos_(TokenPosition::kNoSource) {
  ASSERT(!script.IsNull());
  ASSERT(token_pos_.IsReal());
}

// Create a latent breakpoint at given url and line number.
BreakpointLocation::BreakpointLocation(const String& url,
                                       intptr_t requested_line_number,
                                       intptr_t requested_column_number)
    : script_(Script::null()),
      url_(url.raw()),
      token_pos_(TokenPosition::kNoSource),
      end_token_pos_(TokenPosition::kNoSource),
      next_(NULL),
      conditions_(NULL),
      requested_line_number_(requested_line_number),
      requested_column_number_(requested_column_number),
      function_(Function::null()),
      bytecode_token_pos_(TokenPosition::kNoSource),
      code_token_pos_(TokenPosition::kNoSource) {
  ASSERT(requested_line_number_ >= 0);
}

BreakpointLocation::~BreakpointLocation() {
  Breakpoint* bpt = breakpoints();
  while (bpt != NULL) {
    Breakpoint* temp = bpt;
    bpt = bpt->next();
    delete temp;
  }
}

bool BreakpointLocation::AnyEnabled() const {
  return breakpoints() != NULL;
}

void BreakpointLocation::SetResolved(bool in_bytecode,
                                     const Function& func,
                                     TokenPosition token_pos) {
  ASSERT(!IsLatent());
  ASSERT(func.script() == script_);
  ASSERT((func.token_pos() <= token_pos) &&
         (token_pos <= func.end_token_pos()));
  ASSERT(func.is_debuggable());
  function_ = func.raw();
  token_pos_ = token_pos;
  end_token_pos_ = token_pos;
  if (in_bytecode) {
    bytecode_token_pos_ = token_pos;
  } else {
    code_token_pos_ = token_pos;
  }
}

// Returned resolved pos is either in code or in bytecode.
void BreakpointLocation::GetCodeLocation(Script* script,
                                         TokenPosition* pos) const {
  if (IsLatent()) {
    *script = Script::null();
    *pos = TokenPosition::kNoSource;
  } else {
    *script = this->script();
    *pos = token_pos_;
  }
}

void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
  // Only latent breakpoints can be moved.
  ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
  bpt_location_ = new_bpt_location;
}

void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&closure_));
}

void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&script_));
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&url_));
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));

  Breakpoint* bpt = conditions_;
  while (bpt != NULL) {
    bpt->VisitObjectPointers(visitor);
    bpt = bpt->next();
  }
}

void Breakpoint::PrintJSON(JSONStream* stream) {
  JSONObject jsobj(stream);
  jsobj.AddProperty("type", "Breakpoint");

  jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
  jsobj.AddProperty("breakpointNumber", id());
  if (is_synthetic_async()) {
    jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async());
  }
  jsobj.AddProperty("resolved", bpt_location_->IsResolved());
  if (bpt_location_->IsResolved()) {
    jsobj.AddLocation(bpt_location_);
  } else {
    jsobj.AddUnresolvedLocation(bpt_location_);
  }
}

void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&bytecode_));
#if !defined(TARGET_ARCH_DBC)
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
#endif
}

ActivationFrame::ActivationFrame(uword pc,
                                 uword fp,
                                 uword sp,
                                 const Code& code,
                                 const Array& deopt_frame,
                                 intptr_t deopt_frame_offset,
                                 ActivationFrame::Kind kind)
    : pc_(pc),
      fp_(fp),
      sp_(sp),
      ctx_(Context::ZoneHandle()),
      code_(Code::ZoneHandle(code.raw())),
      bytecode_(Bytecode::ZoneHandle()),
      function_(Function::ZoneHandle(code.function())),
      live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
      token_pos_initialized_(false),
      token_pos_(TokenPosition::kNoSource),
      try_index_(-1),
      deopt_id_(DeoptId::kNone),
      line_number_(-1),
      column_number_(-1),
      context_level_(-1),
      deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
      deopt_frame_offset_(deopt_frame_offset),
      kind_(kind),
      vars_initialized_(false),
      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
      desc_indices_(8),
      pc_desc_(PcDescriptors::ZoneHandle()) {
  ASSERT(!function_.IsNull());
}

#if !defined(DART_PRECOMPILED_RUNTIME)
ActivationFrame::ActivationFrame(uword pc,
                                 uword fp,
                                 uword sp,
                                 const Bytecode& bytecode,
                                 ActivationFrame::Kind kind)
    : pc_(pc),
      fp_(fp),
      sp_(sp),
      ctx_(Context::ZoneHandle()),
      code_(Code::ZoneHandle()),
      bytecode_(Bytecode::ZoneHandle(bytecode.raw())),
      function_(Function::ZoneHandle(bytecode.function())),
      live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
      token_pos_initialized_(false),
      token_pos_(TokenPosition::kNoSource),
      try_index_(-1),
      deopt_id_(DeoptId::kNone),
      line_number_(-1),
      column_number_(-1),
      context_level_(-1),
      deopt_frame_(Array::ZoneHandle()),
      deopt_frame_offset_(0),
      kind_(kind),
      vars_initialized_(false),
      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
      desc_indices_(8),
      pc_desc_(PcDescriptors::ZoneHandle()) {
  ASSERT(!function_.IsNull());  // Frames with bytecode stubs should be skipped.
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ActivationFrame::ActivationFrame(Kind kind)
    : pc_(0),
      fp_(0),
      sp_(0),
      ctx_(Context::ZoneHandle()),
      code_(Code::ZoneHandle()),
      bytecode_(Bytecode::ZoneHandle()),
      function_(Function::ZoneHandle()),
      live_frame_(kind == kRegular),
      token_pos_initialized_(false),
      token_pos_(TokenPosition::kNoSource),
      try_index_(-1),
      line_number_(-1),
      column_number_(-1),
      context_level_(-1),
      deopt_frame_(Array::ZoneHandle()),
      deopt_frame_offset_(0),
      kind_(kind),
      vars_initialized_(false),
      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
      desc_indices_(8),
      pc_desc_(PcDescriptors::ZoneHandle()) {}

ActivationFrame::ActivationFrame(const Closure& async_activation)
    : pc_(0),
      fp_(0),
      sp_(0),
      ctx_(Context::ZoneHandle()),
      code_(Code::ZoneHandle()),
      bytecode_(Bytecode::ZoneHandle()),
      function_(Function::ZoneHandle()),
      live_frame_(false),
      token_pos_initialized_(false),
      token_pos_(TokenPosition::kNoSource),
      try_index_(-1),
      line_number_(-1),
      column_number_(-1),
      context_level_(-1),
      deopt_frame_(Array::ZoneHandle()),
      deopt_frame_offset_(0),
      kind_(kAsyncActivation),
      vars_initialized_(false),
      var_descriptors_(LocalVarDescriptors::ZoneHandle()),
      desc_indices_(8),
      pc_desc_(PcDescriptors::ZoneHandle()) {
  // Extract the function and the code from the asynchronous activation.
  function_ = async_activation.function();
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (!function_.HasCode() && function_.HasBytecode()) {
    bytecode_ = function_.bytecode();
  }
#endif
  if (bytecode_.IsNull()) {
    // Force-optimize functions should not be debuggable.
    ASSERT(!function_.ForceOptimize());
    function_.EnsureHasCompiledUnoptimizedCode();
    code_ = function_.unoptimized_code();
  }
  ctx_ = async_activation.context();
  ASSERT(fp_ == 0);
  ASSERT(!ctx_.IsNull());
}

bool Debugger::NeedsIsolateEvents() {
  return !Isolate::IsVMInternalIsolate(isolate_) &&
         Service::isolate_stream.enabled();
}

bool Debugger::NeedsDebugEvents() {
  ASSERT(!Isolate::IsVMInternalIsolate(isolate_));
  return FLAG_warn_on_pause_with_no_debugger || Service::debug_stream.enabled();
}

void Debugger::InvokeEventHandler(ServiceEvent* event) {
  ASSERT(!event->IsPause());  // For pause events, call Pause instead.
  Service::HandleEvent(event);
}

RawError* Debugger::PauseInterrupted() {
  return PauseRequest(ServiceEvent::kPauseInterrupted);
}

RawError* Debugger::PausePostRequest() {
  return PauseRequest(ServiceEvent::kPausePostRequest);
}

RawError* Debugger::PauseRequest(ServiceEvent::EventKind kind) {
  if (ignore_breakpoints_ || IsPaused()) {
    // We don't let the isolate get interrupted if we are already
    // paused or ignoring breakpoints.
    return Thread::Current()->StealStickyError();
  }
  ServiceEvent event(isolate_, kind);
  DebuggerStackTrace* trace = CollectStackTrace();
  if (trace->Length() > 0) {
    event.set_top_frame(trace->FrameAt(0));
  }
  CacheStackTraces(trace, CollectAsyncCausalStackTrace(),
                   CollectAwaiterReturnStackTrace());
  resume_action_ = kContinue;
  Pause(&event);
  HandleSteppingRequest(trace);
  ClearCachedStackTraces();

  // If any error occurred while in the debug message loop, return it here.
  NoSafepointScope no_safepoint;
  RawError* error = Thread::Current()->StealStickyError();
  ASSERT((error == Error::null()) || error->IsUnwindError());
  return error;
}

void Debugger::SendBreakpointEvent(ServiceEvent::EventKind kind,
                                   Breakpoint* bpt) {
  if (NeedsDebugEvents()) {
    // TODO(turnidge): Currently we send single-shot breakpoint events
    // to the vm service.  Do we want to change this?
    ServiceEvent event(isolate_, kind);
    event.set_breakpoint(bpt);
    InvokeEventHandler(&event);
  }
}

void BreakpointLocation::AddBreakpoint(Breakpoint* bpt, Debugger* dbg) {
  bpt->set_next(breakpoints());
  set_breakpoints(bpt);

  dbg->SyncBreakpointLocation(this);
  dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
}

Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) {
  Breakpoint* bpt = breakpoints();
  while (bpt != NULL) {
    if (bpt->IsRepeated()) break;
    bpt = bpt->next();
  }
  if (bpt == NULL) {
    bpt = new Breakpoint(dbg->nextId(), this);
    bpt->SetIsRepeated();
    AddBreakpoint(bpt, dbg);
  }
  return bpt;
}

Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) {
  Breakpoint* bpt = breakpoints();
  while (bpt != NULL) {
    if (bpt->IsSingleShot()) break;
    bpt = bpt->next();
  }
  if (bpt == NULL) {
    bpt = new Breakpoint(dbg->nextId(), this);
    bpt->SetIsSingleShot();
    AddBreakpoint(bpt, dbg);
  }
  return bpt;
}

Breakpoint* BreakpointLocation::AddPerClosure(Debugger* dbg,
                                              const Instance& closure,
                                              bool for_over_await) {
  Breakpoint* bpt = NULL;
  // Do not reuse existing breakpoints for stepping over await clauses.
  // A second async step-over command will set a new breakpoint before
  // the existing one gets deleted when first async step-over resumes.
  if (!for_over_await) {
    bpt = breakpoints();
    while (bpt != NULL) {
      if (bpt->IsPerClosure() && (bpt->closure() == closure.raw())) break;
      bpt = bpt->next();
    }
  }
  if (bpt == NULL) {
    bpt = new Breakpoint(dbg->nextId(), this);
    bpt->SetIsPerClosure(closure);
    bpt->set_is_synthetic_async(for_over_await);
    AddBreakpoint(bpt, dbg);
  }
  return bpt;
}

const char* Debugger::QualifiedFunctionName(const Function& func) {
  const String& func_name = String::Handle(func.name());
  Class& func_class = Class::Handle(func.Owner());
  String& class_name = String::Handle(func_class.Name());

  return OS::SCreate(Thread::Current()->zone(), "%s%s%s",
                     func_class.IsTopLevel() ? "" : class_name.ToCString(),
                     func_class.IsTopLevel() ? "" : ".", func_name.ToCString());
}

// Returns true if the function |func| overlaps the token range
// [|token_pos|, |end_token_pos|] in |script|.
static bool FunctionOverlaps(const Function& func,
                             const Script& script,
                             TokenPosition token_pos,
                             TokenPosition end_token_pos) {
  TokenPosition func_start = func.token_pos();
  if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
      ((token_pos <= func_start) && (func_start <= end_token_pos))) {
    // Check script equality second because it allocates
    // handles as a side effect.
    return func.script() == script.raw();
  }
  return false;
}

static bool IsImplicitFunction(const Function& func) {
  switch (func.kind()) {
    case RawFunction::kImplicitGetter:
    case RawFunction::kImplicitSetter:
    case RawFunction::kImplicitStaticGetter:
    case RawFunction::kStaticFieldInitializer:
    case RawFunction::kMethodExtractor:
    case RawFunction::kNoSuchMethodDispatcher:
    case RawFunction::kInvokeFieldDispatcher:
    case RawFunction::kIrregexpFunction:
      return true;
    default:
      if (func.token_pos() == func.end_token_pos()) {
        // |func| could be an implicit constructor for example.
        return true;
      }
  }
  return false;
}

bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
  if (!func.HasCode() && !func.HasBytecode()) {
    // If the function is not compiled yet, just check whether there
    // is a user-defined breakpoint that falls into the token
    // range of the function. This may be a false positive: the breakpoint
    // might be inside a local closure.
    Script& script = Script::Handle(zone);
    BreakpointLocation* sbpt = breakpoint_locations_;
    while (sbpt != NULL) {
      script = sbpt->script();
      if (FunctionOverlaps(func, script, sbpt->token_pos(),
                           sbpt->end_token_pos())) {
        return true;
      }
      sbpt = sbpt->next_;
    }
    return false;
  }
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != NULL) {
    if (func.raw() == cbpt->function()) {
      return true;
    }
    cbpt = cbpt->next_;
  }
  return false;
}

bool Debugger::HasBreakpoint(const Code& code) {
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != NULL) {
    if (code.raw() == cbpt->code_) {
      return true;
    }
    cbpt = cbpt->next_;
  }
  return false;
}

void Debugger::PrintBreakpointsToJSONArray(JSONArray* jsarr) const {
  PrintBreakpointsListToJSONArray(breakpoint_locations_, jsarr);
  PrintBreakpointsListToJSONArray(latent_locations_, jsarr);
}

void Debugger::PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
                                               JSONArray* jsarr) const {
  while (sbpt != NULL) {
    Breakpoint* bpt = sbpt->breakpoints();
    while (bpt != NULL) {
      jsarr->AddValue(bpt);
      bpt = bpt->next();
    }
    sbpt = sbpt->next_;
  }
}

void Debugger::PrintSettingsToJSONObject(JSONObject* jsobj) const {
  // This won't cut it when we support filtering by class, etc.
  switch (GetExceptionPauseInfo()) {
    case kNoPauseOnExceptions:
      jsobj->AddProperty("_exceptions", "none");
      break;
    case kPauseOnAllExceptions:
      jsobj->AddProperty("_exceptions", "all");
      break;
    case kPauseOnUnhandledExceptions:
      jsobj->AddProperty("_exceptions", "unhandled");
      break;
    default:
      UNREACHABLE();
  }
}

RawString* ActivationFrame::QualifiedFunctionName() {
  return String::New(Debugger::QualifiedFunctionName(function()));
}

RawString* ActivationFrame::SourceUrl() {
  const Script& script = Script::Handle(SourceScript());
  return script.url();
}

RawScript* ActivationFrame::SourceScript() {
  return function().script();
}

RawLibrary* ActivationFrame::Library() {
  const Class& cls = Class::Handle(function().origin());
  return cls.library();
}

void ActivationFrame::GetPcDescriptors() {
  ASSERT(!IsInterpreted());  // We need to set try_index_ simultaneously.
  if (pc_desc_.IsNull()) {
    pc_desc_ = code().pc_descriptors();
    ASSERT(!pc_desc_.IsNull());
  }
}

// Compute token_pos_ and token_pos_initialized_.
// If not IsInterpreted(), then also compute try_index_ and deopt_id_.
TokenPosition ActivationFrame::TokenPos() {
  if (!token_pos_initialized_) {
    token_pos_initialized_ = true;
    if (IsInterpreted()) {
      token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
      return token_pos_;
    }
    token_pos_ = TokenPosition::kNoSource;
    GetPcDescriptors();
    PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
    const uword pc_offset = pc_ - code().PayloadStart();
    while (iter.MoveNext()) {
      if (iter.PcOffset() == pc_offset) {
        try_index_ = iter.TryIndex();
        token_pos_ = iter.TokenPos();
        deopt_id_ = iter.DeoptId();
        break;
      }
    }
  }
  return token_pos_;
}

intptr_t ActivationFrame::TryIndex() {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (IsInterpreted()) {
    if (pc_desc_.IsNull()) {
      ASSERT(try_index_ == -1);
      pc_desc_ = bytecode().pc_descriptors();
      try_index_ = bytecode().GetTryIndexAtPc(pc_);
    }
    return try_index_;
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  if (!token_pos_initialized_) {
    TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
  }
  return try_index_;
}

intptr_t ActivationFrame::DeoptId() {
  ASSERT(!IsInterpreted());
  if (!token_pos_initialized_) {
    TokenPos();  // Side effect: computes token_pos_initialized_, try_index_.
  }
  return deopt_id_;
}

intptr_t ActivationFrame::LineNumber() {
  // Compute line number lazily since it causes scanning of the script.
  if ((line_number_ < 0) && TokenPos().IsSourcePosition()) {
    const TokenPosition token_pos = TokenPos().SourcePosition();
    const Script& script = Script::Handle(SourceScript());
    script.GetTokenLocation(token_pos, &line_number_, NULL);
  }
  return line_number_;
}

intptr_t ActivationFrame::ColumnNumber() {
  // Compute column number lazily since it causes scanning of the script.
  if ((column_number_ < 0) && TokenPos().IsSourcePosition()) {
    const TokenPosition token_pos = TokenPos().SourcePosition();
    const Script& script = Script::Handle(SourceScript());
    if (script.HasSource()) {
      script.GetTokenLocation(token_pos, &line_number_, &column_number_);
    } else {
      column_number_ = -1;
    }
  }
  return column_number_;
}

void ActivationFrame::GetVarDescriptors() {
  if (var_descriptors_.IsNull()) {
    if (IsInterpreted()) {
      var_descriptors_ = bytecode().GetLocalVarDescriptors();
      ASSERT(!var_descriptors_.IsNull());
      return;
    }
    Code& unoptimized_code = Code::Handle(function().unoptimized_code());
    if (unoptimized_code.IsNull()) {
      Thread* thread = Thread::Current();
      Zone* zone = thread->zone();
      const Error& error = Error::Handle(
          zone, Compiler::EnsureUnoptimizedCode(thread, function()));
      if (!error.IsNull()) {
        Exceptions::PropagateError(error);
      }
      unoptimized_code = function().unoptimized_code();
    }
    ASSERT(!unoptimized_code.IsNull());
    var_descriptors_ = unoptimized_code.GetLocalVarDescriptors();
    ASSERT(!var_descriptors_.IsNull());
  }
}

bool ActivationFrame::IsDebuggable() const {
  return Debugger::IsDebuggable(function());
}

void ActivationFrame::PrintDescriptorsError(const char* message) {
  OS::PrintErr("Bad descriptors: %s\n", message);
  OS::PrintErr("function %s\n", function().ToQualifiedCString());
  OS::PrintErr("pc_ %" Px "\n", pc_);
  OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
  OS::PrintErr("context_level_ %" Px "\n", context_level_);
  DisassembleToStdout formatter;
  if (function().is_declared_in_bytecode()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(function().HasBytecode());
    const Bytecode& bytecode = Bytecode::Handle(function().bytecode());
    bytecode.Disassemble(&formatter);
#else
    UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  } else {
    code().Disassemble(&formatter);
    PcDescriptors::Handle(code().pc_descriptors()).Print();
  }
  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                            Thread::Current(),
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  while (frame != NULL) {
    OS::PrintErr("%s\n", frame->ToCString());
    frame = frames.NextFrame();
  }
  OS::Abort();
}

// Calculate the context level at the current bytecode pc or code deopt id
// of the frame.
intptr_t ActivationFrame::ContextLevel() {
  const Context& ctx = GetSavedCurrentContext();
  if (context_level_ < 0 && !ctx.IsNull()) {
    ASSERT(IsInterpreted() || !code_.is_optimized());
    if (function().is_declared_in_bytecode()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
      // Although this activation frame may not have bytecode, its code was
      // compiled from bytecode.
      if (!IsInterpreted()) {
        // TODO(regis): If this frame was compiled from bytecode, pc_ does not
        // reflect a bytecode pc. How do we map to one? We should generate new
        // LocalVarDescriptors for code compiled from bytecode so that they
        // provide deopt_id to context level mapping.
        UNIMPLEMENTED();
      }
      ASSERT(function().HasBytecode());
      Thread* thread = Thread::Current();
      Zone* zone = thread->zone();
      Bytecode& bytecode = Bytecode::Handle(zone, function().bytecode());
      if (!bytecode.HasLocalVariablesInfo()) {
        PrintDescriptorsError("Missing local variables info");
      }
      intptr_t pc_offset = pc_ - bytecode.PayloadStart();
      kernel::BytecodeLocalVariablesIterator local_vars(zone, bytecode);
      while (local_vars.MoveNext()) {
        if (local_vars.Kind() ==
            kernel::BytecodeLocalVariablesIterator::kScope) {
          if (local_vars.StartPC() <= pc_offset &&
              pc_offset < local_vars.EndPC()) {
            context_level_ = local_vars.ContextLevel();
            break;
          }
        }
      }
      if (context_level_ < 0 && function().IsClosureFunction()) {
        // Obtain the context level from the parent function.
        // TODO(alexmarkov): Define scope which includes the whole closure body.
        Function& parent = Function::Handle(zone, function().parent_function());
        intptr_t depth = 1;
        do {
          bytecode = parent.bytecode();
          kernel::BytecodeLocalVariablesIterator local_vars(zone, bytecode);
          while (local_vars.MoveNext()) {
            if (local_vars.Kind() ==
                kernel::BytecodeLocalVariablesIterator::kScope) {
              if (local_vars.StartTokenPos() <= TokenPos() &&
                  TokenPos() <= local_vars.EndTokenPos()) {
                context_level_ = local_vars.ContextLevel() + depth;
                break;
              }
            }
          }
          if (context_level_ >= 0) break;
          parent = parent.parent_function();
          depth++;
        } while (!parent.IsNull());
      }
      if (context_level_ < 0) {
        PrintDescriptorsError("Missing context level in local variables info");
      }
#else
      UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    } else {
      ASSERT(!code_.is_optimized());
      GetVarDescriptors();
      intptr_t deopt_id = DeoptId();
      if (deopt_id == DeoptId::kNone) {
        PrintDescriptorsError("Missing deopt id");
      }
      intptr_t var_desc_len = var_descriptors_.Length();
      bool found = false;
      for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
        RawLocalVarDescriptors::VarInfo var_info;
        var_descriptors_.GetInfo(cur_idx, &var_info);
        const int8_t kind = var_info.kind();
        if ((kind == RawLocalVarDescriptors::kContextLevel) &&
            (deopt_id >= var_info.begin_pos.value()) &&
            (deopt_id <= var_info.end_pos.value())) {
          context_level_ = var_info.index();
          found = true;
          break;
        }
      }
      if (!found) {
        PrintDescriptorsError("Missing context level");
      }
      ASSERT(context_level_ >= 0);
    }
  }
  return context_level_;
}

RawObject* ActivationFrame::GetAsyncContextVariable(const String& name) {
  if (!function_.IsAsyncClosure() && !function_.IsAsyncGenClosure()) {
    return Object::null();
  }
  GetVarDescriptors();
  intptr_t var_desc_len = var_descriptors_.Length();
  for (intptr_t i = 0; i < var_desc_len; i++) {
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(i, &var_info);
    if (var_descriptors_.GetName(i) == name.raw()) {
      const int8_t kind = var_info.kind();
      if (!live_frame_) {
        ASSERT(kind == RawLocalVarDescriptors::kContextVar);
      }
      const auto variable_index = VariableIndex(var_info.index());
      if (kind == RawLocalVarDescriptors::kStackVar) {
        return GetStackVar(variable_index);
      } else {
        ASSERT(kind == RawLocalVarDescriptors::kContextVar);
        if (!live_frame_) {
          ASSERT(!ctx_.IsNull());
          return GetRelativeContextVar(var_info.scope_id,
                                       variable_index.value(),
                                       /* frame_ctx_level = */ 0);
        }
        return GetContextVar(var_info.scope_id, variable_index.value());
      }
    }
  }
  return Object::null();
}

RawObject* ActivationFrame::GetAsyncCompleter() {
  return GetAsyncContextVariable(Symbols::AsyncCompleter());
}

RawObject* ActivationFrame::GetAsyncCompleterAwaiter(const Object& completer) {
  DEBUG_ASSERT(Thread::Current()->TopErrorHandlerIsExitFrame());

  Object& future = Object::Handle();
  const Class& completer_cls = Class::Handle(completer.clazz());
  ASSERT(!completer_cls.IsNull());
  const Function& future_getter = Function::Handle(
      completer_cls.LookupGetterFunction(Symbols::CompleterFuture()));
  ASSERT(!future_getter.IsNull());
  const Array& args = Array::Handle(Array::New(1));
  args.SetAt(0, Instance::Cast(completer));
  future = DartEntry::InvokeFunction(future_getter, args);
  if (future.IsError()) {
    Exceptions::PropagateError(Error::Cast(future));
  }
  if (future.IsNull()) {
    // The completer object may not be fully initialized yet.
    return Object::null();
  }
  const Class& future_cls = Class::Handle(future.clazz());
  ASSERT(!future_cls.IsNull());
  const Field& awaiter_field = Field::Handle(
      future_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
  ASSERT(!awaiter_field.IsNull());
  return Instance::Cast(future).GetField(awaiter_field);
}

RawObject* ActivationFrame::GetAsyncStreamControllerStream() {
  return GetAsyncContextVariable(Symbols::ControllerStream());
}

RawObject* ActivationFrame::GetAsyncStreamControllerStreamAwaiter(
    const Object& stream) {
  const Class& stream_cls = Class::Handle(stream.clazz());
  ASSERT(!stream_cls.IsNull());
  const Class& stream_impl_cls = Class::Handle(stream_cls.SuperClass());
  const Field& awaiter_field = Field::Handle(
      stream_impl_cls.LookupInstanceFieldAllowPrivate(Symbols::_Awaiter()));
  ASSERT(!awaiter_field.IsNull());
  return Instance::Cast(stream).GetField(awaiter_field);
}

RawObject* ActivationFrame::GetAsyncAwaiter() {
  const Object& async_stream_controller_stream =
      Object::Handle(GetAsyncStreamControllerStream());
  if (!async_stream_controller_stream.IsNull()) {
    return GetAsyncStreamControllerStreamAwaiter(
        async_stream_controller_stream);
  }
  const Object& completer = Object::Handle(GetAsyncCompleter());
  if (!completer.IsNull()) {
    return GetAsyncCompleterAwaiter(completer);
  }
  return Object::null();
}

RawObject* ActivationFrame::GetCausalStack() {
  return GetAsyncContextVariable(Symbols::AsyncStackTraceVar());
}

bool ActivationFrame::HandlesException(const Instance& exc_obj) {
  if ((kind_ == kAsyncSuspensionMarker) || (kind_ == kAsyncCausal)) {
    // These frames are historical.
    return false;
  }
  intptr_t try_index = TryIndex();
  if (try_index < 0) {
    return false;
  }
  ExceptionHandlers& handlers = ExceptionHandlers::Handle();
  Array& handled_types = Array::Handle();
  AbstractType& type = Type::Handle();
  const bool is_async =
      function().IsAsyncClosure() || function().IsAsyncGenClosure();
  if (IsInterpreted()) {
    handlers = bytecode().exception_handlers();
  } else {
    handlers = code().exception_handlers();
  }
  ASSERT(!handlers.IsNull());
  intptr_t num_handlers_checked = 0;
  while (try_index != kInvalidTryIndex) {
    // Detect circles in the exception handler data.
    num_handlers_checked++;
    ASSERT(num_handlers_checked <= handlers.num_entries());
    // Only consider user written handlers for async methods.
    if (!is_async || !handlers.IsGenerated(try_index)) {
      handled_types = handlers.GetHandledTypes(try_index);
      const intptr_t num_types = handled_types.Length();
      for (intptr_t k = 0; k < num_types; k++) {
        type ^= handled_types.At(k);
        ASSERT(!type.IsNull());
        // Uninstantiated types are not added to ExceptionHandlers data.
        ASSERT(type.IsInstantiated());
        if (type.IsDynamicType()) {
          return true;
        }
        if (exc_obj.IsInstanceOf(type, Object::null_type_arguments(),
                                 Object::null_type_arguments())) {
          return true;
        }
      }
    }
    try_index = handlers.OuterTryIndex(try_index);
  }
  return false;
}

void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
  // Attempt to determine the token pos and try index from the async closure.
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const Script& script = Script::Handle(zone, function().script());

  ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure());
  // This should only be called on frames that aren't active on the stack.
  ASSERT(fp() == 0);

  ASSERT(script.kind() == RawScript::kKernelTag);
  const Array& await_to_token_map =
      Array::Handle(zone, script.yield_positions());
  if (await_to_token_map.IsNull()) {
    // No mapping.
    return;
  }
  GetVarDescriptors();
  intptr_t var_desc_len = var_descriptors_.Length();
  intptr_t await_jump_var = -1;
  for (intptr_t i = 0; i < var_desc_len; i++) {
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(i, &var_info);
    const int8_t kind = var_info.kind();
    if (var_descriptors_.GetName(i) == Symbols::AwaitJumpVar().raw()) {
      ASSERT(kind == RawLocalVarDescriptors::kContextVar);
      ASSERT(!ctx_.IsNull());
      Object& await_jump_index = Object::Handle(ctx_.At(var_info.index()));
      ASSERT(await_jump_index.IsSmi());
      await_jump_var = Smi::Cast(await_jump_index).Value();
    }
  }
  if (await_jump_var < 0) {
    return;
  }
  intptr_t await_to_token_map_index = await_jump_var - 1;
  // yield_positions returns all yield positions for the script (in sorted
  // order).
  // We thus need to offset the function start to get the actual index.
  if (!function_.token_pos().IsReal()) {
    return;
  }
  const intptr_t function_start = function_.token_pos().value();
  for (intptr_t i = 0;
       i < await_to_token_map.Length() &&
       Smi::Value(reinterpret_cast<RawSmi*>(await_to_token_map.At(i))) <
           function_start;
       i++) {
    await_to_token_map_index++;
  }

  if (await_to_token_map_index >= await_to_token_map.Length()) {
    return;
  }

  const Object& token_pos =
      Object::Handle(await_to_token_map.At(await_to_token_map_index));
  if (token_pos.IsNull()) {
    return;
  }
  ASSERT(token_pos.IsSmi());
  token_pos_ = TokenPosition(Smi::Cast(token_pos).Value());
  token_pos_initialized_ = true;
  if (IsInterpreted()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
    // In order to determine the try index, we need to map the token position
    // to a pc offset, and then a pc offset to the try index.
    // TODO(regis): Should we set the token position fields in pc descriptors?
    uword pc_offset = kUwordMax;
    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode());
    while (iter.MoveNext()) {
      // PcOffsets are monotonic in source positions, so we get the lowest one.
      if (iter.TokenPos() == token_pos_) {
        pc_offset = iter.PcOffset();
        break;
      }
    }
    if (pc_offset < kUwordMax) {
      try_index_ =
          bytecode().GetTryIndexAtPc(bytecode().PayloadStart() + pc_offset);
    }
#else
    UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    return;
  }
  GetPcDescriptors();
  PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
  while (iter.MoveNext()) {
    if (iter.TokenPos() == token_pos_) {
      // Match the lowest try index at this token position.
      // TODO(johnmccutchan): Is this heuristic precise enough?
      if (iter.TryIndex() != kInvalidTryIndex) {
        if ((try_index_ == -1) || (iter.TryIndex() < try_index_)) {
          try_index_ = iter.TryIndex();
        }
      }
    }
  }
}

bool ActivationFrame::IsAsyncMachinery() const {
  Isolate* isolate = Isolate::Current();
  if (function_.raw() == isolate->object_store()->complete_on_async_return()) {
    // We are completing an async function's completer.
    return true;
  }
  if (function_.Owner() ==
      isolate->object_store()->async_star_stream_controller()) {
    // We are inside the async* stream controller code.
    return true;
  }
  return false;
}

// Get the saved current context of this activation.
const Context& ActivationFrame::GetSavedCurrentContext() {
  if (!ctx_.IsNull()) return ctx_;
  GetVarDescriptors();
  intptr_t var_desc_len = var_descriptors_.Length();
  Object& obj = Object::Handle();
  for (intptr_t i = 0; i < var_desc_len; i++) {
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(i, &var_info);
    const int8_t kind = var_info.kind();
    if (kind == RawLocalVarDescriptors::kSavedCurrentContext) {
      if (FLAG_trace_debugger_stacktrace) {
        OS::PrintErr("\tFound saved current ctx at index %d\n",
                     var_info.index());
      }
      const auto variable_index = VariableIndex(var_info.index());
      obj = GetStackVar(variable_index);
      if (obj.IsClosure()) {
        ASSERT(function().name() == Symbols::Call().raw());
        ASSERT(function().IsInvokeFieldDispatcher());
        // Closure.call frames.
        ctx_ = Closure::Cast(obj).context();
      } else if (obj.IsContext()) {
        ctx_ = Context::Cast(obj).raw();
      } else {
        ASSERT(obj.IsNull());
      }
      return ctx_;
    }
  }
  return ctx_;
}

RawObject* ActivationFrame::GetAsyncOperation() {
  GetVarDescriptors();
  intptr_t var_desc_len = var_descriptors_.Length();
  for (intptr_t i = 0; i < var_desc_len; i++) {
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(i, &var_info);
    if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) {
      const int8_t kind = var_info.kind();
      const auto variable_index = VariableIndex(var_info.index());
      if (kind == RawLocalVarDescriptors::kStackVar) {
        return GetStackVar(variable_index);
      } else {
        ASSERT(kind == RawLocalVarDescriptors::kContextVar);
        return GetContextVar(var_info.scope_id, variable_index.value());
      }
    }
  }
  return Object::null();
}

ActivationFrame* DebuggerStackTrace::GetHandlerFrame(
    const Instance& exc_obj) const {
  for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) {
    ActivationFrame* frame = FrameAt(frame_index);
    if (frame->HandlesException(exc_obj)) {
      return frame;
    }
  }
  return NULL;
}

void ActivationFrame::GetDescIndices() {
  if (vars_initialized_) {
    return;
  }
  GetVarDescriptors();

  TokenPosition activation_token_pos = TokenPos();
  if (!activation_token_pos.IsDebugPause() || !live_frame_) {
    // We don't have a token position for this frame, so can't determine
    // which variables are visible.
    vars_initialized_ = true;
    return;
  }

  GrowableArray<String*> var_names(8);
  intptr_t var_desc_len = var_descriptors_.Length();
  for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
    ASSERT(var_names.length() == desc_indices_.length());
    RawLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(cur_idx, &var_info);
    const int8_t kind = var_info.kind();
    if ((kind != RawLocalVarDescriptors::kStackVar) &&
        (kind != RawLocalVarDescriptors::kContextVar)) {
      continue;
    }
    if ((var_info.begin_pos <= activation_token_pos) &&
        (activation_token_pos <= var_info.end_pos)) {
      if ((kind == RawLocalVarDescriptors::kContextVar) &&
          (ContextLevel() < var_info.scope_id)) {
        // The variable is textually in scope but the context level
        // at the activation frame's PC is lower than the context
        // level of the variable. The context containing the variable
        // has already been removed from the chain. This can happen when we
        // break at a return statement, since the contexts get discarded
        // before the debugger gets called.
        continue;
      }
      // The current variable is textually in scope. Now check whether
      // there is another local variable with the same name that shadows
      // or is shadowed by this variable.
      String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
      intptr_t indices_len = desc_indices_.length();
      bool name_match_found = false;
      for (intptr_t i = 0; i < indices_len; i++) {
        if (var_name.Equals(*var_names[i])) {
          // Found two local variables with the same name. Now determine
          // which one is shadowed.
          name_match_found = true;
          RawLocalVarDescriptors::VarInfo i_var_info;
          var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
          if (i_var_info.begin_pos < var_info.begin_pos) {
            // The variable we found earlier is in an outer scope
            // and is shadowed by the current variable. Replace the
            // descriptor index of the previously found variable
            // with the descriptor index of the current variable.
            desc_indices_[i] = cur_idx;
          } else {
            // The variable we found earlier is in an inner scope
            // and shadows the current variable. Skip the current
            // variable. (Nothing to do.)
          }
          break;  // Stop looking for name matches.
        }
      }
      if (!name_match_found) {
        // No duplicate name found. Add the current descriptor index to the
        // list of visible variables.
        desc_indices_.Add(cur_idx);
        var_names.Add(&var_name);
      }
    }
  }
  vars_initialized_ = true;
}

intptr_t ActivationFrame::NumLocalVariables() {
  GetDescIndices();
  return desc_indices_.length();
}

DART_FORCE_INLINE static RawObject* GetVariableValue(uword addr) {
  return *reinterpret_cast<RawObject**>(addr);
}

// Caution: GetParameter only works for fixed parameters.
RawObject* ActivationFrame::GetParameter(intptr_t index) {
  intptr_t num_parameters = function().num_fixed_parameters();
  ASSERT(0 <= index && index < num_parameters);

  if (IsInterpreted()) {
    if (function().NumOptionalParameters() > 0) {
      // Note that we do not access optional but only fixed parameters, hence
      // we do not need to replicate the logic of IndexFor() in bytecode reader.
      return GetVariableValue(fp() + index * kWordSize);
    } else {
      return GetVariableValue(
          fp() - (kKBCParamEndSlotFromFp + num_parameters - index) * kWordSize);
    }
  }

  if (function().NumOptionalParameters() > 0) {
    // If the function has optional parameters, the first positional parameter
    // can be in a number of places in the caller's frame depending on how many
    // were actually supplied at the call site, but they are copied to a fixed
    // place in the callee's frame.

    return GetVariableValue(LocalVarAddress(
        fp(), runtime_frame_layout.FrameSlotForVariableIndex(-index)));
  } else {
    intptr_t reverse_index = num_parameters - index;
    return GetVariableValue(ParamAddress(fp(), reverse_index));
  }
}

RawObject* ActivationFrame::GetClosure() {
  ASSERT(function().IsClosureFunction());
  return GetParameter(0);
}

RawObject* ActivationFrame::GetStackVar(VariableIndex variable_index) {
  if (IsInterpreted()) {
    intptr_t slot_index = -variable_index.value();
    if (slot_index < 0) {
      slot_index -= kKBCParamEndSlotFromFp;  // Accessing a parameter.
    }
    return GetVariableValue(fp() + slot_index * kWordSize);
  }
  const intptr_t slot_index =
      runtime_frame_layout.FrameSlotForVariableIndex(variable_index.value());
  if (deopt_frame_.IsNull()) {
    return GetVariableValue(LocalVarAddress(fp(), slot_index));
  } else {
    return deopt_frame_.At(LocalVarIndex(deopt_frame_offset_, slot_index));
  }
}

bool ActivationFrame::IsRewindable() const {
  if (deopt_frame_.IsNull()) {
    return true;
  }
  // TODO(turnidge): This is conservative.  It looks at all values in
  // the deopt_frame_ even though some of them may correspond to other
  // inlined frames.
  Object& obj = Object::Handle();
  for (int i = 0; i < deopt_frame_.Length(); i++) {
    obj = deopt_frame_.At(i);
    if (obj.raw() == Symbols::OptimizedOut().raw()) {
      return false;
    }
  }
  return true;
}

void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot,
                                                intptr_t frame_ctx_level,
                                                intptr_t var_ctx_level) {
  OS::PrintErr(
      "-------------------------\n"
      "Encountered context mismatch\n"
      "\tctx_slot: %" Pd
      "\n"
      "\tframe_ctx_level: %" Pd
      "\n"
      "\tvar_ctx_level: %" Pd "\n\n",
      ctx_slot, frame_ctx_level, var_ctx_level);

  OS::PrintErr(
      "-------------------------\n"
      "Current frame:\n%s\n",
      this->ToCString());

  OS::PrintErr(
      "-------------------------\n"
      "Context contents:\n");
  const Context& ctx = GetSavedCurrentContext();
  ctx.Dump(8);

  OS::PrintErr(
      "-------------------------\n"
      "Debugger stack trace...\n\n");
  DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
  intptr_t num_frames = stack->Length();
  for (intptr_t i = 0; i < num_frames; i++) {
    ActivationFrame* frame = stack->FrameAt(i);
    OS::PrintErr("#%04" Pd " %s", i, frame->ToCString());
  }

  OS::PrintErr(
      "-------------------------\n"
      "All frames...\n\n");
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = iterator.NextFrame();
  intptr_t num = 0;
  while ((frame != NULL)) {
    OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
    frame = iterator.NextFrame();
  }
}

void ActivationFrame::VariableAt(intptr_t i,
                                 String* name,
                                 TokenPosition* declaration_token_pos,
                                 TokenPosition* visible_start_token_pos,
                                 TokenPosition* visible_end_token_pos,
                                 Object* value) {
  GetDescIndices();
  ASSERT(i < desc_indices_.length());
  intptr_t desc_index = desc_indices_[i];
  ASSERT(name != NULL);

  *name = var_descriptors_.GetName(desc_index);

  RawLocalVarDescriptors::VarInfo var_info;
  var_descriptors_.GetInfo(desc_index, &var_info);
  ASSERT(declaration_token_pos != NULL);
  *declaration_token_pos = var_info.declaration_pos;
  ASSERT(visible_start_token_pos != NULL);
  *visible_start_token_pos = var_info.begin_pos;
  ASSERT(visible_end_token_pos != NULL);
  *visible_end_token_pos = var_info.end_pos;
  ASSERT(value != NULL);
  const int8_t kind = var_info.kind();
  const auto variable_index = VariableIndex(var_info.index());
  if (kind == RawLocalVarDescriptors::kStackVar) {
    *value = GetStackVar(variable_index);
  } else {
    ASSERT(kind == RawLocalVarDescriptors::kContextVar);
    *value = GetContextVar(var_info.scope_id, variable_index.value());
  }
}

RawObject* ActivationFrame::GetContextVar(intptr_t var_ctx_level,
                                          intptr_t ctx_slot) {
  // The context level at the PC/token index of this activation frame.
  intptr_t frame_ctx_level = ContextLevel();

  return GetRelativeContextVar(var_ctx_level, ctx_slot, frame_ctx_level);
}

RawObject* ActivationFrame::GetRelativeContextVar(intptr_t var_ctx_level,
                                                  intptr_t ctx_slot,
                                                  intptr_t frame_ctx_level) {
  const Context& ctx = GetSavedCurrentContext();
  ASSERT(!ctx.IsNull());

  intptr_t level_diff = frame_ctx_level - var_ctx_level;
  if (level_diff == 0) {
    if ((ctx_slot < 0) || (ctx_slot >= ctx.num_variables())) {
      PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
    }
    ASSERT((ctx_slot >= 0) && (ctx_slot < ctx.num_variables()));
    return ctx.At(ctx_slot);
  } else {
    ASSERT(level_diff > 0);
    Context& var_ctx = Context::Handle(ctx.raw());
    while (level_diff > 0 && !var_ctx.IsNull()) {
      level_diff--;
      var_ctx = var_ctx.parent();
    }
    if (var_ctx.IsNull() || (ctx_slot < 0) ||
        (ctx_slot >= var_ctx.num_variables())) {
      PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
    }
    ASSERT(!var_ctx.IsNull());
    ASSERT((ctx_slot >= 0) && (ctx_slot < var_ctx.num_variables()));
    return var_ctx.At(ctx_slot);
  }
}

RawArray* ActivationFrame::GetLocalVariables() {
  GetDescIndices();
  intptr_t num_variables = desc_indices_.length();
  String& var_name = String::Handle();
  Object& value = Instance::Handle();
  const Array& list = Array::Handle(Array::New(2 * num_variables));
  for (intptr_t i = 0; i < num_variables; i++) {
    TokenPosition ignore;
    VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
    list.SetAt(2 * i, var_name);
    list.SetAt((2 * i) + 1, value);
  }
  return list.raw();
}

RawObject* ActivationFrame::GetReceiver() {
  GetDescIndices();
  intptr_t num_variables = desc_indices_.length();
  String& var_name = String::Handle();
  Instance& value = Instance::Handle();
  for (intptr_t i = 0; i < num_variables; i++) {
    TokenPosition ignore;
    VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
    if (var_name.Equals(Symbols::This())) {
      return value.raw();
    }
  }
  return Symbols::OptimizedOut().raw();
}

static bool IsSyntheticVariableName(const String& var_name) {
  return (var_name.Length() >= 1) && (var_name.CharAt(0) == ':');
}

static bool IsPrivateVariableName(const String& var_name) {
  return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_');
}

RawObject* ActivationFrame::EvaluateCompiledExpression(
    const uint8_t* kernel_bytes,
    intptr_t kernel_length,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) {
  if (function().is_static()) {
    const Class& cls = Class::Handle(function().Owner());
    return cls.EvaluateCompiledExpression(kernel_bytes, kernel_length,
                                          type_definitions, arguments,
                                          type_arguments);
  } else {
    const Object& receiver = Object::Handle(GetReceiver());
    const Class& method_cls = Class::Handle(function().origin());
    ASSERT(receiver.IsInstance() || receiver.IsNull());
    if (!(receiver.IsInstance() || receiver.IsNull())) {
      return Object::null();
    }
    const Instance& inst = Instance::Cast(receiver);
    return inst.EvaluateCompiledExpression(method_cls, kernel_bytes,
                                           kernel_length, type_definitions,
                                           arguments, type_arguments);
  }
}

RawTypeArguments* ActivationFrame::BuildParameters(
    const GrowableObjectArray& param_names,
    const GrowableObjectArray& param_values,
    const GrowableObjectArray& type_params_names) {
  GetDescIndices();
  bool type_arguments_available = false;
  String& name = String::Handle();
  String& existing_name = String::Handle();
  Object& value = Instance::Handle();
  TypeArguments& type_arguments = TypeArguments::Handle();
  intptr_t num_variables = desc_indices_.length();
  for (intptr_t i = 0; i < num_variables; i++) {
    TokenPosition ignore;
    VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
    if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
      type_arguments_available = true;
      type_arguments ^= value.raw();
    } else if (!name.Equals(Symbols::This()) &&
               !IsSyntheticVariableName(name)) {
      if (IsPrivateVariableName(name)) {
        name = String::ScrubName(name);
      }
      bool conflict = false;
      for (intptr_t j = 0; j < param_names.Length(); j++) {
        existing_name ^= param_names.At(j);
        if (name.Equals(existing_name)) {
          conflict = true;
          break;
        }
      }
      // If local has the same name as a binding in the incoming scope, prefer
      // the one from the incoming scope, since it is logically a child scope
      // of the activation's current scope.
      if (!conflict) {
        param_names.Add(name);
        param_values.Add(value);
      }
    }
  }

  if ((function().IsGeneric() || function().HasGenericParent()) &&
      type_arguments_available) {
    intptr_t num_vars =
        function().NumTypeParameters() + function().NumParentTypeParameters();
    type_params_names.Grow(num_vars);
    type_params_names.SetLength(num_vars);
    TypeArguments& type_params = TypeArguments::Handle();
    TypeParameter& type_param = TypeParameter::Handle();
    Function& current = Function::Handle(function().raw());
    intptr_t mapping_offset = num_vars;
    for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
                  current = current.parent_function()) {
      type_params = current.type_parameters();
      intptr_t size = current.NumTypeParameters();
      ASSERT(mapping_offset >= size);
      mapping_offset -= size;
      for (intptr_t j = 0; j < size; ++j) {
        type_param = TypeParameter::RawCast(type_params.TypeAt(j));
        name = type_param.Name();
        // Write the names in backwards in terms of chain of functions.
        // But keep the order of names within the same function. so they
        // match up with the order of the types in 'type_arguments'.
        // Index:0 1 2 3 ...
        //       |Names in Grandparent| |Names in Parent| ..|Names in Child|
        type_params_names.SetAt(mapping_offset + j, name);
      }
    }
    if (!type_arguments.IsNull()) {
      if (type_arguments.Length() == 0) {
        for (intptr_t i = 0; i < num_vars; ++i) {
          type_arguments.SetTypeAt(i, Object::dynamic_type());
        }
      }
      ASSERT(type_arguments.Length() == num_vars);
    }
  }

  return type_arguments.raw();
}

const char* ActivationFrame::ToCString() {
  const String& url = String::Handle(SourceUrl());
  intptr_t line = LineNumber();
  const char* func_name = Debugger::QualifiedFunctionName(function());
  return Thread::Current()->zone()->PrintToString(
      "[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px
      ")\n"
      "\tfunction = %s\n"
      "\turl = %s\n"
      "\tline = %" Pd
      "\n"
      "\tcontext = %s\n"
      "\tcontext level = %" Pd " ]\n",
      pc(), fp(), sp(), func_name, url.ToCString(), line, ctx_.ToCString(),
      ContextLevel());
}

void ActivationFrame::PrintToJSONObject(JSONObject* jsobj) {
  if (kind_ == kRegular) {
    PrintToJSONObjectRegular(jsobj);
  } else if (kind_ == kAsyncCausal) {
    PrintToJSONObjectAsyncCausal(jsobj);
  } else if (kind_ == kAsyncSuspensionMarker) {
    PrintToJSONObjectAsyncSuspensionMarker(jsobj);
  } else if (kind_ == kAsyncActivation) {
    PrintToJSONObjectAsyncActivation(jsobj);
  } else {
    UNIMPLEMENTED();
  }
}

void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj) {
  const Script& script = Script::Handle(SourceScript());
  jsobj->AddProperty("type", "Frame");
  jsobj->AddProperty("kind", KindToCString(kind_));
  const TokenPosition pos = TokenPos().SourcePosition();
  jsobj->AddLocation(script, pos);
  jsobj->AddProperty("function", function());
  if (IsInterpreted()) {
    jsobj->AddProperty("code", bytecode());
  } else {
    jsobj->AddProperty("code", code());
  }
  {
    JSONArray jsvars(jsobj, "vars");
    const int num_vars = NumLocalVariables();
    for (intptr_t v = 0; v < num_vars; v++) {
      String& var_name = String::Handle();
      Instance& var_value = Instance::Handle();
      TokenPosition declaration_token_pos;
      TokenPosition visible_start_token_pos;
      TokenPosition visible_end_token_pos;
      VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
                 &visible_end_token_pos, &var_value);
      if ((var_name.raw() != Symbols::AsyncOperation().raw()) &&
          (var_name.raw() != Symbols::AsyncCompleter().raw()) &&
          (var_name.raw() != Symbols::ControllerStream().raw()) &&
          (var_name.raw() != Symbols::AwaitJumpVar().raw()) &&
          (var_name.raw() != Symbols::AsyncStackTraceVar().raw())) {
        JSONObject jsvar(&jsvars);
        jsvar.AddProperty("type", "BoundVariable");
        var_name = String::ScrubName(var_name);
        jsvar.AddProperty("name", var_name.ToCString());
        jsvar.AddProperty("value", var_value);
        // Where was the variable declared?
        jsvar.AddProperty("declarationTokenPos", declaration_token_pos);
        // When the variable becomes visible to the scope.
        jsvar.AddProperty("scopeStartTokenPos", visible_start_token_pos);
        // When the variable stops being visible to the scope.
        jsvar.AddProperty("scopeEndTokenPos", visible_end_token_pos);
      }
    }
  }
}

void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj) {
  jsobj->AddProperty("type", "Frame");
  jsobj->AddProperty("kind", KindToCString(kind_));
  const Script& script = Script::Handle(SourceScript());
  const TokenPosition pos = TokenPos().SourcePosition();
  jsobj->AddLocation(script, pos);
  jsobj->AddProperty("function", function());
  if (IsInterpreted()) {
    jsobj->AddProperty("code", bytecode());
  } else {
    jsobj->AddProperty("code", code());
  }
}

void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
    JSONObject* jsobj) {
  jsobj->AddProperty("type", "Frame");
  jsobj->AddProperty("kind", KindToCString(kind_));
  jsobj->AddProperty("marker", "AsynchronousSuspension");
}

void ActivationFrame::PrintToJSONObjectAsyncActivation(JSONObject* jsobj) {
  jsobj->AddProperty("type", "Frame");
  jsobj->AddProperty("kind", KindToCString(kind_));
  const Script& script = Script::Handle(SourceScript());
  const TokenPosition pos = TokenPos().SourcePosition();
  jsobj->AddLocation(script, pos);
  jsobj->AddProperty("function", function());
  if (IsInterpreted()) {
    jsobj->AddProperty("code", bytecode());
  } else {
    jsobj->AddProperty("code", code());
  }
}

static bool IsFunctionVisible(const Function& function) {
  return FLAG_show_invisible_frames || function.is_visible();
}

void DebuggerStackTrace::AddActivation(ActivationFrame* frame) {
  if (IsFunctionVisible(frame->function())) {
    trace_.Add(frame);
  }
}

void DebuggerStackTrace::AddMarker(ActivationFrame::Kind marker) {
  ASSERT(marker == ActivationFrame::kAsyncSuspensionMarker);
  trace_.Add(new ActivationFrame(marker));
}

void DebuggerStackTrace::AddAsyncCausalFrame(uword pc, const Code& code) {
  trace_.Add(new ActivationFrame(pc, 0, 0, code, Array::Handle(), 0,
                                 ActivationFrame::kAsyncCausal));
}

#if !defined(DART_PRECOMPILED_RUNTIME)
void DebuggerStackTrace::AddAsyncCausalFrame(uword pc,
                                             const Bytecode& bytecode) {
  trace_.Add(
      new ActivationFrame(pc, 0, 0, bytecode, ActivationFrame::kAsyncCausal));
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
                               RawPcDescriptors::kUnoptStaticCall |
                               RawPcDescriptors::kRuntimeCall;

CodeBreakpoint::CodeBreakpoint(const Code& code,
                               TokenPosition token_pos,
                               uword pc,
                               RawPcDescriptors::Kind kind)
    : code_(code.raw()),
      bytecode_(Bytecode::null()),
      token_pos_(token_pos),
      pc_(pc),
      line_number_(-1),
      is_enabled_(false),
      bpt_location_(NULL),
      next_(NULL),
      breakpoint_kind_(kind),
#if !defined(TARGET_ARCH_DBC)
      saved_value_(Code::null())
#else
      saved_value_(SimulatorBytecode::kTrap),
      saved_value_fastsmi_(SimulatorBytecode::kTrap)
#endif
{
  ASSERT(!code.IsNull());
  ASSERT(token_pos_.IsReal());
  ASSERT(pc_ != 0);
  ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
}

CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
                               TokenPosition token_pos,
                               uword pc)
    : code_(Code::null()),
      bytecode_(bytecode.raw()),
      token_pos_(token_pos),
      pc_(pc),
      line_number_(-1),
      is_enabled_(false),
      bpt_location_(NULL),
      next_(NULL),
      breakpoint_kind_(RawPcDescriptors::kAnyKind),
#if !defined(TARGET_ARCH_DBC)
      saved_value_(Code::null())
#else
      saved_value_(SimulatorBytecode::kTrap),
      saved_value_fastsmi_(SimulatorBytecode::kTrap)
#endif
{
  ASSERT(!bytecode.IsNull());
  ASSERT(token_pos_.IsReal());
  ASSERT(pc_ != 0);
}

CodeBreakpoint::~CodeBreakpoint() {
  // Make sure we don't leave patched code behind.
  ASSERT(!IsEnabled());
// Poison the data so we catch use after free errors.
#ifdef DEBUG
  code_ = Code::null();
  bytecode_ = Bytecode::null();
  pc_ = 0ul;
  bpt_location_ = NULL;
  next_ = NULL;
  breakpoint_kind_ = RawPcDescriptors::kOther;
#endif
}

RawFunction* CodeBreakpoint::function() const {
  if (IsInterpreted()) {
    ASSERT(Bytecode::Handle(bytecode_).function() != Function::null());
    return Bytecode::Handle(bytecode_).function();
  } else {
    return Code::Handle(code_).function();
  }
}

RawScript* CodeBreakpoint::SourceCode() {
  const Function& func = Function::Handle(this->function());
  return func.script();
}

RawString* CodeBreakpoint::SourceUrl() {
  const Script& script = Script::Handle(SourceCode());
  return script.url();
}

intptr_t CodeBreakpoint::LineNumber() {
  // Compute line number lazily since it causes scanning of the script.
  if (line_number_ < 0) {
    const Script& script = Script::Handle(SourceCode());
    script.GetTokenLocation(token_pos_, &line_number_, NULL);
  }
  return line_number_;
}

void CodeBreakpoint::Enable() {
  if (!is_enabled_) {
    if (IsInterpreted()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
      SetBytecodeBreakpoint();
#else
      UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    } else {
      PatchCode();
    }
  }
  ASSERT(is_enabled_);
}

void CodeBreakpoint::Disable() {
  if (is_enabled_) {
    if (IsInterpreted()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
      UnsetBytecodeBreakpoint();
#else
      UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    } else {
      RestoreCode();
    }
  }
  ASSERT(!is_enabled_);
}

Debugger::Debugger(Isolate* isolate)
    : isolate_(isolate),
      next_id_(1),
      latent_locations_(NULL),
      breakpoint_locations_(NULL),
      code_breakpoints_(NULL),
      resume_action_(kContinue),
      resume_frame_index_(-1),
      post_deopt_frame_index_(-1),
      ignore_breakpoints_(false),
      pause_event_(NULL),
      stack_trace_(NULL),
      async_causal_stack_trace_(NULL),
      awaiter_stack_trace_(NULL),
      stepping_fp_(0),
      async_stepping_fp_(0),
      top_frame_awaiter_(Object::null()),
      skip_next_step_(false),
      needs_breakpoint_cleanup_(false),
      synthetic_async_breakpoint_(NULL),
      exc_pause_info_(kNoPauseOnExceptions) {}

Debugger::~Debugger() {
  ASSERT(!IsPaused());
  ASSERT(latent_locations_ == NULL);
  ASSERT(breakpoint_locations_ == NULL);
  ASSERT(code_breakpoints_ == NULL);
  ASSERT(stack_trace_ == NULL);
  ASSERT(async_causal_stack_trace_ == NULL);
  ASSERT(synthetic_async_breakpoint_ == NULL);
}

void Debugger::Shutdown() {
  // TODO(johnmccutchan): Do not create a debugger for isolates that don't need
  // them. Then, assert here that isolate_ is not one of those isolates.
  if (Isolate::IsVMInternalIsolate(isolate_)) {
    return;
  }
  while (breakpoint_locations_ != NULL) {
    BreakpointLocation* loc = breakpoint_locations_;
    breakpoint_locations_ = breakpoint_locations_->next();
    delete loc;
  }
  while (latent_locations_ != NULL) {
    BreakpointLocation* loc = latent_locations_;
    latent_locations_ = latent_locations_->next();
    delete loc;
  }
  while (code_breakpoints_ != NULL) {
    CodeBreakpoint* cbpt = code_breakpoints_;
    code_breakpoints_ = code_breakpoints_->next();
    cbpt->Disable();
    delete cbpt;
  }
  if (NeedsIsolateEvents()) {
    ServiceEvent event(isolate_, ServiceEvent::kIsolateExit);
    InvokeEventHandler(&event);
  }
}

void Debugger::OnIsolateRunnable() {}

static RawFunction* ResolveLibraryFunction(const Library& library,
                                           const String& fname) {
  ASSERT(!library.IsNull());
  const Object& object = Object::Handle(library.ResolveName(fname));
  if (!object.IsNull() && object.IsFunction()) {
    return Function::Cast(object).raw();
  }
  return Function::null();
}

bool Debugger::SetupStepOverAsyncSuspension(const char** error) {
  ActivationFrame* top_frame = TopDartFrame();
  if (!IsAtAsyncJump(top_frame)) {
    // Not at an async operation.
    if (error) {
      *error = "Isolate must be paused at an async suspension point";
    }
    return false;
  }
  Object& closure = Object::Handle(top_frame->GetAsyncOperation());
  ASSERT(!closure.IsNull());
  ASSERT(closure.IsInstance());
  ASSERT(Instance::Cast(closure).IsClosure());
  Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true);
  if (bpt == NULL) {
    // Unable to set the breakpoint.
    if (error) {
      *error = "Unable to set breakpoint at async suspension point";
    }
    return false;
  }
  return true;
}

bool Debugger::SetResumeAction(ResumeAction action,
                               intptr_t frame_index,
                               const char** error) {
  if (error) {
    *error = NULL;
  }
  resume_frame_index_ = -1;
  switch (action) {
    case kStepInto:
    case kStepOver:
    case kStepOut:
    case kContinue:
      resume_action_ = action;
      return true;
    case kStepRewind:
      if (!CanRewindFrame(frame_index, error)) {
        return false;
      }
      resume_action_ = kStepRewind;
      resume_frame_index_ = frame_index;
      return true;
    case kStepOverAsyncSuspension:
      return SetupStepOverAsyncSuspension(error);
    default:
      UNREACHABLE();
      return false;
  }
}

RawFunction* Debugger::ResolveFunction(const Library& library,
                                       const String& class_name,
                                       const String& function_name) {
  ASSERT(!library.IsNull());
  ASSERT(!class_name.IsNull());
  ASSERT(!function_name.IsNull());
  if (class_name.Length() == 0) {
    return ResolveLibraryFunction(library, function_name);
  }
  const Class& cls = Class::Handle(library.LookupClass(class_name));
  Function& function = Function::Handle();
  if (!cls.IsNull()) {
    function = cls.LookupStaticFunction(function_name);
    if (function.IsNull()) {
      function = cls.LookupDynamicFunction(function_name);
    }
  }
  return function.raw();
}

// Deoptimize all functions in the isolate.
// TODO(hausner): Actually we only need to deoptimize those functions
// that inline the function that contains the newly created breakpoint.
// We currently don't have this info so we deoptimize all functions.
void Debugger::DeoptimizeWorld() {
#if defined(DART_PRECOMPILED_RUNTIME)
  UNREACHABLE();
#else
  BackgroundCompiler::Stop(isolate_);
  if (FLAG_trace_deoptimization) {
    THR_Print("Deopt for debugger\n");
  }
  isolate_->set_has_attempted_stepping(true);

  DeoptimizeFunctionsOnStack();

  // Iterate over all classes, deoptimize functions.
  // TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
  const ClassTable& class_table = *isolate_->class_table();
  Zone* zone = Thread::Current()->zone();
  Class& cls = Class::Handle(zone);
  Array& functions = Array::Handle(zone);
  GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
  Function& function = Function::Handle(zone);
  Code& code = Code::Handle(zone);
  intptr_t num_classes = class_table.NumCids();
  for (intptr_t i = 1; i < num_classes; i++) {
    if (class_table.HasValidClassAt(i)) {
      cls = class_table.At(i);

      // Disable optimized functions.
      functions = cls.functions();
      if (!functions.IsNull()) {
        intptr_t num_functions = functions.Length();
        for (intptr_t pos = 0; pos < num_functions; pos++) {
          function ^= functions.At(pos);
          ASSERT(!function.IsNull());
          if (function.HasOptimizedCode()) {
            function.SwitchToUnoptimizedCode();
          }
          code = function.unoptimized_code();
          if (!code.IsNull()) {
            code.ResetSwitchableCalls(zone);
          }
          // Also disable any optimized implicit closure functions.
          if (function.HasImplicitClosureFunction()) {
            function = function.ImplicitClosureFunction();
            if (function.HasOptimizedCode()) {
              function.SwitchToUnoptimizedCode();
            }
            code = function.unoptimized_code();
            if (!code.IsNull()) {
              code.ResetSwitchableCalls(zone);
            }
          }
        }
      }
    }
  }

  // Disable optimized closure functions.
  closures = isolate_->object_store()->closure_functions();
  const intptr_t num_closures = closures.Length();
  for (intptr_t pos = 0; pos < num_closures; pos++) {
    function ^= closures.At(pos);
    ASSERT(!function.IsNull());
    if (function.HasOptimizedCode()) {
      function.SwitchToUnoptimizedCode();
    }
    code = function.unoptimized_code();
    if (!code.IsNull()) {
      code.ResetSwitchableCalls(zone);
    }
  }
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void Debugger::NotifySingleStepping(bool value) const {
  isolate_->set_single_step(value);
#if !defined(DART_PRECOMPILED_RUNTIME)
  // Do not call Interpreter::Current(), which may allocate an interpreter.
  Interpreter* interpreter = Thread::Current()->interpreter();
  if (interpreter != nullptr) {
    // Do not reset is_debugging to false if bytecode debug breaks are enabled.
    interpreter->set_is_debugging(value || HasEnabledBytecodeBreakpoints());
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
}

ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
                                            uword pc,
                                            StackFrame* frame,
                                            const Code& code,
                                            const Array& deopt_frame,
                                            intptr_t deopt_frame_offset,
                                            ActivationFrame::Kind kind) {
  ASSERT(code.ContainsInstructionAt(pc));
  ActivationFrame* activation =
      new ActivationFrame(pc, frame->fp(), frame->sp(), code, deopt_frame,
                          deopt_frame_offset, kind);
  if (FLAG_trace_debugger_stacktrace) {
    const Context& ctx = activation->GetSavedCurrentContext();
    OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
  }
  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
  }
  return activation;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
                                            uword pc,
                                            StackFrame* frame,
                                            const Bytecode& bytecode,
                                            ActivationFrame::Kind kind) {
  ASSERT(bytecode.ContainsInstructionAt(pc));
  ActivationFrame* activation =
      new ActivationFrame(pc, frame->fp(), frame->sp(), bytecode, kind);
  if (FLAG_trace_debugger_stacktrace) {
    const Context& ctx = activation->GetSavedCurrentContext();
    OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
  }
  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
  }
  return activation;
}

RawArray* Debugger::DeoptimizeToArray(Thread* thread,
                                      StackFrame* frame,
                                      const Code& code) {
  ASSERT(code.is_optimized());
  Isolate* isolate = thread->isolate();
  // Create the DeoptContext for this deoptimization.
  DeoptContext* deopt_context =
      new DeoptContext(frame, code, DeoptContext::kDestIsAllocated, NULL, NULL,
                       true, false /* deoptimizing_code */);
  isolate->set_deopt_context(deopt_context);

  deopt_context->FillDestFrame();
  deopt_context->MaterializeDeferredObjects();
  const Array& dest_frame =
      Array::Handle(thread->zone(), deopt_context->DestFrameAsArray());

  isolate->set_deopt_context(NULL);
  delete deopt_context;

  return dest_frame.raw();
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

DebuggerStackTrace* Debugger::CollectStackTrace() {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  Code& code = Code::Handle(zone);
#if !defined(DART_PRECOMPILED_RUNTIME)
  Bytecode& bytecode = Bytecode::Handle(zone);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  Code& inlined_code = Code::Handle(zone);
  Array& deopt_frame = Array::Handle(zone);

  for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
       frame = iterator.NextFrame()) {
    ASSERT(frame->IsValid());
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr("CollectStackTrace: visiting frame:\n\t%s\n",
                   frame->ToCString());
    }
    if (frame->IsDartFrame()) {
      if (frame->is_interpreted()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        bytecode = frame->LookupDartBytecode();
        if (bytecode.function() == Function::null()) {
          continue;  // Skip bytecode stub frame.
        }
        stack_trace->AddActivation(
            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
#else
        UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      } else {
        code = frame->LookupDartCode();
        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
                         &inlined_code, &deopt_frame);
      }
    }
  }
  return stack_trace;
}

void Debugger::AppendCodeFrames(Thread* thread,
                                Isolate* isolate,
                                Zone* zone,
                                DebuggerStackTrace* stack_trace,
                                StackFrame* frame,
                                Code* code,
                                Code* inlined_code,
                                Array* deopt_frame) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (code->is_optimized()) {
    // TODO(rmacnak): Use CodeSourceMap
    *deopt_frame = DeoptimizeToArray(thread, frame, *code);
    for (InlinedFunctionsIterator it(*code, frame->pc()); !it.Done();
         it.Advance()) {
      *inlined_code = it.code();
      if (FLAG_trace_debugger_stacktrace) {
        const Function& function = Function::Handle(zone, it.function());
        ASSERT(!function.IsNull());
        OS::PrintErr("CollectStackTrace: visiting inlined function: %s\n",
                     function.ToFullyQualifiedCString());
      }
      intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
      stack_trace->AddActivation(CollectDartFrame(isolate, it.pc(), frame,
                                                  *inlined_code, *deopt_frame,
                                                  deopt_frame_offset));
    }
    return;
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  stack_trace->AddActivation(CollectDartFrame(isolate, frame->pc(), frame,
                                              *code, Object::null_array(), 0));
}

DebuggerStackTrace* Debugger::CollectAsyncCausalStackTrace() {
  if (!FLAG_causal_async_stacks) {
    return NULL;
  }
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);

  Object& code_obj = Object::Handle(zone);
  Code& code = Code::Handle(zone);
#if !defined(DART_PRECOMPILED_RUNTIME)
  Bytecode& bytecode = Bytecode::Handle(zone);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  Smi& offset = Smi::Handle();
  Code& inlined_code = Code::Handle(zone);
  Array& deopt_frame = Array::Handle(zone);

  Function& async_function = Function::Handle(zone);
  class StackTrace& async_stack_trace = StackTrace::Handle(zone);
  Array& async_code_array = Array::Handle(zone);
  Array& async_pc_offset_array = Array::Handle(zone);
  StackTraceUtils::ExtractAsyncStackTraceInfo(
      thread, &async_function, &async_stack_trace, &async_code_array,
      &async_pc_offset_array);

  if (async_function.IsNull()) {
    return NULL;
  }

  intptr_t synchronous_stack_trace_length =
      StackTraceUtils::CountFrames(thread, 0, async_function);

  // Append the top frames from the synchronous stack trace, up until the active
  // asynchronous function. We truncate the remainder of the synchronous
  // stack trace because it contains activations that are part of the
  // asynchronous dispatch mechanisms.
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = iterator.NextFrame();
  while (synchronous_stack_trace_length > 0) {
    ASSERT(frame != NULL);
    if (frame->IsDartFrame()) {
      if (frame->is_interpreted()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        bytecode = frame->LookupDartBytecode();
        if (bytecode.function() == Function::null()) {
          continue;  // Skip bytecode stub frame.
        }
        stack_trace->AddActivation(
            CollectDartFrame(isolate, frame->pc(), frame, bytecode));
#else
        UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      } else {
        code = frame->LookupDartCode();
        AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
                         &inlined_code, &deopt_frame);
      }
      synchronous_stack_trace_length--;
    }
    frame = iterator.NextFrame();
  }

  // Now we append the asynchronous causal stack trace. These are not active
  // frames but a historical record of how this asynchronous function was
  // activated.
  while (!async_stack_trace.IsNull()) {
    for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
      code_obj = async_stack_trace.CodeAtFrame(i);
      if (code_obj.IsNull()) {
        break;
      }
      if (code_obj.raw() == StubCode::AsynchronousGapMarker().raw()) {
        stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
        // The frame immediately below the asynchronous gap marker is the
        // identical to the frame above the marker. Skip the frame to enhance
        // the readability of the trace.
        i++;
      } else {
        offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
#if !defined(DART_PRECOMPILED_RUNTIME)
        if (code_obj.IsBytecode()) {
          bytecode ^= code_obj.raw();
          uword pc = bytecode.PayloadStart() + offset.Value();
          stack_trace->AddAsyncCausalFrame(pc, bytecode);
          continue;
        }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
        code ^= code_obj.raw();
        uword pc = code.PayloadStart() + offset.Value();
        if (code.is_optimized()) {
          for (InlinedFunctionsIterator it(code, pc); !it.Done();
               it.Advance()) {
            inlined_code = it.code();
            stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
          }
        } else {
          stack_trace->AddAsyncCausalFrame(pc, code);
        }
      }
    }
    // Follow the link.
    async_stack_trace = async_stack_trace.async_link();
  }

  return stack_trace;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static bool CheckAndSkipAsync(int skip_sync_async_frames_count,
                              const String& function_name) {
  return (skip_sync_async_frames_count == 2 &&
          function_name.Equals(Symbols::_ClosureCall())) ||
         (skip_sync_async_frames_count == 1 &&
          function_name.Equals(Symbols::_AsyncAwaitCompleterStart()));
}
#endif

DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
#if defined(DART_PRECOMPILED_RUNTIME)
  // Causal async stacks are not supported in the AOT runtime.
  ASSERT(!FLAG_async_debugger);
  return NULL;
#else
  if (!FLAG_async_debugger) {
    return NULL;
  }

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);

  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);

  Code& code = Code::Handle(zone);
  Bytecode& bytecode = Bytecode::Handle(zone);
  Smi& offset = Smi::Handle(zone);
  Function& function = Function::Handle(zone);
  Code& inlined_code = Code::Handle(zone);
  Closure& async_activation = Closure::Handle(zone);
  Object& next_async_activation = Object::Handle(zone);
  Array& deopt_frame = Array::Handle(zone);
  class StackTrace& async_stack_trace = StackTrace::Handle(zone);
  bool stack_has_async_function = false;

  // Number of frames we are trying to skip that form "sync async" entry.
  int skip_sync_async_frames_count = -1;
  String& function_name = String::Handle(zone);
  for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
       frame = iterator.NextFrame()) {
    ASSERT(frame->IsValid());
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr("CollectAwaiterReturnStackTrace: visiting frame:\n\t%s\n",
                   frame->ToCString());
    }
    if (frame->IsDartFrame()) {
      if (frame->is_interpreted()) {
        bytecode = frame->LookupDartBytecode();
        function = bytecode.function();
        if (function.IsNull()) {
          continue;  // Skip bytecode stub frame.
        }

        if (skip_sync_async_frames_count > 0) {
          function_name = function.QualifiedScrubbedName();
          if (CheckAndSkipAsync(skip_sync_async_frames_count, function_name)) {
            skip_sync_async_frames_count--;
          } else {
            // Unexpected function in synchronous call of async function.
            break;
          }
        }

        if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
          ActivationFrame* activation =
              CollectDartFrame(isolate, frame->pc(), frame, bytecode,
                               ActivationFrame::kAsyncActivation);
          ASSERT(activation != NULL);
          stack_trace->AddActivation(activation);
          stack_has_async_function = true;
          // Grab the awaiter.
          async_activation ^= activation->GetAsyncAwaiter();
          async_stack_trace ^= activation->GetCausalStack();
          // see comment regarding skipping frames of async functions called
          // synchronously above.
          skip_sync_async_frames_count = 2;
        } else {
          stack_trace->AddActivation(
              CollectDartFrame(isolate, frame->pc(), frame, bytecode));
        }
      } else {
        code = frame->LookupDartCode();
        if (code.is_optimized()) {
          deopt_frame = DeoptimizeToArray(thread, frame, code);
          bool found_async_awaiter = false;
          bool abort_attempt_to_navigate_through_sync_async = false;
          for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
               it.Advance()) {
            inlined_code = it.code();
            function = it.function();

            if (skip_sync_async_frames_count > 0) {
              function_name ^= function.QualifiedScrubbedName();
              if (CheckAndSkipAsync(skip_sync_async_frames_count,
                                    function_name)) {
                skip_sync_async_frames_count--;
              } else {
                // Unexpected function in sync async call
                skip_sync_async_frames_count = -1;
                abort_attempt_to_navigate_through_sync_async = true;
                break;
              }
            }

            if (FLAG_trace_debugger_stacktrace) {
              ASSERT(!function.IsNull());
              OS::PrintErr(
                  "CollectAwaiterReturnStackTrace: visiting inlined function: "
                  "%s\n",
                  function.ToFullyQualifiedCString());
            }
            intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
            if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
              ActivationFrame* activation = CollectDartFrame(
                  isolate, it.pc(), frame, inlined_code, deopt_frame,
                  deopt_frame_offset, ActivationFrame::kAsyncActivation);
              ASSERT(activation != NULL);
              stack_trace->AddActivation(activation);
              stack_has_async_function = true;
              // Grab the awaiter.
              async_activation ^= activation->GetAsyncAwaiter();
              found_async_awaiter = true;
              // async function might have been called synchronously, in which
              // case we need to keep going down the stack.
              // To determine how we are called we peek few more frames further
              // expecting to see Closure_call followed by
              // AsyncAwaitCompleter_start.
              // If we are able to see those functions we continue going down
              // thestack, if we are not, we break out of the loop as we are
              // not interested in exploring rest of the stack - there is only
              // dart-internal code left.
              skip_sync_async_frames_count = 2;
            } else {
              stack_trace->AddActivation(
                  CollectDartFrame(isolate, it.pc(), frame, inlined_code,
                                   deopt_frame, deopt_frame_offset));
            }
          }
          // Break out of outer loop.
          if (found_async_awaiter ||
              abort_attempt_to_navigate_through_sync_async) {
            break;
          }
        } else {
          function = code.function();

          if (skip_sync_async_frames_count > 0) {
            function_name ^= function.QualifiedScrubbedName();
            if (CheckAndSkipAsync(skip_sync_async_frames_count,
                                  function_name)) {
              skip_sync_async_frames_count--;
            } else {
              // Unexpected function in synchronous call of async function.
              break;
            }
          }

          if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
            ActivationFrame* activation = CollectDartFrame(
                isolate, frame->pc(), frame, code, Object::null_array(), 0,
                ActivationFrame::kAsyncActivation);
            ASSERT(activation != NULL);
            stack_trace->AddActivation(activation);
            stack_has_async_function = true;
            // Grab the awaiter.
            async_activation ^= activation->GetAsyncAwaiter();
            async_stack_trace ^= activation->GetCausalStack();
            // see comment regarding skipping frames of async functions called
            // synchronously above.
            skip_sync_async_frames_count = 2;
          } else {
            stack_trace->AddActivation(CollectDartFrame(
                isolate, frame->pc(), frame, code, Object::null_array(), 0));
          }
        }
      }
    }
  }

  // If the stack doesn't have any async functions on it, return NULL.
  if (!stack_has_async_function) {
    return NULL;
  }

  // Append the awaiter return call stack.
  while (!async_activation.IsNull()) {
    ActivationFrame* activation = new (zone) ActivationFrame(async_activation);
    activation->ExtractTokenPositionFromAsyncClosure();
    stack_trace->AddActivation(activation);
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr(
          "CollectAwaiterReturnStackTrace: visiting awaiter return "
          "closures:\n\t%s\n",
          activation->function().ToFullyQualifiedCString());
    }
    next_async_activation = activation->GetAsyncAwaiter();
    if (next_async_activation.IsNull()) {
      // No more awaiters. Extract the causal stack trace (if it exists).
      async_stack_trace ^= activation->GetCausalStack();
      break;
    }
    async_activation = Closure::RawCast(next_async_activation.raw());
  }

  // Now we append the asynchronous causal stack trace. These are not active
  // frames but a historical record of how this asynchronous function was
  // activated.
  while (!async_stack_trace.IsNull()) {
    for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
      if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
        // Incomplete OutOfMemory/StackOverflow trace OR array padding.
        break;
      }
      if (async_stack_trace.CodeAtFrame(i) ==
          StubCode::AsynchronousGapMarker().raw()) {
        stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
        // The frame immediately below the asynchronous gap marker is the
        // identical to the frame above the marker. Skip the frame to enhance
        // the readability of the trace.
        i++;
      } else {
        code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
        offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
        uword pc = code.PayloadStart() + offset.Value();
        if (code.is_optimized()) {
          for (InlinedFunctionsIterator it(code, pc); !it.Done();
               it.Advance()) {
            inlined_code = it.code();
            stack_trace->AddAsyncCausalFrame(it.pc(), inlined_code);
          }
        } else {
          stack_trace->AddAsyncCausalFrame(pc, code);
        }
      }
    }
    // Follow the link.
    async_stack_trace = async_stack_trace.async_link();
  }

  return stack_trace;
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

ActivationFrame* Debugger::TopDartFrame() const {
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame;
  while (true) {
    frame = iterator.NextFrame();
    RELEASE_ASSERT(frame != nullptr);
    if (!frame->IsDartFrame()) {
      continue;
    }
#if !defined(DART_PRECOMPILED_RUNTIME)
    if (frame->is_interpreted()) {
      Bytecode& bytecode = Bytecode::Handle(frame->LookupDartBytecode());
      if (bytecode.function() == Function::null()) {
        continue;  // Skip bytecode stub frame.
      }
      ActivationFrame* activation =
          new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), bytecode);
      return activation;
    }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    Code& code = Code::Handle(frame->LookupDartCode());
    ActivationFrame* activation = new ActivationFrame(
        frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
    return activation;
  }
}

DebuggerStackTrace* Debugger::StackTrace() {
  return (stack_trace_ != NULL) ? stack_trace_ : CollectStackTrace();
}

DebuggerStackTrace* Debugger::CurrentStackTrace() {
  return CollectStackTrace();
}

DebuggerStackTrace* Debugger::AsyncCausalStackTrace() {
  return (async_causal_stack_trace_ != NULL) ? async_causal_stack_trace_
                                             : CollectAsyncCausalStackTrace();
}

DebuggerStackTrace* Debugger::CurrentAsyncCausalStackTrace() {
  return CollectAsyncCausalStackTrace();
}

DebuggerStackTrace* Debugger::AwaiterStackTrace() {
  return (awaiter_stack_trace_ != NULL) ? awaiter_stack_trace_
                                        : CollectAwaiterReturnStackTrace();
}

DebuggerStackTrace* Debugger::CurrentAwaiterStackTrace() {
  return CollectAwaiterReturnStackTrace();
}

DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) {
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
  Function& function = Function::Handle();
  Object& code_object = Object::Handle();
  Code& code = Code::Handle();
#if !defined(DART_PRECOMPILED_RUNTIME)
  Bytecode& bytecode = Bytecode::Handle();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

  const uword fp = 0;
  const uword sp = 0;
  const Array& deopt_frame = Array::Handle();
  const intptr_t deopt_frame_offset = -1;

  for (intptr_t i = 0; i < ex_trace.Length(); i++) {
    code_object = ex_trace.CodeAtFrame(i);
    // Pre-allocated StackTraces may include empty slots, either (a) to indicate
    // where frames were omitted in the case a stack has more frames than the
    // pre-allocated trace (such as a stack overflow) or (b) because a stack has
    // fewer frames that the pre-allocated trace (such as memory exhaustion with
    // a shallow stack).
    if (!code_object.IsNull()) {
      if (code_object.IsBytecode()) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        bytecode ^= code_object.raw();
        function = bytecode.function();
        // Skip bytecode stub frames and frames with invisible function.
        if (!function.IsNull() && function.is_visible()) {
          ASSERT(function.raw() == bytecode.function());
          uword pc =
              bytecode.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
          ActivationFrame* activation =
              new ActivationFrame(pc, fp, sp, bytecode);
          stack_trace->AddActivation(activation);
        }
#else
        UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      } else {
        code ^= code_object.raw();
        ASSERT(code.IsFunctionCode());
        function = code.function();
        if (function.is_visible()) {
          ASSERT(function.raw() == code.function());
          uword pc =
              code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
          if (code.is_optimized() && ex_trace.expand_inlined()) {
            // Traverse inlined frames.
            for (InlinedFunctionsIterator it(code, pc); !it.Done();
                 it.Advance()) {
              function = it.function();
              code = it.code();
              ASSERT(function.raw() == code.function());
              uword pc = it.pc();
              ASSERT(pc != 0);
              ASSERT(code.PayloadStart() <= pc);
              ASSERT(pc < (code.PayloadStart() + code.Size()));

              ActivationFrame* activation = new ActivationFrame(
                  pc, fp, sp, code, deopt_frame, deopt_frame_offset);
              stack_trace->AddActivation(activation);
            }
          } else {
            ActivationFrame* activation = new ActivationFrame(
                pc, fp, sp, code, deopt_frame, deopt_frame_offset);
            stack_trace->AddActivation(activation);
          }
        }
      }
    }
  }
  return stack_trace;
}

void Debugger::SetExceptionPauseInfo(Dart_ExceptionPauseInfo pause_info) {
  ASSERT((pause_info == kNoPauseOnExceptions) ||
         (pause_info == kPauseOnUnhandledExceptions) ||
         (pause_info == kPauseOnAllExceptions));
  exc_pause_info_ = pause_info;
}

Dart_ExceptionPauseInfo Debugger::GetExceptionPauseInfo() const {
  return exc_pause_info_;
}

bool Debugger::ShouldPauseOnException(DebuggerStackTrace* stack_trace,
                                      const Instance& exception) {
  if (exc_pause_info_ == kNoPauseOnExceptions) {
    return false;
  }
  if (exc_pause_info_ == kPauseOnAllExceptions) {
    return true;
  }
  ASSERT(exc_pause_info_ == kPauseOnUnhandledExceptions);
  ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
  if (handler_frame == NULL) {
    // Did not find an exception handler that catches this exception.
    // Note that this check is not precise, since we can't check
    // uninstantiated types, i.e. types containing type parameters.
    // Thus, we may report an exception as unhandled when in fact
    // it will be caught once we unwind the stack.
    return true;
  }
  return false;
}

void Debugger::PauseException(const Instance& exc) {
  if (FLAG_stress_async_stacks) {
    CollectAwaiterReturnStackTrace();
  }
  // We ignore this exception event when the VM is executing code invoked
  // by the debugger to evaluate variables values, when we see a nested
  // breakpoint or exception event, or if the debugger is not
  // interested in exception events.
  if (ignore_breakpoints_ || IsPaused() ||
      (exc_pause_info_ == kNoPauseOnExceptions)) {
    return;
  }
  DebuggerStackTrace* awaiter_stack_trace = CollectAwaiterReturnStackTrace();
  DebuggerStackTrace* stack_trace = CollectStackTrace();
  if (awaiter_stack_trace != NULL) {
    if (!ShouldPauseOnException(awaiter_stack_trace, exc)) {
      return;
    }
  } else {
    if (!ShouldPauseOnException(stack_trace, exc)) {
      return;
    }
  }
  ServiceEvent event(isolate_, ServiceEvent::kPauseException);
  event.set_exception(&exc);
  if (stack_trace->Length() > 0) {
    event.set_top_frame(stack_trace->FrameAt(0));
  }
  CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
                   CollectAwaiterReturnStackTrace());
  Pause(&event);
  HandleSteppingRequest(stack_trace_);  // we may get a rewind request
  ClearCachedStackTraces();
}

// Returns the best fit token position for a breakpoint.
//
// Takes a range of tokens [requested_token_pos, last_token_pos] and
// an optional column (requested_column).  The range of tokens usually
// represents one line of the program text, but can represent a larger
// range on recursive calls.
//
// The best fit is found in two passes.
//
// The first pass finds a candidate token which:
//
//   - is a safepoint,
//   - has the lowest column number compatible with the requested column
//     if a column has been specified,
// and:
//   - has the lowest token position number which satisfies the above.
//
// When we consider a column number, we look for the token which
// intersects the desired column.  For example:
//
//          1         2         3
// 12345678901234567890         0
//
//   var x = function(function(y));
//              ^
//
// If we request a breakpoint at column 14, the lowest column number
// compatible with that would for column 11 (beginning of the
// 'function' token) in the example above.
//
// Once this candidate token from the first pass is found, we then
// have a second pass which considers only those tokens on the same
// line as the candidate token.
//
// The second pass finds a best fit token which:
//
//   - is a safepoint,
//   - has the same column number as the candidate token (perhaps
//     more than one token has the same column number),
// and:
//   - has the lowest code address in the generated code.
//
// We prefer the lowest compiled code address, because this tends to
// select the first subexpression on a line.  For example in a line
// with nested function calls f(g(x)), the call to g() will have a
// lower compiled code address than the call to f().
//
// If no best fit token can be found, the search is expanded,
// searching through the rest of the current function by calling this
// function recursively.
//
// TODO(turnidge): Given that we usually call this function with a
// token range restricted to a single line, this could be a one-pass
// algorithm, which would be simpler.  I believe that it only needs
// two passes to support the recursive try-the-whole-function case.
// Rewrite this later, once there are more tests in place.
TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
                                             const Function& func,
                                             TokenPosition requested_token_pos,
                                             TokenPosition last_token_pos,
                                             intptr_t requested_column,
                                             TokenPosition exact_token_pos) {
  ASSERT(!func.HasOptimizedCode());

  if (requested_token_pos < func.token_pos()) {
    requested_token_pos = func.token_pos();
  }
  if (last_token_pos > func.end_token_pos()) {
    last_token_pos = func.end_token_pos();
  }

  Zone* zone = Thread::Current()->zone();
  Script& script = Script::Handle(zone, func.script());
  Code& code = Code::Handle(zone);
#if !defined(DART_PRECOMPILED_RUNTIME)
  Bytecode& bytecode = Bytecode::Handle(zone);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  PcDescriptors& desc = PcDescriptors::Handle(zone);
  if (in_bytecode) {
#if !defined(DART_PRECOMPILED_RUNTIME)
    ASSERT(func.HasBytecode());
    bytecode = func.bytecode();
    ASSERT(!bytecode.IsNull());
#else
    UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  } else {
    ASSERT(func.HasCode());
    code = func.unoptimized_code();
    ASSERT(!code.IsNull());
    desc = code.pc_descriptors();
  }

  // First pass: find the safe point which is closest to the beginning
  // of the given token range.
  TokenPosition best_fit_pos = TokenPosition::kMaxSource;
  intptr_t best_column = INT_MAX;
  intptr_t best_line = INT_MAX;
  // best_token_pos and exact_token_pos are only used
  // if column number is provided.
  TokenPosition best_token_pos = TokenPosition::kNoSource;

  if (in_bytecode) {
#if !defined(DART_PRECOMPILED_RUNTIME)
    kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
    while (iter.MoveNext()) {
      const TokenPosition pos = iter.TokenPos();
      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
          (pos > last_token_pos)) {
        // Token is not in the target range.
        continue;
      }

      intptr_t token_start_column = -1;
      intptr_t token_line = -1;
      if (requested_column >= 0) {
        kernel::BytecodeSourcePositionsIterator iter2(zone, bytecode);
        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
        while (iter2.MoveNext()) {
          const TokenPosition next = iter2.TokenPos();
          if (next < next_closest_token_position && next > pos) {
            next_closest_token_position = next;
          }
        }

        TokenPosition ignored;
        TokenPosition end_of_line_pos;
        script.GetTokenLocation(pos, &token_line, &token_start_column);
        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
        TokenPosition token_end_pos =
            (end_of_line_pos < next_closest_token_position)
                ? end_of_line_pos
                : next_closest_token_position;

        if ((token_end_pos < exact_token_pos) ||
            (token_start_column > best_column)) {
          // Prefer the token with the lowest column number compatible
          // with the requested column.
          continue;
        }
      }

      // Prefer the lowest (first) token pos.
      if (pos < best_fit_pos) {
        best_fit_pos = pos;
        best_line = token_line;
        best_column = token_start_column;
        // best_token_pos is only used when column number is specified.
        best_token_pos = TokenPosition(exact_token_pos.value() -
                                       (requested_column - best_column));
      }
    }
#else
    UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  } else {
    PcDescriptors::Iterator iter(desc, kSafepointKind);
    while (iter.MoveNext()) {
      const TokenPosition pos = iter.TokenPos();
      if ((!pos.IsReal()) || (pos < requested_token_pos) ||
          (pos > last_token_pos)) {
        // Token is not in the target range.
        continue;
      }

      intptr_t token_start_column = -1;
      intptr_t token_line = -1;
      if (requested_column >= 0) {
        // Find next closest safepoint
        PcDescriptors::Iterator iter2(desc, kSafepointKind);
        TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
        while (iter2.MoveNext()) {
          const TokenPosition next = iter2.TokenPos();
          if (next < next_closest_token_position && next > pos) {
            next_closest_token_position = next;
          }
        }

        TokenPosition ignored;
        TokenPosition end_of_line_pos;
        script.GetTokenLocation(pos, &token_line, &token_start_column);
        script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
        TokenPosition token_end_pos =
            (end_of_line_pos < next_closest_token_position)
                ? end_of_line_pos
                : next_closest_token_position;

        if ((token_end_pos < exact_token_pos) ||
            (token_start_column > best_column)) {
          // Prefer the token with the lowest column number compatible
          // with the requested column.
          continue;
        }
      }

      // Prefer the lowest (first) token pos.
      if (pos < best_fit_pos) {
        best_fit_pos = pos;
        best_line = token_line;
        best_column = token_start_column;
        // best_token_pos is only used when column number is specified.
        best_token_pos = TokenPosition(exact_token_pos.value() -
                                       (requested_column - best_column));
      }
    }
  }

  // Second pass (if we found a safe point in the first pass).  Find
  // the token on the line which is at the best fit column (if column
  // was specified) and has the lowest code address.
  if (best_fit_pos != TokenPosition::kMaxSource) {
    const Script& script = Script::Handle(zone, func.script());
    const TokenPosition begin_pos = best_fit_pos;

    TokenPosition end_of_line_pos;
    ASSERT(script.kind() == RawScript::kKernelTag);
    if (best_line == -1) {
      script.GetTokenLocation(begin_pos, &best_line, NULL);
    }
    ASSERT(best_line > 0);
    TokenPosition ignored;
    script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
    if (end_of_line_pos < begin_pos) {
      end_of_line_pos = begin_pos;
    }

    uword lowest_pc_offset = kUwordMax;
    if (in_bytecode) {
#if !defined(DART_PRECOMPILED_RUNTIME)
      kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
      while (iter.MoveNext()) {
        const TokenPosition pos = iter.TokenPos();
        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
          // Token is not on same line as best fit.
          continue;
        }

        if (requested_column >= 0) {
          if (pos != best_token_pos) {
            continue;
          }
        }

        // Prefer the lowest pc offset.
        if (iter.PcOffset() < lowest_pc_offset) {
          lowest_pc_offset = iter.PcOffset();
          best_fit_pos = pos;
        }
      }
#else
      UNREACHABLE();
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
    } else {
      PcDescriptors::Iterator iter(desc, kSafepointKind);
      while (iter.MoveNext()) {
        const TokenPosition pos = iter.TokenPos();
        if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
          // Token is not on same line as best fit.
          continue;
        }

        if (requested_column >= 0) {
          if (pos != best_token_pos) {
            continue;
          }
        }

        // Prefer the lowest pc offset.
        if (iter.PcOffset() < lowest_pc_offset) {
          lowest_pc_offset = iter.PcOffset();
          best_fit_pos = pos;
        }
      }
    }
    return best_fit_pos;
  }

  // We didn't find a safe point in the given token range. Try and
  // find a safe point in the remaining source code of the function.
  // Since we have moved to the next line of the function, we no
  // longer are requesting a specific column number.
  if (last_token_pos < func.end_token_pos()) {
    return ResolveBreakpointPos(in_bytecode, func, last_token_pos,
                                func.end_token_pos(), -1 /* no column */,
                                TokenPosition::kNoSource);
  }
  return TokenPosition::kNoSource;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
// Find a 'debug break checked' bytecode in the range [pc..end_pc[ and return
// the pc after it or nullptr.
static const KBCInstr* FindBreakpointCheckedInstr(const KBCInstr* pc,
                                                  const KBCInstr* end_pc) {
  while ((pc < end_pc) && !KernelBytecode::IsDebugBreakCheckedOpcode(pc)) {
    pc = KernelBytecode::Next(pc);
  }
  if (pc < end_pc) {
    ASSERT(KernelBytecode::IsDebugBreakCheckedOpcode(pc));
    // The checked debug break pc must point to the next bytecode.
    return KernelBytecode::Next(pc);
  }
  // No 'debug break checked' bytecode in the range.
  return nullptr;
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

void Debugger::MakeCodeBreakpointAt(const Function& func,
                                    BreakpointLocation* loc) {
  ASSERT(loc->token_pos_.IsReal());
  ASSERT((loc != NULL) && loc->IsResolved());
  ASSERT(!func.HasOptimizedCode());
  ASSERT(func.HasCode() || func.HasBytecode());
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (func.HasBytecode()) {
    Bytecode& bytecode = Bytecode::Handle(func.bytecode());
    ASSERT(!bytecode.IsNull());
    const KBCInstr* pc = nullptr;
    if (bytecode.HasSourcePositions()) {
      kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
                                                   bytecode);
      bool check_range = false;
      while (iter.MoveNext()) {
        if (check_range) {
          const KBCInstr* end_pc =
              reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
              iter.PcOffset();
          check_range = false;
          // Find a 'debug break checked' bytecode in the range [pc..end_pc[.
          pc = FindBreakpointCheckedInstr(pc, end_pc);
          if (pc != nullptr) {
            // TODO(regis): We may want to find all PCs for a token position,
            // e.g. in the case of duplicated bytecode in finally clauses.
            break;
          }
        }
        if (iter.TokenPos() == loc->token_pos_) {
          pc = reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
               iter.PcOffset();
          check_range = true;
        }
      }
      if (check_range) {
        ASSERT(pc != nullptr);
        // Use the end of the bytecode as the end of the range to check.
        pc = FindBreakpointCheckedInstr(
            pc, reinterpret_cast<const KBCInstr*>(bytecode.PayloadStart()) +
                    bytecode.Size());
      }
    }
    if (pc != nullptr) {
      CodeBreakpoint* code_bpt = GetCodeBreakpoint(reinterpret_cast<uword>(pc));
      if (code_bpt == NULL) {
        // No code breakpoint for this code exists; create one.
        code_bpt = new CodeBreakpoint(bytecode, loc->token_pos_,
                                      reinterpret_cast<uword>(pc));
        RegisterCodeBreakpoint(code_bpt);
      }
      code_bpt->set_bpt_location(loc);
      if (loc->AnyEnabled()) {
        code_bpt->Enable();
      }
    }
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  if (func.HasCode()) {
    Code& code = Code::Handle(func.unoptimized_code());
    ASSERT(!code.IsNull());
    PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
    uword lowest_pc_offset = kUwordMax;
    RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
    // Find the safe point with the lowest compiled code address
    // that maps to the token position of the source breakpoint.
    PcDescriptors::Iterator iter(desc, kSafepointKind);
    while (iter.MoveNext()) {
      if (iter.TokenPos() == loc->token_pos_) {
        if (iter.PcOffset() < lowest_pc_offset) {
          lowest_pc_offset = iter.PcOffset();
          lowest_kind = iter.Kind();
        }
      }
    }
    if (lowest_pc_offset != kUwordMax) {
      uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
      CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
      if (code_bpt == NULL) {
        // No code breakpoint for this code exists; create one.
        code_bpt =
            new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
        RegisterCodeBreakpoint(code_bpt);
      }
      code_bpt->set_bpt_location(loc);
      if (loc->AnyEnabled()) {
        code_bpt->Enable();
      }
    }
  }
}

void Debugger::FindCompiledFunctions(
    const Script& script,
    TokenPosition start_pos,
    TokenPosition end_pos,
    GrowableObjectArray* bytecode_function_list,
    GrowableObjectArray* code_function_list) {
  Zone* zone = Thread::Current()->zone();
  Class& cls = Class::Handle(zone);
  Array& functions = Array::Handle(zone);
  GrowableObjectArray& closures = GrowableObjectArray::Handle(zone);
  Function& function = Function::Handle(zone);

  closures = isolate_->object_store()->closure_functions();
  const intptr_t num_closures = closures.Length();
  for (intptr_t pos = 0; pos < num_closures; pos++) {
    function ^= closures.At(pos);
    ASSERT(!function.IsNull());
    if ((function.token_pos() == start_pos) &&
        (function.end_token_pos() == end_pos) &&
        (function.script() == script.raw())) {
      if (function.is_debuggable()) {
        if (function.HasBytecode()) {
          bytecode_function_list->Add(function);
        }
        if (function.HasCode()) {
          code_function_list->Add(function);
        }
      }
      if (function.HasImplicitClosureFunction()) {
        function = function.ImplicitClosureFunction();
        if (function.is_debuggable()) {
          if (function.HasBytecode()) {
            bytecode_function_list->Add(function);
          }
          if (function.HasCode()) {
            code_function_list->Add(function);
          }
        }
      }
    }
  }

  const ClassTable& class_table = *isolate_->class_table();
  const intptr_t num_classes = class_table.NumCids();
  for (intptr_t i = 1; i < num_classes; i++) {
    if (class_table.HasValidClassAt(i)) {
      cls = class_table.At(i);
      // If the class is not finalized, e.g. if it hasn't been parsed
      // yet entirely, we can ignore it. If it contains a function with
      // an unresolved breakpoint, we will detect it if and when the
      // function gets compiled.
      if (!cls.is_finalized()) {
        continue;
      }
      // Note: we need to check the functions of this class even if
      // the class is defined in a different 'script'. There could
      // be mixin functions from the given script in this class.
      functions = cls.functions();
      if (!functions.IsNull()) {
        const intptr_t num_functions = functions.Length();
        for (intptr_t pos = 0; pos < num_functions; pos++) {
          function ^= functions.At(pos);
          ASSERT(!function.IsNull());
          // Check token position first to avoid unnecessary calls
          // to script() which allocates handles.
          if ((function.token_pos() == start_pos) &&
              (function.end_token_pos() == end_pos) &&
              (function.script() == script.raw())) {
            if (function.is_debuggable()) {
              if (function.HasBytecode()) {
                bytecode_function_list->Add(function);
              }
              if (function.HasCode()) {
                code_function_list->Add(function);
              }
            }
            if (function.HasImplicitClosureFunction()) {
              function = function.ImplicitClosureFunction();
              if (function.is_debuggable()) {
                if (function.HasBytecode()) {
                  bytecode_function_list->Add(function);
                }
                if (function.HasCode()) {
                  code_function_list->Add(function);
                }
              }
            }
          }
        }
      }
    }
  }
}

static void SelectBestFit(Function* best_fit, Function* func) {
  if (best_fit->IsNull()) {
    *best_fit = func->raw();
  } else {
    if ((func->token_pos() > best_fit->token_pos()) &&
        ((func->end_token_pos() <= best_fit->end_token_pos()))) {
      *best_fit = func->raw();
    }
  }
}

// Returns true if a best fit is found. A best fit can either be a function
// or a field. If it is a function, then the best fit function is returned
// in |best_fit|. If a best fit is a field, it means that a latent
// breakpoint can be set in the range |token_pos| to |last_token_pos|.
bool Debugger::FindBestFit(const Script& script,
                           TokenPosition token_pos,
                           TokenPosition last_token_pos,
                           Function* best_fit) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Class& cls = Class::Handle(zone);
  Library& lib = Library::Handle(zone, script.FindLibrary());
  ASSERT(!lib.IsNull());
  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
      zone, isolate_->object_store()->closure_functions());
  Array& functions = Array::Handle(zone);
  Function& function = Function::Handle(zone);
  Array& fields = Array::Handle(zone);
  Field& field = Field::Handle(zone);
  Error& error = Error::Handle(zone);

  const intptr_t num_closures = closures.Length();
  for (intptr_t i = 0; i < num_closures; i++) {
    function ^= closures.At(i);
    if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
      // Select the inner most closure.
      SelectBestFit(best_fit, &function);
    }
  }
  if (!best_fit->IsNull()) {
    // The inner most closure found will be the best fit. Going
    // over class functions below will not help in any further
    // narrowing.
    return true;
  }

  const ClassTable& class_table = *isolate_->class_table();
  const intptr_t num_classes = class_table.NumCids();
  for (intptr_t i = 1; i < num_classes; i++) {
    if (!class_table.HasValidClassAt(i)) {
      continue;
    }
    cls = class_table.At(i);
    // This class is relevant to us only if it belongs to the
    // library to which |script| belongs.
    if (cls.library() != lib.raw()) {
      continue;
    }
    // Parse class definition if not done yet.
    error = cls.EnsureIsFinalized(Thread::Current());
    if (!error.IsNull()) {
      // Ignore functions in this class.
      // TODO(hausner): Should we propagate this error? How?
      // EnsureIsFinalized only returns an error object if there
      // is no longjump base on the stack.
      continue;
    }
    functions = cls.functions();
    if (!functions.IsNull()) {
      const intptr_t num_functions = functions.Length();
      for (intptr_t pos = 0; pos < num_functions; pos++) {
        function ^= functions.At(pos);
        ASSERT(!function.IsNull());
        if (IsImplicitFunction(function)) {
          // Implicit functions do not have a user specifiable source
          // location.
          continue;
        }
        if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
          // Closures and inner functions within a class method are not
          // present in the functions of a class. Hence, we can return
          // right away as looking through other functions of a class
          // will not narrow down to any inner function/closure.
          *best_fit = function.raw();
          return true;
        }
      }
    }
    // If none of the functions in the class contain token_pos, then we
    // check if it falls within a function literal initializer of a field
    // that has not been initialized yet. If the field (and hence the
    // function literal initializer) has already been initialized, then
    // it would have been found above in the object store as a closure.
    fields = cls.fields();
    if (!fields.IsNull()) {
      const intptr_t num_fields = fields.Length();
      for (intptr_t pos = 0; pos < num_fields; pos++) {
        TokenPosition start;
        TokenPosition end;
        field ^= fields.At(pos);
        ASSERT(!field.IsNull());
        if (field.Script() != script.raw()) {
          // The field should be defined in the script we want to set
          // the breakpoint in.
          continue;
        }
        if (!field.has_initializer()) {
          continue;
        }
        start = field.token_pos();
        end = field.end_token_pos();
        if ((start <= token_pos && token_pos <= end) ||
            (token_pos <= start && start <= last_token_pos)) {
          return true;
        }
      }
    }
  }
  return false;
}

BreakpointLocation* Debugger::SetCodeBreakpoints(
    bool in_bytecode,
    BreakpointLocation* loc,
    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) {
  Function& function = Function::Handle();
  function ^= functions.At(0);
  TokenPosition breakpoint_pos =
      ResolveBreakpointPos(in_bytecode, function, token_pos, last_token_pos,
                           requested_column, exact_token_pos);
  if (!breakpoint_pos.IsReal()) {
    return NULL;
  }
  if (loc == NULL) {
    // Find an existing resolved breakpoint location.
    loc = GetBreakpointLocation(
        script, TokenPosition::kNoSource,
        /* requested_line = */ -1,
        /* requested_column = */ -1,
        in_bytecode ? breakpoint_pos : TokenPosition::kNoSource,
        !in_bytecode ? breakpoint_pos : TokenPosition::kNoSource);
  }
  if (loc == NULL) {
    // Find an existing unresolved breakpoint location.
    loc = GetBreakpointLocation(script, token_pos, requested_line,
                                requested_column);
  }
  if (loc == NULL) {
    loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
                                 requested_line, requested_column);
    RegisterBreakpointLocation(loc);
  }
  // A source breakpoint for this location may already exists, but it may
  // not yet be resolved in both bytecode and code.
  if (loc->IsResolved(in_bytecode)) {
    return loc;
  }
  loc->SetResolved(in_bytecode, function, breakpoint_pos);

  // Create code breakpoints for all compiled functions we found.
  Function& func = Function::Handle();
  const intptr_t num_functions = functions.Length();
  for (intptr_t i = 0; i < num_functions; i++) {
    func ^= functions.At(i);
    ASSERT((in_bytecode && func.HasBytecode()) ||
           (!in_bytecode && func.HasCode()));
    MakeCodeBreakpointAt(func, loc);
  }
  if (FLAG_verbose_debug) {
    intptr_t line_number;
    intptr_t column_number;
    script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
    OS::PrintErr(
        "Resolved BP for "
        "function '%s' at line %" Pd " col %" Pd "\n",
        func.ToFullyQualifiedCString(), line_number, column_number);
  }
  return loc;
}

BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
                                            TokenPosition token_pos,
                                            TokenPosition last_token_pos,
                                            intptr_t requested_line,
                                            intptr_t requested_column,
                                            const Function& function) {
  Function& func = Function::Handle();
  if (function.IsNull()) {
    if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
      return NULL;
    }
    // If func was not set (still Null), the best fit is a field.
  } else {
    func = function.raw();
    if (!func.token_pos().IsReal()) {
      return NULL;  // Missing source positions in bytecode?
    }
  }
  if (!func.IsNull()) {
    // There may be more than one function object for a given function
    // in source code. There may be implicit closure functions, and
    // there may be copies of mixin functions. Collect all compiled
    // functions whose source code range matches exactly the best fit
    // function we found.
    GrowableObjectArray& bytecode_functions =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    GrowableObjectArray& code_functions =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
                          &bytecode_functions, &code_functions);

    if (bytecode_functions.Length() > 0 || code_functions.Length() > 0) {
      // One or more function object containing this breakpoint location
      // have already been compiled. We can resolve the breakpoint now.
      // If requested_column is larger than zero, [token_pos, last_token_pos]
      // governs one single line of code.
      TokenPosition exact_token_pos = TokenPosition(-1);
      if (token_pos != last_token_pos && requested_column >= 0) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        exact_token_pos =
            FindExactTokenPosition(script, token_pos, requested_column);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      }
      // Since source positions may differ in code and bytecode, process
      // breakpoints in bytecode and code separately.
      BreakpointLocation* loc = NULL;
      if (bytecode_functions.Length() > 0) {
        loc = SetCodeBreakpoints(true, loc, script, token_pos, last_token_pos,
                                 requested_line, requested_column,
                                 exact_token_pos, bytecode_functions);
      }
      if (code_functions.Length() > 0) {
        DeoptimizeWorld();
        loc = SetCodeBreakpoints(false, loc, script, token_pos, last_token_pos,
                                 requested_line, requested_column,
                                 exact_token_pos, code_functions);
      }
      if (loc != NULL) {
        return loc;
      }
    }
  }
  // There is either an uncompiled function, or an uncompiled function literal
  // initializer of a field at |token_pos|. Hence, Register an unresolved
  // breakpoint.
  if (FLAG_verbose_debug) {
    intptr_t line_number;
    intptr_t column_number;
    script.GetTokenLocation(token_pos, &line_number, &column_number);
    if (func.IsNull()) {
      OS::PrintErr(
          "Registering pending breakpoint for "
          "an uncompiled function literal at line %" Pd " col %" Pd "\n",
          line_number, column_number);
    } else {
      OS::PrintErr(
          "Registering pending breakpoint for "
          "uncompiled function '%s' at line %" Pd " col %" Pd "\n",
          func.ToFullyQualifiedCString(), line_number, column_number);
    }
  }
  BreakpointLocation* loc =
      GetBreakpointLocation(script, token_pos, -1, requested_column);
  if (loc == NULL) {
    loc = new BreakpointLocation(script, token_pos, last_token_pos,
                                 requested_line, requested_column);
    RegisterBreakpointLocation(loc);
  }
  return loc;
}

// Synchronize the enabled/disabled state of all code breakpoints
// associated with the breakpoint location loc.
void Debugger::SyncBreakpointLocation(BreakpointLocation* loc) {
  bool any_enabled = loc->AnyEnabled();

  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != NULL) {
    if (loc == cbpt->bpt_location()) {
      if (any_enabled) {
        cbpt->Enable();
      } else {
        cbpt->Disable();
      }
    }
    cbpt = cbpt->next();
  }
}

Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
                                           bool single_shot) {
  ASSERT(!target_function.IsNull());
  if (!target_function.is_debuggable()) {
    return NULL;
  }
  const Script& script = Script::Handle(target_function.script());
  BreakpointLocation* bpt_location = SetBreakpoint(
      script, target_function.token_pos(), target_function.end_token_pos(), -1,
      -1 /* no requested line/col */, target_function);
  if (bpt_location == NULL) {
    return NULL;
  }

  if (single_shot) {
    return bpt_location->AddSingleShot(this);
  } else {
    return bpt_location->AddRepeated(this);
  }
}

Breakpoint* Debugger::SetBreakpointAtActivation(const Instance& closure,
                                                bool for_over_await) {
  if (!closure.IsClosure()) {
    return NULL;
  }
  const Function& func = Function::Handle(Closure::Cast(closure).function());
  const Script& script = Script::Handle(func.script());
  BreakpointLocation* bpt_location =
      SetBreakpoint(script, func.token_pos(), func.end_token_pos(), -1,
                    -1 /* no line/col */, func);
  return bpt_location->AddPerClosure(this, closure, for_over_await);
}

Breakpoint* Debugger::BreakpointAtActivation(const Instance& closure) {
  if (!closure.IsClosure()) {
    return NULL;
  }

  BreakpointLocation* loc = breakpoint_locations_;
  while (loc != NULL) {
    Breakpoint* bpt = loc->breakpoints();
    while (bpt != NULL) {
      if (bpt->IsPerClosure()) {
        if (closure.raw() == bpt->closure()) {
          return bpt;
        }
      }
      bpt = bpt->next();
    }
    loc = loc->next();
  }

  return NULL;
}

Breakpoint* Debugger::SetBreakpointAtLine(const String& script_url,
                                          intptr_t line_number) {
  // Prevent future tests from calling this function in the wrong
  // execution state.  If you hit this assert, consider using
  // Dart_SetBreakpoint instead.
  ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);

  BreakpointLocation* loc =
      BreakpointLocationAtLineCol(script_url, line_number, -1 /* no column */);
  if (loc != NULL) {
    return loc->AddRepeated(this);
  }
  return NULL;
}

Breakpoint* Debugger::SetBreakpointAtLineCol(const String& script_url,
                                             intptr_t line_number,
                                             intptr_t column_number) {
  // Prevent future tests from calling this function in the wrong
  // execution state.  If you hit this assert, consider using
  // Dart_SetBreakpoint instead.
  ASSERT(Thread::Current()->execution_state() == Thread::kThreadInVM);

  BreakpointLocation* loc =
      BreakpointLocationAtLineCol(script_url, line_number, column_number);
  if (loc != NULL) {
    return loc->AddRepeated(this);
  }
  return NULL;
}

BreakpointLocation* Debugger::BreakpointLocationAtLineCol(
    const String& script_url,
    intptr_t line_number,
    intptr_t column_number) {
  Zone* zone = Thread::Current()->zone();
  Library& lib = Library::Handle(zone);
  Script& script = Script::Handle(zone);
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate_->object_store()->libraries());
  const GrowableObjectArray& scripts =
      GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
  bool is_package = script_url.StartsWith(Symbols::PackageScheme());
  for (intptr_t i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    // Ensure that all top-level members are loaded so their scripts
    // are available for look up. When certain script only contains
    // top level functions, scripts could still be loaded correctly.
    lib.EnsureTopLevelClassIsFinalized();
    script = lib.LookupScript(script_url, !is_package);
    if (!script.IsNull()) {
      scripts.Add(script);
    }
  }
  if (scripts.Length() == 0) {
    // No script found with given url. Create a latent breakpoint which
    // will be set if the url is loaded later.
    BreakpointLocation* latent_bpt =
        GetLatentBreakpoint(script_url, line_number, column_number);
    if (FLAG_verbose_debug) {
      OS::PrintErr(
          "Set latent breakpoint in url '%s' at "
          "line %" Pd " col %" Pd "\n",
          script_url.ToCString(), line_number, column_number);
    }
    return latent_bpt;
  }
  if (scripts.Length() > 1) {
    if (FLAG_verbose_debug) {
      OS::PrintErr("Multiple scripts match url '%s'\n", script_url.ToCString());
    }
    return NULL;
  }
  script ^= scripts.At(0);
  TokenPosition first_token_idx, last_token_idx;
  script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
  if (!first_token_idx.IsReal()) {
    // Script does not contain the given line number.
    if (FLAG_verbose_debug) {
      OS::PrintErr("Script '%s' does not contain line number %" Pd "\n",
                   script_url.ToCString(), line_number);
    }
    return NULL;
  } else if (!last_token_idx.IsReal()) {
    // Line does not contain any tokens.
    if (FLAG_verbose_debug) {
      OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
                   script_url.ToCString());
    }
    return NULL;
  }

  BreakpointLocation* loc = NULL;
  ASSERT(first_token_idx <= last_token_idx);
  while ((loc == NULL) && (first_token_idx <= last_token_idx)) {
    loc = SetBreakpoint(script, first_token_idx, last_token_idx, line_number,
                        column_number, Function::Handle());
    first_token_idx.Next();
  }
  if ((loc == NULL) && FLAG_verbose_debug) {
    OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
                 script_url.ToCString());
  }
  return loc;
}

// static
void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != NULL);
  BreakpointLocation* loc = breakpoint_locations_;
  while (loc != NULL) {
    loc->VisitObjectPointers(visitor);
    loc = loc->next();
  }
  loc = latent_locations_;
  while (loc != NULL) {
    loc->VisitObjectPointers(visitor);
    loc = loc->next();
  }
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != NULL) {
    cbpt->VisitObjectPointers(visitor);
    cbpt = cbpt->next();
  }
  visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_frame_awaiter_));
}

void Debugger::Pause(ServiceEvent* event) {
  ASSERT(event->IsPause());      // Should call InvokeEventHandler instead.
  ASSERT(!ignore_breakpoints_);  // We shouldn't get here when ignoring bpts.
  ASSERT(!IsPaused());           // No recursive pausing.

  pause_event_ = event;
  pause_event_->UpdateTimestamp();

  // We are about to invoke the debugger's event handler. Disable
  // interrupts for this thread while waiting for debug commands over
  // the service protocol.
  {
    Thread* thread = Thread::Current();
    DisableThreadInterruptsScope dtis(thread);
    TIMELINE_DURATION(thread, Debugger, "Debugger Pause");

    // Send the pause event.
    Service::HandleEvent(event);

    {
      TransitionVMToNative transition(thread);
      isolate_->PauseEventHandler();
    }

    // Notify the service that we have resumed.
    const Error& error = Error::Handle(Thread::Current()->sticky_error());
    ASSERT(error.IsNull() || error.IsUnwindError() ||
           error.IsUnhandledException());

    // Only send a resume event when the isolate is not unwinding.
    if (!error.IsUnwindError()) {
      ServiceEvent resume_event(event->isolate(), ServiceEvent::kResume);
      resume_event.set_top_frame(event->top_frame());
      Service::HandleEvent(&resume_event);
    }
  }

  if (needs_breakpoint_cleanup_) {
    RemoveUnlinkedCodeBreakpoints();
  }
  pause_event_ = NULL;
}

void Debugger::EnterSingleStepMode() {
  ResetSteppingFramePointers();
  DeoptimizeWorld();
  NotifySingleStepping(true);
}

void Debugger::ResetSteppingFramePointers() {
  stepping_fp_ = 0;
  async_stepping_fp_ = 0;
}

bool Debugger::SteppedForSyntheticAsyncBreakpoint() const {
  return synthetic_async_breakpoint_ != NULL;
}

void Debugger::CleanupSyntheticAsyncBreakpoint() {
  if (synthetic_async_breakpoint_ != NULL) {
    RemoveBreakpoint(synthetic_async_breakpoint_->id());
    synthetic_async_breakpoint_ = NULL;
  }
}

void Debugger::RememberTopFrameAwaiter() {
  if (!FLAG_async_debugger) {
    return;
  }
  if (stack_trace_->Length() > 0) {
    top_frame_awaiter_ = stack_trace_->FrameAt(0)->GetAsyncAwaiter();
  } else {
    top_frame_awaiter_ = Object::null();
  }
}

void Debugger::SetAsyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
  if (!FLAG_async_debugger) {
    return;
  }
  if ((stack_trace->Length()) > 0 &&
      (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
       stack_trace->FrameAt(0)->function().IsAsyncGenClosure())) {
    async_stepping_fp_ = stack_trace->FrameAt(0)->fp();
  } else {
    async_stepping_fp_ = 0;
  }
}

void Debugger::SetSyncSteppingFramePointer(DebuggerStackTrace* stack_trace) {
  if (stack_trace->Length() > 0) {
    stepping_fp_ = stack_trace->FrameAt(0)->fp();
  } else {
    stepping_fp_ = 0;
  }
}

void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace,
                                     bool skip_next_step) {
  ResetSteppingFramePointers();
  RememberTopFrameAwaiter();
  if (resume_action_ == kStepInto) {
    // When single stepping, we need to deoptimize because we might be
    // stepping into optimized code.  This happens in particular if
    // the isolate has been interrupted, but can happen in other cases
    // as well.  We need to deoptimize the world in case we are about
    // to call an optimized function.
    DeoptimizeWorld();
    NotifySingleStepping(true);
    skip_next_step_ = skip_next_step;
    SetAsyncSteppingFramePointer(stack_trace);
    if (FLAG_verbose_debug) {
      OS::PrintErr("HandleSteppingRequest- kStepInto\n");
    }
  } else if (resume_action_ == kStepOver) {
    DeoptimizeWorld();
    NotifySingleStepping(true);
    skip_next_step_ = skip_next_step;
    SetSyncSteppingFramePointer(stack_trace);
    SetAsyncSteppingFramePointer(stack_trace);
    if (FLAG_verbose_debug) {
      OS::PrintErr("HandleSteppingRequest- kStepOver %" Px "\n", stepping_fp_);
    }
  } else if (resume_action_ == kStepOut) {
    if (FLAG_async_debugger) {
      if (stack_trace->FrameAt(0)->function().IsAsyncClosure() ||
          stack_trace->FrameAt(0)->function().IsAsyncGenClosure()) {
        // Request to step out of an async/async* closure.
        const Object& async_op =
            Object::Handle(stack_trace->FrameAt(0)->GetAsyncAwaiter());
        if (!async_op.IsNull()) {
          // Step out to the awaiter.
          ASSERT(async_op.IsClosure());
          AsyncStepInto(Closure::Cast(async_op));
          return;
        }
      }
    }
    // Fall through to synchronous stepping.
    DeoptimizeWorld();
    NotifySingleStepping(true);
    // Find topmost caller that is debuggable.
    for (intptr_t i = 1; i < stack_trace->Length(); i++) {
      ActivationFrame* frame = stack_trace->FrameAt(i);
      if (frame->IsDebuggable()) {
        stepping_fp_ = frame->fp();
        break;
      }
    }
    if (FLAG_verbose_debug) {
      OS::PrintErr("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_);
    }
  } else if (resume_action_ == kStepRewind) {
    if (FLAG_trace_rewind) {
      OS::PrintErr("Rewinding to frame %" Pd "\n", resume_frame_index_);
      OS::PrintErr(
          "-------------------------\n"
          "All frames...\n\n");
      StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                                  Thread::Current(),
                                  StackFrameIterator::kNoCrossThreadIteration);
      StackFrame* frame = iterator.NextFrame();
      intptr_t num = 0;
      while ((frame != NULL)) {
        OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
        frame = iterator.NextFrame();
      }
    }
    RewindToFrame(resume_frame_index_);
    UNREACHABLE();
  }
}

void Debugger::CacheStackTraces(DebuggerStackTrace* stack_trace,
                                DebuggerStackTrace* async_causal_stack_trace,
                                DebuggerStackTrace* awaiter_stack_trace) {
  ASSERT(stack_trace_ == NULL);
  stack_trace_ = stack_trace;
  ASSERT(async_causal_stack_trace_ == NULL);
  async_causal_stack_trace_ = async_causal_stack_trace;
  ASSERT(awaiter_stack_trace_ == NULL);
  awaiter_stack_trace_ = awaiter_stack_trace;
}

void Debugger::ClearCachedStackTraces() {
  stack_trace_ = NULL;
  async_causal_stack_trace_ = NULL;
  awaiter_stack_trace_ = NULL;
}

static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack,
                                         intptr_t frame_index) {
  for (intptr_t i = frame_index + 1; i < stack->Length(); i++) {
    ActivationFrame* frame = stack->FrameAt(i);
    if (frame->IsRewindable()) {
      return i;
    }
  }
  return -1;
}

// Can the top frame be rewound?
bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const {
  // check rewind pc is found
  DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace();
  intptr_t num_frames = stack->Length();
  if (frame_index < 1 || frame_index >= num_frames) {
    if (error) {
      *error = Thread::Current()->zone()->PrintToString(
          "Frame must be in bounds [1..%" Pd
          "]: "
          "saw %" Pd "",
          num_frames - 1, frame_index);
    }
    return false;
  }
  ActivationFrame* frame = stack->FrameAt(frame_index);
  if (!frame->IsRewindable()) {
    intptr_t next_index = FindNextRewindFrameIndex(stack, frame_index);
    if (next_index > 0) {
      *error = Thread::Current()->zone()->PrintToString(
          "Cannot rewind to frame %" Pd
          " due to conflicting compiler "
          "optimizations. "
          "Run the vm with --no-prune-dead-locals to disallow these "
          "optimizations. "
          "Next valid rewind frame is %" Pd ".",
          frame_index, next_index);
    } else {
      *error = Thread::Current()->zone()->PrintToString(
          "Cannot rewind to frame %" Pd
          " due to conflicting compiler "
          "optimizations. "
          "Run the vm with --no-prune-dead-locals to disallow these "
          "optimizations.",
          frame_index);
    }
    return false;
  }
  return true;
}

// Given a return address pc, find the "rewind" pc, which is the pc
// before the corresponding call.
static uword LookupRewindPc(const Code& code, uword pc) {
  ASSERT(!code.is_optimized());
  ASSERT(code.ContainsInstructionAt(pc));

  uword pc_offset = pc - code.PayloadStart();
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(code.pc_descriptors());
  PcDescriptors::Iterator iter(
      descriptors, RawPcDescriptors::kRewind | RawPcDescriptors::kIcCall |
                       RawPcDescriptors::kUnoptStaticCall);
  intptr_t rewind_deopt_id = -1;
  uword rewind_pc = 0;
  while (iter.MoveNext()) {
    if (iter.Kind() == RawPcDescriptors::kRewind) {
      // Remember the last rewind so we don't need to iterator twice.
      rewind_pc = code.PayloadStart() + iter.PcOffset();
      rewind_deopt_id = iter.DeoptId();
    }
    if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) {
      return rewind_pc;
    }
  }
  return 0;
}

void Debugger::RewindToFrame(intptr_t frame_index) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Code& code = Code::Handle(zone);
  Function& function = Function::Handle(zone);

  // Find the requested frame.
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  intptr_t current_frame = 0;
  for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
       frame = iterator.NextFrame()) {
    ASSERT(frame->IsValid());
    if (frame->IsDartFrame()) {
      code = frame->LookupDartCode();
      function = code.function();
      if (!IsFunctionVisible(function)) {
        continue;
      }
      if (code.is_optimized()) {
        intptr_t sub_index = 0;
        for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
             it.Advance()) {
          if (current_frame == frame_index) {
            RewindToOptimizedFrame(frame, code, sub_index);
            UNREACHABLE();
          }
          current_frame++;
          sub_index++;
        }
      } else {
        if (current_frame == frame_index) {
          // We are rewinding to an unoptimized frame.
          RewindToUnoptimizedFrame(frame, code);
          UNREACHABLE();
        }
        current_frame++;
      }
    }
  }
  UNIMPLEMENTED();
}

void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) {
  // We will be jumping out of the debugger rather than exiting this
  // function, so prepare the debugger state.
  ClearCachedStackTraces();
  resume_action_ = kContinue;
  resume_frame_index_ = -1;
  EnterSingleStepMode();

  uword rewind_pc = LookupRewindPc(code, frame->pc());
  if (FLAG_trace_rewind && rewind_pc == 0) {
    OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc());
  }
  ASSERT(rewind_pc != 0);
  if (FLAG_trace_rewind) {
    OS::PrintErr(
        "===============================\n"
        "Rewinding to unoptimized frame:\n"
        "    rewind_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
        ")\n"
        "===============================\n",
        rewind_pc, frame->sp(), frame->fp());
  }
  Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(),
                          frame->fp(), true /* clear lazy deopt at target */);
  UNREACHABLE();
}

void Debugger::RewindToOptimizedFrame(StackFrame* frame,
                                      const Code& optimized_code,
                                      intptr_t sub_index) {
  post_deopt_frame_index_ = sub_index;

  // We will be jumping out of the debugger rather than exiting this
  // function, so prepare the debugger state.
  ClearCachedStackTraces();
  resume_action_ = kContinue;
  resume_frame_index_ = -1;
  EnterSingleStepMode();

  if (FLAG_trace_rewind) {
    OS::PrintErr(
        "===============================\n"
        "Deoptimizing frame for rewind:\n"
        "    deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px
        ")\n"
        "===============================\n",
        frame->pc(), frame->sp(), frame->fp());
  }
  Thread* thread = Thread::Current();
  thread->set_resume_pc(frame->pc());
  uword deopt_stub_pc = StubCode::DeoptForRewind().EntryPoint();
  Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(),
                          true /* clear lazy deopt at target */);
  UNREACHABLE();
}

void Debugger::RewindPostDeopt() {
  intptr_t rewind_frame = post_deopt_frame_index_;
  post_deopt_frame_index_ = -1;
  if (FLAG_trace_rewind) {
    OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame);
    OS::PrintErr(
        "-------------------------\n"
        "All frames...\n\n");
    StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                                Thread::Current(),
                                StackFrameIterator::kNoCrossThreadIteration);
    StackFrame* frame = iterator.NextFrame();
    intptr_t num = 0;
    while ((frame != NULL)) {
      OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString());
      frame = iterator.NextFrame();
    }
  }

  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Code& code = Code::Handle(zone);

  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  intptr_t current_frame = 0;
  for (StackFrame* frame = iterator.NextFrame(); frame != NULL;
       frame = iterator.NextFrame()) {
    ASSERT(frame->IsValid());
    if (frame->IsDartFrame()) {
      code = frame->LookupDartCode();
      ASSERT(!code.is_optimized());
      if (current_frame == rewind_frame) {
        RewindToUnoptimizedFrame(frame, code);
        UNREACHABLE();
      }
      current_frame++;
    }
  }
}

// static
bool Debugger::IsDebuggable(const Function& func) {
  if (!func.is_debuggable()) {
    return false;
  }
  const Class& cls = Class::Handle(func.Owner());
  const Library& lib = Library::Handle(cls.library());
  return lib.IsDebuggable();
}

bool Debugger::IsDebugging(Thread* thread, const Function& func) {
  Debugger* debugger = thread->isolate()->debugger();
  return debugger->IsStepping() ||
         debugger->HasBreakpoint(func, thread->zone());
}

void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
  resume_action_ = kContinue;
  ResetSteppingFramePointers();
  NotifySingleStepping(false);
  ASSERT(!IsPaused());
  if ((bpt != NULL) && bpt->IsSingleShot()) {
    RemoveBreakpoint(bpt->id());
    bpt = NULL;
  }

  ServiceEvent event(isolate_, ServiceEvent::kPauseBreakpoint);
  event.set_top_frame(top_frame);
  event.set_breakpoint(bpt);
  event.set_at_async_jump(IsAtAsyncJump(top_frame));
  Pause(&event);
}

bool Debugger::IsAtAsyncJump(ActivationFrame* top_frame) {
  Zone* zone = Thread::Current()->zone();
  Object& closure_or_null =
      Object::Handle(zone, top_frame->GetAsyncOperation());
  if (!closure_or_null.IsNull()) {
    ASSERT(closure_or_null.IsInstance());
    ASSERT(Instance::Cast(closure_or_null).IsClosure());
    const Script& script = Script::Handle(zone, top_frame->SourceScript());
    ASSERT(script.kind() == RawScript::kKernelTag);
    // Are we at a yield point (previous await)?
    const Array& yields = Array::Handle(script.yield_positions());
    intptr_t looking_for = top_frame->TokenPos().value();
    Smi& value = Smi::Handle(zone);
    for (int i = 0; i < yields.Length(); i++) {
      value ^= yields.At(i);
      if (value.Value() == looking_for) return true;
    }
  }
  return false;
}

RawError* Debugger::PauseStepping() {
  ASSERT(isolate_->single_step());
  // Don't pause recursively.
  if (IsPaused()) {
    return Error::null();
  }
  if (skip_next_step_) {
    skip_next_step_ = false;
    return Error::null();
  }

  // Check whether we are in a Dart function that the user is
  // interested in. If we saved the frame pointer of a stack frame
  // the user is interested in, we ignore the single step if we are
  // in a callee of that frame. Note that we assume that the stack
  // grows towards lower addresses.
  ActivationFrame* frame = TopDartFrame();
  ASSERT(frame != NULL);

  if (FLAG_async_debugger) {
    if ((async_stepping_fp_ != 0) && (top_frame_awaiter_ != Object::null())) {
      // Check if the user has single stepped out of an async function with
      // an awaiter. The first check handles the case of calling into the
      // async machinery as we finish the async function. The second check
      // handles the case of returning from an async function.
      const bool exited_async_function =
          (IsCalleeFrameOf(async_stepping_fp_, frame->fp()) &&
           frame->IsAsyncMachinery()) ||
          IsCalleeFrameOf(frame->fp(), async_stepping_fp_);
      if (exited_async_function) {
        // Step to the top frame awaiter.
        const Object& async_op = Object::Handle(top_frame_awaiter_);
        top_frame_awaiter_ = Object::null();
        AsyncStepInto(Closure::Cast(async_op));
        return Error::null();
      }
    }
  }

  if (stepping_fp_ != 0) {
    // There is an "interesting frame" set. Only pause at appropriate
    // locations in this frame.
    if (IsCalleeFrameOf(stepping_fp_, frame->fp())) {
      // We are in a callee of the frame we're interested in.
      // Ignore this stepping break.
      return Error::null();
    } else if (IsCalleeFrameOf(frame->fp(), stepping_fp_)) {
      // We returned from the "interesting frame", there can be no more
      // stepping breaks for it. Pause at the next appropriate location
      // and let the user set the "interesting" frame again.
      ResetSteppingFramePointers();
    }
  }

  if (!frame->IsDebuggable()) {
    return Error::null();
  }
  if (!frame->TokenPos().IsDebugPause()) {
    return Error::null();
  }

  // If there is an active breakpoint at this pc, then we should have
  // already bailed out of this function in the skip_next_step_ test
  // above.
  ASSERT(!HasActiveBreakpoint(frame->pc()));

  if (FLAG_verbose_debug) {
    OS::PrintErr(">>> single step break at %s:%" Pd " (func %s token %s)\n",
                 String::Handle(frame->SourceUrl()).ToCString(),
                 frame->LineNumber(),
                 String::Handle(frame->QualifiedFunctionName()).ToCString(),
                 frame->TokenPos().ToCString());
  }

  CacheStackTraces(CollectStackTrace(), CollectAsyncCausalStackTrace(),
                   CollectAwaiterReturnStackTrace());
  if (SteppedForSyntheticAsyncBreakpoint()) {
    CleanupSyntheticAsyncBreakpoint();
  }
  SignalPausedEvent(frame, NULL);
  HandleSteppingRequest(stack_trace_);
  ClearCachedStackTraces();

  // If any error occurred while in the debug message loop, return it here.
  return Thread::Current()->StealStickyError();
}

RawError* Debugger::PauseBreakpoint() {
  // We ignore this breakpoint when the VM is executing code invoked
  // by the debugger to evaluate variables values, or when we see a nested
  // breakpoint or exception event.
  if (ignore_breakpoints_ || IsPaused()) {
    return Error::null();
  }
  DebuggerStackTrace* stack_trace = CollectStackTrace();
  ASSERT(stack_trace->Length() > 0);
  ActivationFrame* top_frame = stack_trace->FrameAt(0);
  ASSERT(top_frame != NULL);
  CodeBreakpoint* cbpt = GetCodeBreakpoint(top_frame->pc());
  ASSERT(cbpt != NULL);

  Breakpoint* bpt_hit = FindHitBreakpoint(cbpt->bpt_location_, top_frame);
  if (bpt_hit == NULL) {
    return Error::null();
  }

  if (bpt_hit->is_synthetic_async()) {
    DebuggerStackTrace* stack_trace = CollectStackTrace();
    ASSERT(stack_trace->Length() > 0);
    CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
                     CollectAwaiterReturnStackTrace());

    // Hit a synthetic async breakpoint.
    if (FLAG_verbose_debug) {
      OS::PrintErr(">>> hit synthetic breakpoint at %s:%" Pd
                   " "
                   "(token %s) (address %#" Px ")\n",
                   String::Handle(cbpt->SourceUrl()).ToCString(),
                   cbpt->LineNumber(), cbpt->token_pos().ToCString(),
                   top_frame->pc());
    }

    ASSERT(synthetic_async_breakpoint_ == NULL);
    synthetic_async_breakpoint_ = bpt_hit;
    bpt_hit = NULL;

    // We are at the entry of an async function.
    // We issue a step over to resume at the point after the await statement.
    SetResumeAction(kStepOver);
    // When we single step from a user breakpoint, our next stepping
    // point will be at the exact same pc.  Skip it.
    HandleSteppingRequest(stack_trace_, true /* skip next step */);
    ClearCachedStackTraces();
    return Error::null();
  }

  if (FLAG_verbose_debug) {
    OS::PrintErr(">>> hit breakpoint %" Pd " at %s:%" Pd
                 " (token %s) "
                 "(address %#" Px ")\n",
                 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(),
                 cbpt->LineNumber(), cbpt->token_pos().ToCString(),
                 top_frame->pc());
  }

  CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
                   CollectAwaiterReturnStackTrace());
  SignalPausedEvent(top_frame, bpt_hit);
  // When we single step from a user breakpoint, our next stepping
  // point will be at the exact same pc.  Skip it.
  HandleSteppingRequest(stack_trace_, true /* skip next step */);
  ClearCachedStackTraces();

  // If any error occurred while in the debug message loop, return it here.
  return Thread::Current()->StealStickyError();
}

Breakpoint* Debugger::FindHitBreakpoint(BreakpointLocation* location,
                                        ActivationFrame* top_frame) {
  if (location == NULL) {
    return NULL;
  }
  // There may be more than one applicable breakpoint at this location, but we
  // will report only one as reached. If there is a single-shot breakpoint, we
  // favor it; then a closure-specific breakpoint ; then an general breakpoint.

  // First check for a single-shot breakpoint.
  Breakpoint* bpt = location->breakpoints();
  while (bpt != NULL) {
    if (bpt->IsSingleShot()) {
      return bpt;
    }
    bpt = bpt->next();
  }

  // Now check for a closure-specific breakpoint.
  bpt = location->breakpoints();
  while (bpt != NULL) {
    if (bpt->IsPerClosure()) {
      Object& closure = Object::Handle(top_frame->GetClosure());
      ASSERT(closure.IsInstance());
      ASSERT(Instance::Cast(closure).IsClosure());
      if (closure.raw() == bpt->closure()) {
        return bpt;
      }
    }
    bpt = bpt->next();
  }

  // Finally, check for a general breakpoint.
  bpt = location->breakpoints();
  while (bpt != NULL) {
    if (bpt->IsRepeated()) {
      return bpt;
    }
    bpt = bpt->next();
  }

  return NULL;
}

void Debugger::PauseDeveloper(const String& msg) {
  // We ignore this breakpoint when the VM is executing code invoked
  // by the debugger to evaluate variables values, or when we see a nested
  // breakpoint or exception event.
  if (ignore_breakpoints_ || IsPaused()) {
    return;
  }

  DebuggerStackTrace* stack_trace = CollectStackTrace();
  ASSERT(stack_trace->Length() > 0);
  CacheStackTraces(stack_trace, CollectAsyncCausalStackTrace(),
                   CollectAwaiterReturnStackTrace());
  // TODO(johnmccutchan): Send |msg| to Observatory.

  // We are in the native call to Developer_debugger.  the developer
  // gets a better experience by not seeing this call. To accomplish
  // this, we continue execution until the call exits (step out).
  SetResumeAction(kStepOut);
  HandleSteppingRequest(stack_trace_);
  ClearCachedStackTraces();
}

void Debugger::NotifyIsolateCreated() {
  if (NeedsIsolateEvents()) {
    ServiceEvent event(isolate_, ServiceEvent::kIsolateStart);
    InvokeEventHandler(&event);
  }
}

// Return innermost closure contained in 'function' that contains
// the given token position.
// Note: this should only be called for compiled functions and not for
// bytecode functions.
RawFunction* Debugger::FindInnermostClosure(const Function& function,
                                            TokenPosition token_pos) {
  ASSERT(function.HasCode());
  Zone* zone = Thread::Current()->zone();
  const Script& outer_origin = Script::Handle(zone, function.script());
  const GrowableObjectArray& closures = GrowableObjectArray::Handle(
      zone, Isolate::Current()->object_store()->closure_functions());
  const intptr_t num_closures = closures.Length();
  Function& closure = Function::Handle(zone);
  Function& best_fit = Function::Handle(zone);
  for (intptr_t i = 0; i < num_closures; i++) {
    closure ^= closures.At(i);
    if ((function.token_pos() < closure.token_pos()) &&
        (closure.end_token_pos() < function.end_token_pos()) &&
        (closure.token_pos() <= token_pos) &&
        (token_pos <= closure.end_token_pos()) &&
        (closure.script() == outer_origin.raw())) {
      SelectBestFit(&best_fit, &closure);
    }
  }
  return best_fit.raw();
}

#if !defined(DART_PRECOMPILED_RUNTIME)
// On single line of code with given column number,
// Calculate exact tokenPosition
TokenPosition Debugger::FindExactTokenPosition(const Script& script,
                                               TokenPosition start_of_line,
                                               intptr_t column_number) {
  intptr_t line = -1;
  intptr_t col = -1;
  Zone* zone = Thread::Current()->zone();
  kernel::KernelLineStartsReader line_starts_reader(
      TypedData::Handle(zone, script.line_starts()), zone);
  line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
  return TokenPosition(start_of_line.value() + (column_number - col));
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

void Debugger::HandleCodeChange(bool bytecode_loaded, const Function& func) {
  if (breakpoint_locations_ == NULL) {
    // Return with minimal overhead if there are no breakpoints.
    return;
  }
  if (!func.is_debuggable()) {
    // Nothing to do if the function is not debuggable. If there is
    // a pending breakpoint in an inner function (that is debuggable),
    // we'll resolve the breakpoint when the inner function is compiled.
    return;
  }
  // Iterate over all source breakpoints to check whether breakpoints
  // need to be set in the newly compiled function.
  Zone* zone = Thread::Current()->zone();
  Script& script = Script::Handle(zone);
  for (BreakpointLocation* loc = breakpoint_locations_; loc != NULL;
       loc = loc->next()) {
    script = loc->script();
    if (FunctionOverlaps(func, script, loc->token_pos(),
                         loc->end_token_pos())) {
      TokenPosition token_pos = loc->token_pos();
      TokenPosition end_token_pos = loc->end_token_pos();
      if (token_pos != end_token_pos && loc->requested_column_number() >= 0) {
#if !defined(DART_PRECOMPILED_RUNTIME)
        // Narrow down the token position range to a single value
        // if requested column number is provided so that inner
        // Closure won't be missed.
        token_pos = FindExactTokenPosition(script, token_pos,
                                           loc->requested_column_number());
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      }
      if (bytecode_loaded) {
        // func's bytecode was just loaded.
        // If func has an inner closure, we got notified earlier.
        // Therefore we will always resolve the breakpoint correctly to the
        // innermost function without searching for it.
      } else {
        // func was just compiled.
        const Function& inner_function =
            Function::Handle(zone, FindInnermostClosure(func, token_pos));
        if (!inner_function.IsNull()) {
          // The local function of a function we just compiled cannot
          // be compiled already.
          ASSERT(!inner_function.HasCode());
          if (FLAG_verbose_debug) {
            OS::PrintErr(
                "Pending BP remains unresolved in inner function '%s'\n",
                inner_function.ToFullyQualifiedCString());
          }
          continue;
        }

        // TODO(hausner): What should we do if function is optimized?
        // Can we deoptimize the function?
        ASSERT(!func.HasOptimizedCode());
      }

      // There is no local function within func that contains the
      // breakpoint token position. Resolve the breakpoint if necessary
      // and set the code breakpoints.
      if (!loc->IsResolved(bytecode_loaded)) {
        // Resolve source breakpoint in the newly compiled function.
        TokenPosition bp_pos = ResolveBreakpointPos(
            bytecode_loaded, func, loc->token_pos(), loc->end_token_pos(),
            loc->requested_column_number(), token_pos);
        if (!bp_pos.IsDebugPause()) {
          if (FLAG_verbose_debug) {
            OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
                         String::Handle(func.name()).ToCString());
          }
          continue;
        }
        TokenPosition requested_pos = loc->token_pos();
        TokenPosition requested_end_pos = loc->end_token_pos();
        loc->SetResolved(bytecode_loaded, func, bp_pos);
        Breakpoint* bpt = loc->breakpoints();
        while (bpt != NULL) {
          if (FLAG_verbose_debug) {
            OS::PrintErr(
                "Resolved BP %" Pd
                " to pos %s, "
                "function '%s' (requested range %s-%s, "
                "requested col %" Pd ")\n",
                bpt->id(), loc->token_pos().ToCString(),
                func.ToFullyQualifiedCString(), requested_pos.ToCString(),
                requested_end_pos.ToCString(), loc->requested_column_number());
          }
          SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
          bpt = bpt->next();
        }
      }
      ASSERT(loc->IsResolved(bytecode_loaded));
      if (FLAG_verbose_debug) {
        Breakpoint* bpt = loc->breakpoints();
        while (bpt != NULL) {
          OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
                       func.IsClosureFunction() ? "closure" : "function",
                       String::Handle(func.name()).ToCString());
          bpt = bpt->next();
        }
      }
      MakeCodeBreakpointAt(func, loc);
    }
  }
}

void Debugger::NotifyDoneLoading() {
  if (latent_locations_ == NULL) {
    // Common, fast path.
    return;
  }
  Zone* zone = Thread::Current()->zone();
  Library& lib = Library::Handle(zone);
  Script& script = Script::Handle(zone);
  String& url = String::Handle(zone);
  BreakpointLocation* loc = latent_locations_;
  BreakpointLocation* prev_loc = NULL;
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate_->object_store()->libraries());
  while (loc != NULL) {
    url = loc->url();
    bool found_match = false;
    bool is_package = url.StartsWith(Symbols::PackageScheme());
    for (intptr_t i = 0; i < libs.Length(); i++) {
      lib ^= libs.At(i);
      script = lib.LookupScript(url, !is_package);
      if (!script.IsNull()) {
        // Found a script with matching url for this latent breakpoint.
        // Unlink the latent breakpoint from the list.
        found_match = true;
        BreakpointLocation* matched_loc = loc;
        loc = loc->next();
        if (prev_loc == NULL) {
          latent_locations_ = loc;
        } else {
          prev_loc->set_next(loc);
        }
        // Now find the token range at the requested line and make a
        // new unresolved source breakpoint.
        intptr_t line_number = matched_loc->requested_line_number();
        intptr_t column_number = matched_loc->requested_column_number();
        ASSERT(line_number >= 0);
        TokenPosition first_token_pos, last_token_pos;
        script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
        if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) {
          // Script does not contain the given line number or there are no
          // tokens on the line. Drop the breakpoint silently.
          Breakpoint* bpt = matched_loc->breakpoints();
          while (bpt != NULL) {
            if (FLAG_verbose_debug) {
              OS::PrintErr("No code found at line %" Pd
                           ": "
                           "dropping latent breakpoint %" Pd " in '%s'\n",
                           line_number, bpt->id(), url.ToCString());
            }
            Breakpoint* prev = bpt;
            bpt = bpt->next();
            delete prev;
          }
          delete matched_loc;
        } else {
          // We don't expect to already have a breakpoint for this location.
          // If there is one, assert in debug build but silently drop
          // the latent breakpoint in release build.
          BreakpointLocation* existing_loc =
              GetBreakpointLocation(script, first_token_pos, -1, column_number);
          ASSERT(existing_loc == NULL);
          if (existing_loc == NULL) {
            // Create and register a new source breakpoint for the
            // latent breakpoint.
            BreakpointLocation* unresolved_loc =
                new BreakpointLocation(script, first_token_pos, last_token_pos,
                                       line_number, column_number);
            RegisterBreakpointLocation(unresolved_loc);

            // Move breakpoints over.
            Breakpoint* bpt = matched_loc->breakpoints();
            unresolved_loc->set_breakpoints(bpt);
            matched_loc->set_breakpoints(NULL);
            while (bpt != NULL) {
              bpt->set_bpt_location(unresolved_loc);
              if (FLAG_verbose_debug) {
                OS::PrintErr(
                    "Converted latent breakpoint "
                    "%" Pd " in '%s' at line %" Pd " col %" Pd "\n",
                    bpt->id(), url.ToCString(), line_number, column_number);
              }
              bpt = bpt->next();
            }
            SyncBreakpointLocation(unresolved_loc);
          }
          delete matched_loc;
          // Break out of the iteration over loaded libraries. If the
          // same url has been loaded into more than one library, we
          // only set a breakpoint in the first one.
          // TODO(hausner): There is one possible pitfall here.
          // If the user sets a latent breakpoint using a partial url that
          // ends up matching more than one script, the breakpoint might
          // get set in the wrong script.
          // It would be better if we could warn the user if multiple
          // scripts are matching.
          break;
        }
      }
    }
    if (!found_match) {
      // No matching url found in any of the libraries.
      if (FLAG_verbose_debug) {
        Breakpoint* bpt = loc->breakpoints();
        while (bpt != NULL) {
          OS::PrintErr(
              "No match found for latent breakpoint id "
              "%" Pd " with url '%s'\n",
              bpt->id(), url.ToCString());
          bpt = bpt->next();
        }
      }
      loc = loc->next();
    }
  }
}

// TODO(hausner): Could potentially make this faster by checking
// whether the call target at pc is a debugger stub.
bool Debugger::HasActiveBreakpoint(uword pc) {
  CodeBreakpoint* cbpt = GetCodeBreakpoint(pc);
  return (cbpt != NULL) && (cbpt->IsEnabled());
}

CodeBreakpoint* Debugger::GetCodeBreakpoint(uword breakpoint_address) {
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != NULL) {
    if (cbpt->pc() == breakpoint_address) {
      return cbpt;
    }
    cbpt = cbpt->next();
  }
  return NULL;
}

RawCode* Debugger::GetPatchedStubAddress(uword breakpoint_address) {
  CodeBreakpoint* cbpt = GetCodeBreakpoint(breakpoint_address);
  if (cbpt != NULL) {
    return cbpt->OrigStubAddress();
  }
  UNREACHABLE();
  return Code::null();
}

// Remove and delete the source breakpoint bpt and its associated
// code breakpoints.
void Debugger::RemoveBreakpoint(intptr_t bp_id) {
  if (RemoveBreakpointFromTheList(bp_id, &breakpoint_locations_)) {
    return;
  }
  RemoveBreakpointFromTheList(bp_id, &latent_locations_);
}

// Remove and delete the source breakpoint bpt and its associated
// code breakpoints. Returns true, if breakpoint was found and removed,
// returns false, if breakpoint was not found.
bool Debugger::RemoveBreakpointFromTheList(intptr_t bp_id,
                                           BreakpointLocation** list) {
  BreakpointLocation* prev_loc = NULL;
  BreakpointLocation* curr_loc = *list;
  while (curr_loc != NULL) {
    Breakpoint* prev_bpt = NULL;
    Breakpoint* curr_bpt = curr_loc->breakpoints();
    while (curr_bpt != NULL) {
      if (curr_bpt->id() == bp_id) {
        if (prev_bpt == NULL) {
          curr_loc->set_breakpoints(curr_bpt->next());
        } else {
          prev_bpt->set_next(curr_bpt->next());
        }

        // Send event to client before the breakpoint's fields are
        // poisoned and deleted.
        SendBreakpointEvent(ServiceEvent::kBreakpointRemoved, curr_bpt);

        curr_bpt->set_next(NULL);
        curr_bpt->set_bpt_location(NULL);
        // Remove possible references to the breakpoint.
        if (pause_event_ != NULL && pause_event_->breakpoint() == curr_bpt) {
          pause_event_->set_breakpoint(NULL);
        }
        if (synthetic_async_breakpoint_ == curr_bpt) {
          synthetic_async_breakpoint_ = NULL;
        }
        delete curr_bpt;
        curr_bpt = NULL;

        // Delete the breakpoint location object if there are no more
        // breakpoints at that location.
        if (curr_loc->breakpoints() == NULL) {
          if (prev_loc == NULL) {
            *list = curr_loc->next();
          } else {
            prev_loc->set_next(curr_loc->next());
          }

          if (!curr_loc->IsLatent()) {
            // Remove references from code breakpoints to this breakpoint
            // location and disable them.
            // Latent breakpoint locations won't have code breakpoints.
            UnlinkCodeBreakpoints(curr_loc);
          }
          BreakpointLocation* next_loc = curr_loc->next();
          delete curr_loc;
          curr_loc = next_loc;
        }

        // The code breakpoints will be deleted when the VM resumes
        // after the pause event.
        return true;
      }

      prev_bpt = curr_bpt;
      curr_bpt = curr_bpt->next();
    }
    prev_loc = curr_loc;
    curr_loc = curr_loc->next();
  }
  // breakpoint with bp_id does not exist, nothing to do.
  return false;
}

// Unlink code breakpoints from the given breakpoint location.
// They will later be deleted when control returns from the pause event
// callback. Also, disable the breakpoint so it no longer fires if it
// should be hit before it gets deleted.
void Debugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) {
  ASSERT(bpt_location != NULL);
  CodeBreakpoint* curr_bpt = code_breakpoints_;
  while (curr_bpt != NULL) {
    if (curr_bpt->bpt_location() == bpt_location) {
      curr_bpt->Disable();
      curr_bpt->set_bpt_location(NULL);
      needs_breakpoint_cleanup_ = true;
    }
    curr_bpt = curr_bpt->next();
  }
}

// Remove and delete unlinked code breakpoints, i.e. breakpoints that
// are not associated with a breakpoint location.
void Debugger::RemoveUnlinkedCodeBreakpoints() {
  CodeBreakpoint* prev_bpt = NULL;
  CodeBreakpoint* curr_bpt = code_breakpoints_;
  while (curr_bpt != NULL) {
    if (curr_bpt->bpt_location() == NULL) {
      if (prev_bpt == NULL) {
        code_breakpoints_ = code_breakpoints_->next();
      } else {
        prev_bpt->set_next(curr_bpt->next());
      }
      CodeBreakpoint* temp_bpt = curr_bpt;
      curr_bpt = curr_bpt->next();
      temp_bpt->Disable();
      delete temp_bpt;
    } else {
      prev_bpt = curr_bpt;
      curr_bpt = curr_bpt->next();
    }
  }
  needs_breakpoint_cleanup_ = false;
}

BreakpointLocation* Debugger::GetBreakpointLocation(
    const Script& script,
    TokenPosition token_pos,
    intptr_t requested_line,
    intptr_t requested_column,
    TokenPosition bytecode_token_pos,
    TokenPosition code_token_pos) {
  BreakpointLocation* loc = breakpoint_locations_;
  while (loc != NULL) {
    if (loc->script_ == script.raw() &&
        (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
        ((requested_line == -1) ||
         (loc->requested_line_number_ == requested_line)) &&
        ((requested_column == -1) ||
         (loc->requested_column_number_ == requested_column)) &&
        (!bytecode_token_pos.IsReal() ||
         (loc->bytecode_token_pos_ == bytecode_token_pos)) &&
        (!code_token_pos.IsReal() ||
         (loc->code_token_pos_ == code_token_pos))) {
      return loc;
    }
    loc = loc->next();
  }
  return NULL;
}

Breakpoint* Debugger::GetBreakpointById(intptr_t id) {
  Breakpoint* bpt = GetBreakpointByIdInTheList(id, breakpoint_locations_);
  if (bpt != NULL) {
    return bpt;
  }
  return GetBreakpointByIdInTheList(id, latent_locations_);
}

Breakpoint* Debugger::GetBreakpointByIdInTheList(intptr_t id,
                                                 BreakpointLocation* list) {
  BreakpointLocation* loc = list;
  while (loc != NULL) {
    Breakpoint* bpt = loc->breakpoints();
    while (bpt != NULL) {
      if (bpt->id() == id) {
        return bpt;
      }
      bpt = bpt->next();
    }
    loc = loc->next();
  }
  return NULL;
}

void Debugger::MaybeAsyncStepInto(const Closure& async_op) {
  if (FLAG_async_debugger && IsSingleStepping()) {
    // We are single stepping, set a breakpoint on the closure activation
    // and resume execution so we can hit the breakpoint.
    AsyncStepInto(async_op);
  }
}

void Debugger::AsyncStepInto(const Closure& async_op) {
  SetBreakpointAtActivation(async_op, true);
  Continue();
}

void Debugger::Continue() {
  SetResumeAction(kContinue);
  stepping_fp_ = 0;
  async_stepping_fp_ = 0;
  NotifySingleStepping(false);
}

BreakpointLocation* Debugger::GetLatentBreakpoint(const String& url,
                                                  intptr_t line,
                                                  intptr_t column) {
  BreakpointLocation* loc = latent_locations_;
  String& bpt_url = String::Handle();
  while (loc != NULL) {
    bpt_url = loc->url();
    if (bpt_url.Equals(url) && (loc->requested_line_number() == line) &&
        (loc->requested_column_number() == column)) {
      return loc;
    }
    loc = loc->next();
  }
  // No breakpoint for this location requested. Allocate new one.
  loc = new BreakpointLocation(url, line, column);
  loc->set_next(latent_locations_);
  latent_locations_ = loc;
  return loc;
}

void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
  ASSERT(loc->next() == NULL);
  loc->set_next(breakpoint_locations_);
  breakpoint_locations_ = loc;
}

void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* cbpt) {
  ASSERT(cbpt->next() == NULL);
  cbpt->set_next(code_breakpoints_);
  code_breakpoints_ = cbpt;
}

#endif  // !PRODUCT

}  // namespace dart
