// 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 "vm/bytecode_reader.h"
#include "vm/closure_functions_cache.h"
#include "vm/code_descriptors.h"
#include "vm/code_patcher.h"
#include "vm/compiler/api/deopt_id.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/isolate_reload.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"
#include "vm/zone_text_buffer.h"

#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/deopt_instructions.h"
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {

DEFINE_FLAG(bool,
            trace_debugger_stacktrace,
            false,
            "Trace debugger stacktrace collection");
DEFINE_FLAG(bool,
            trace_debugger_stacktrace_verbose,
            false,
            "Additional output when tracing debugger stacktraces");
DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind");
DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages");

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(
    Debugger* debugger,
    const GrowableHandlePtrArray<const Script>& scripts,
    TokenPosition token_pos,
    TokenPosition end_token_pos,
    intptr_t requested_line_number,
    intptr_t requested_column_number)
    : debugger_(debugger),
      scripts_(MallocGrowableArray<ScriptPtr>(scripts.length())),
      url_(scripts.At(0).url()),
      line_number_lock_(new SafepointRwLock()),
      line_number_(-1),  // lazily computed
      token_pos_(token_pos),
      end_token_pos_(end_token_pos),
      next_(nullptr),
      conditions_(nullptr),
      requested_line_number_(requested_line_number),
      requested_column_number_(requested_column_number),
      code_token_pos_(TokenPosition::kNoSource) {
  ASSERT(scripts.length() > 0);
  ASSERT(token_pos.IsReal());
  for (intptr_t i = 0; i < scripts.length(); ++i) {
    scripts_.Add(scripts.At(i).ptr());
  }
}

// Create a latent breakpoint at given url and line number.
BreakpointLocation::BreakpointLocation(Debugger* debugger,
                                       const String& url,
                                       intptr_t requested_line_number,
                                       intptr_t requested_column_number)
    : debugger_(debugger),
      scripts_(MallocGrowableArray<ScriptPtr>(0)),
      url_(url.ptr()),
      line_number_lock_(new SafepointRwLock()),
      line_number_(-1),  // lazily computed
      token_pos_(TokenPosition::kNoSource),
      end_token_pos_(TokenPosition::kNoSource),
      next_(nullptr),
      conditions_(nullptr),
      requested_line_number_(requested_line_number),
      requested_column_number_(requested_column_number),
      code_token_pos_(TokenPosition::kNoSource) {
  ASSERT(requested_line_number_ >= 0);
}

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

bool BreakpointLocation::AnyEnabled() const {
  Breakpoint* bpt = breakpoints();
  while (bpt != nullptr) {
    if (bpt->is_enabled()) {
      return true;
    }
    bpt = bpt->next();
  }
  return false;
}

void BreakpointLocation::SetResolved(const Function& func,
                                     TokenPosition token_pos) {
#if defined(DEBUG)
  const Script& func_script = Script::Handle(func.script());
  const String& func_url = String::Handle(func_script.url());
  const String& script_url = String::Handle(url_);
  ASSERT(script_url.Equals(func_url));
#endif  // defined(DEBUG)
  ASSERT(!IsLatent());
  ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
  ASSERT(func.is_debuggable());
  token_pos_.store(token_pos);
  end_token_pos_.store(token_pos);
  code_token_pos_ = token_pos;
}

void BreakpointLocation::GetCodeLocation(Script* script,
                                         TokenPosition* pos) const {
  if (IsLatent()) {
    *script = Script::null();
    *pos = TokenPosition::kNoSource;
  } else {
    *script = this->script();
    *pos = token_pos_;
  }
}

intptr_t BreakpointLocation::line_number() {
  // Compute line number lazily since it causes scanning of the script.
  {
    SafepointReadRwLocker sl(Thread::Current(), line_number_lock());
    if (line_number_ >= 0) {
      return line_number_;
    }
  }
  SafepointWriteRwLocker sl(Thread::Current(), line_number_lock());
  if (line_number_ < 0) {
    Script::Handle(script()).GetTokenLocation(token_pos(), &line_number_);
  }
  return line_number_;
}

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

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

void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  for (intptr_t i = 0; i < scripts_.length(); ++i) {
    visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&scripts_.data()[i]));
  }
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&url_));

  Breakpoint* bpt = conditions_;
  while (bpt != nullptr) {
    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("enabled", enabled_);
  jsobj.AddProperty("breakpointNumber", id());
  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<ObjectPtr*>(&code_));
  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_value_));
}

const char* CodeBreakpoint::ToCString() const {
  if (breakpoint_locations_.length() == 0) {
    return "unlinked breakpoint";
  }

  char buffer[1024];
  BufferFormatter f(buffer, sizeof(buffer));
  // Pick the first, all other should have same script/line number.
  BreakpointLocation* breakpoint_location = breakpoint_locations_.At(0);
  String& source_url = String::Handle(breakpoint_location->url());
  intptr_t line_number = breakpoint_location->line_number();

  f.Printf("breakpoint at %s:%" Pd, source_url.ToCString(), line_number);
  return Thread::Current()->zone()->MakeCopyOfString(buffer);
}

ActivationFrame::ActivationFrame(uword pc,
                                 uword fp,
                                 uword sp,
                                 const Function& function,
                                 const Object& code_or_bytecode,
                                 const Array& deopt_frame,
                                 intptr_t deopt_frame_offset)
    : pc_(pc),
      fp_(fp),
      sp_(sp),
      code_or_bytecode_(Object::ZoneHandle(code_or_bytecode.ptr())),
      function_(Function::ZoneHandle(function.ptr())),
      closure_(Closure::null_closure()),
      deopt_frame_(Array::ZoneHandle(deopt_frame.ptr())),
      deopt_frame_offset_(deopt_frame_offset),
      kind_(kRegular),
      desc_indices_(8),
      pc_desc_(PcDescriptors::ZoneHandle()) {
  ASSERT(!function.IsNull());
  ASSERT(code_or_bytecode.IsCode() || code_or_bytecode.IsBytecode());
}

ActivationFrame::ActivationFrame(uword pc,
                                 const Function& function,
                                 const Object& code_or_bytecode,
                                 const Closure& closure)
    : pc_(pc),
      code_or_bytecode_(Object::ZoneHandle(code_or_bytecode.ptr())),
      function_(Function::ZoneHandle(function.ptr())),
      closure_(Closure::ZoneHandle(closure.ptr())),
      deopt_frame_(Array::empty_array()),
      deopt_frame_offset_(0),
      kind_(kAsyncAwaiter) {
  ASSERT(code_or_bytecode.IsCode() || code_or_bytecode.IsBytecode());
}

ActivationFrame::ActivationFrame(Kind kind)
    : code_or_bytecode_(Object::null_object()),
      function_(Function::null_function()),
      closure_(Closure::null_closure()),
      deopt_frame_(Array::empty_array()),
      deopt_frame_offset_(0),
      kind_(kind) {
  ASSERT(kind == kAsyncSuspensionMarker);
}

bool Debugger::NeedsIsolateEvents() {
  ASSERT(isolate_ == Isolate::Current());
  return !Isolate::IsSystemIsolate(isolate_) &&
         Service::isolate_stream.enabled();
}

bool Debugger::NeedsDebugEvents() {
  if (Isolate::Current() == nullptr) {
    // E.g., NoActiveIsolateScope.
    return false;
  }
  RELEASE_ASSERT(isolate_ == Isolate::Current());
  ASSERT(!Isolate::IsSystemIsolate(isolate_));
  return FLAG_warn_on_pause_with_no_debugger || Service::debug_stream.enabled();
}

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

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

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

ErrorPtr 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 = DebuggerStackTrace::Collect();
  if (trace->Length() > 0) {
    event.set_top_frame(trace->FrameAt(0));
  }
  CacheStackTraces(trace, DebuggerStackTrace::CollectAsyncAwaiters());
  set_resume_action(kContinue);
  Pause(&event);
  HandleSteppingRequest();
  ClearCachedStackTraces();

  // If any error occurred while in the debug message loop, return it here.
  NoSafepointScope no_safepoint;
  ErrorPtr 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);
  bpt->Enable();
  dbg->group_debugger()->SyncBreakpointLocation(this);
  dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
}

Breakpoint* BreakpointLocation::AddRepeated(Debugger* dbg) {
  return AddBreakpoint(dbg, Closure::Handle(), /*single_shot=*/false);
}

Breakpoint* BreakpointLocation::AddSingleShot(Debugger* dbg) {
  return AddBreakpoint(dbg, Closure::Handle(), /*single_shot=*/true);
}

Breakpoint* BreakpointLocation::AddBreakpoint(Debugger* dbg,
                                              const Closure& closure,
                                              bool single_shot) {
  Breakpoint* bpt = breakpoints();
  while (bpt != nullptr) {
    if ((bpt->closure() == closure.ptr()) &&
        (bpt->is_single_shot() == single_shot)) {
      break;
    }
    bpt = bpt->next();
  }
  if (bpt == nullptr) {
    bpt = new Breakpoint(dbg->nextId(), this, single_shot, closure);
    AddBreakpoint(bpt, dbg);
  }
  return bpt;
}

static const char* 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 String& script_url,
                             TokenPosition token_pos,
                             TokenPosition end_token_pos) {
  const TokenPosition& func_start = func.token_pos();
  if (token_pos.IsWithin(func_start, func.end_token_pos()) ||
      func_start.IsWithin(token_pos, end_token_pos)) {
    // Check script equality last because it allocates handles as a side effect.
    Script& func_script = Script::Handle(func.script());
    String& url = String::Handle(func_script.url());
    return script_url.Equals(url);
  }
  return false;
}

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

bool GroupDebugger::HasCodeBreakpointInFunctionUnsafe(const Function& func) {
  DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadReader() ||
               Thread::Current()->IsInStoppedMutatorsScope());
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != nullptr) {
    if (func.ptr() == cbpt->function()) {
      return true;
    }
    cbpt = cbpt->next_;
  }
  return false;
}

bool GroupDebugger::HasCodeBreakpointInFunction(const Function& func) {
  auto thread = Thread::Current();
  // Don't need to worry about the lock if mutators are stopped.
  if (thread->IsInStoppedMutatorsScope()) {
    return HasCodeBreakpointInFunctionUnsafe(func);
  } else {
    SafepointReadRwLocker sl(thread, code_breakpoints_lock());
    return HasCodeBreakpointInFunctionUnsafe(func);
  }
}

bool GroupDebugger::HasBreakpointInCode(const Code& code) {
  auto thread = Thread::Current();
  SafepointReadRwLocker sl(thread, code_breakpoints_lock());
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != nullptr) {
    if (code.ptr() == 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 != nullptr) {
    Breakpoint* bpt = sbpt->breakpoints();
    while (bpt != nullptr) {
      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();
  }
}

ActivationFrame::Relation ActivationFrame::CompareTo(bool is_interpreted,
                                                     uword fp,
                                                     uword other_fp) {
  if (fp == other_fp) {
    return kSelf;
  }
#if defined(DART_DYNAMIC_MODULES)
  if (is_interpreted) {
    // Unlike compiled code, interpreted stacks grow towards higher addresses.
    return fp > other_fp ? kCallee : kCaller;
  }
#endif
  return IsCalleeFrameOf(other_fp, fp) ? kCallee : kCaller;
}

StringPtr ActivationFrame::QualifiedFunctionName() {
  return String::New(::dart::QualifiedFunctionName(function()));
}

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

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

LibraryPtr ActivationFrame::Library() {
  const Class& cls = Class::Handle(function().Owner());
  return cls.library();
}

void ActivationFrame::GetPcDescriptors() {
  ASSERT(!IsInterpreted());
  if (pc_desc_.IsNull()) {
    pc_desc_ = code().pc_descriptors();
    ASSERT(!pc_desc_.IsNull());
  }
}

// If not token_pos_initialized_, compute token_pos_, try_index_ and,
// if not IsInterpreted(), also compute deopt_id_.
TokenPosition ActivationFrame::TokenPos() {
  if (!token_pos_initialized_) {
    token_pos_ = TokenPosition::kNoSource;
    if (IsInterpreted()) {
      token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
      try_index_ = bytecode().GetTryIndexAtPc(pc_);
    } else {
      GetPcDescriptors();
      PcDescriptors::Iterator iter(pc_desc_, UntaggedPcDescriptors::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;
        }
      }
    }
    token_pos_initialized_ = true;
  }
  return token_pos_;
}

intptr_t ActivationFrame::TryIndex() {
  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.
  const TokenPosition& token_pos = TokenPos().ToRealIfSynthetic();
  if ((line_number_ < 0) && token_pos.IsReal()) {
    const Script& script = Script::Handle(SourceScript());
    script.GetTokenLocation(token_pos, &line_number_, &column_number_);
  }
  return line_number_;
}

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

void ActivationFrame::GetVarDescriptors() {
  if (var_descriptors_.IsNull()) {
    if (IsInterpreted()) {
#if defined(DART_PRECOMPILED_RUNTIME)
      UNREACHABLE();
#else
      var_descriptors_ = bytecode().GetLocalVarDescriptors();
      ASSERT(!var_descriptors_.IsNull());
#endif
      return;
    }
    Code& unoptimized_code = Code::Handle(function().unoptimized_code());
    if (unoptimized_code.IsNull()) {
      if (function().ForceOptimize()) {
        var_descriptors_ = Object::empty_var_descriptors().ptr();
        return;
      }
      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 {
  ASSERT(!function().IsNull());
  return Debugger::IsDebuggable(function());
}

void ActivationFrame::PrintContextLevelError(const char* message) {
  OS::PrintErr("Cannot locate context level: %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_);
  OS::PrintErr("token_pos_ %s\n", token_pos_.ToCString());
  if (IsInterpreted() && bytecode().HasLocalVariablesInfo()) {
#if defined(DART_DYNAMIC_MODULES)
    Zone* const zone = Thread::Current()->zone();
    ZoneTextBuffer buffer(zone);
    KernelBytecodeDisassembler::PrintLocalVariablesInfo(
        zone, &buffer, bytecode(), PayloadStart());
    OS::PrintErr("%s\n", buffer.buffer());
#endif
  } else {
    DisassembleToStdout formatter;
    code().Disassemble(&formatter);
    PcDescriptors::Handle(code().pc_descriptors()).Print();
  }
  StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
                            Thread::Current(),
                            StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame = frames.NextFrame();
  while (frame != nullptr) {
    OS::PrintErr("%s\n", frame->ToCString());
    frame = frames.NextFrame();
  }
  OS::Abort();
}

// Calculate the context level at the current pc of the frame.
intptr_t ActivationFrame::ContextLevel() {
  ASSERT(kind_ == kRegular);
  const Context& ctx = GetSavedCurrentContext();
  if (context_level_ < 0 && !ctx.IsNull()) {
    ASSERT(IsInterpreted() || !code().is_optimized());
    bool found = false;
    if (IsInterpreted()) {
#if defined(DART_DYNAMIC_MODULES) && !defined(PRODUCT) &&                      \
    !defined(DART_PRECOMPILED_RUNTIME)
      const intptr_t pc_offset = pc() - PayloadStart();
      DEBUG_ONLY(intptr_t closest_start = 0);
      bytecode::BytecodeLocalVariablesIterator local_vars(
          Thread::Current()->zone(), bytecode());
      while (local_vars.MoveNext()) {
        if (local_vars.IsScope()) {
          if (local_vars.StartPC() <= pc_offset &&
              pc_offset <= local_vars.EndPC()) {
            DEBUG_ASSERT(!found || local_vars.StartPC() > closest_start);
            found = true;
            context_level_ = local_vars.ContextLevel();
            DEBUG_ONLY(closest_start = local_vars.StartPC());
          } else if (local_vars.StartPC() > pc_offset) {
            // The scopes in the local variables info are ordered by starting
            // PC offset, so no need to search further.
            break;
          }
        }
      }
      if (!found) {
        PrintContextLevelError(
            "No Scope local variable info for the current PC");
      }
#else
      UNREACHABLE();
#endif
    } else {
      GetVarDescriptors();
      intptr_t var_desc_len = var_descriptors_.Length();
      // We store the deopt ids as real token positions.
      intptr_t deopt_id = DeoptId();
      if (deopt_id == DeoptId::kNone) {
        PrintContextLevelError("Missing deopt id");
      }
      const TokenPosition to_compare = TokenPosition::Deserialize(deopt_id);
      for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
        UntaggedLocalVarDescriptors::VarInfo var_info;
        var_descriptors_.GetInfo(cur_idx, &var_info);
        const int8_t kind = var_info.kind();
        if ((kind == UntaggedLocalVarDescriptors::kContextLevel) &&
            to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
          context_level_ = var_info.index();
          found = true;
          break;
        }
      }
      if (!found) {
        PrintContextLevelError(
            "No ContextLevel var descriptor that contains the deopt id");
      }
    }
    ASSERT(context_level_ >= 0);
  }
  return context_level_;
}

bool ActivationFrame::HandlesException(const Instance& exc_obj) {
  if (kind_ == kAsyncSuspensionMarker) {
    return false;
  }
  intptr_t try_index = TryIndex();
  auto& handlers = ExceptionHandlers::Handle();
  if (IsInterpreted()) {
    handlers = bytecode().exception_handlers();
  } else {
    handlers = code().exception_handlers();
  }
  ASSERT(!handlers.IsNull());
  if ((try_index < 0) && !handlers.has_async_handler()) {
    return false;
  }
  Array& handled_types = Array::Handle();
  AbstractType& type = Type::Handle();
  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 and ignore synthesized try/catch in
    // async methods as well as synthetic try/catch hiding inside try/finally.
    if (!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;
}

// Get the saved current context of this activation.
const Context& ActivationFrame::GetSavedCurrentContext(intptr_t* index) {
  // If the index of the variable was requested, do the retrieval again.
  if (context_initialized_ && index == nullptr) return ctx_;
  context_initialized_ = true;
  GetVarDescriptors();
  intptr_t var_desc_len = var_descriptors_.Length();
  Object& obj = Object::Handle();
  for (intptr_t i = 0; i < var_desc_len; i++) {
    UntaggedLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(i, &var_info);
    const int8_t kind = var_info.kind();
    if (kind == UntaggedLocalVarDescriptors::kSavedCurrentContext) {
      if (index != nullptr) {
        *index = var_info.index();
      }
      const auto variable_index = VariableIndex(var_info.index());
      obj = GetStackVar(variable_index);
      if (function_.IsImplicitInstanceClosureFunction()) {
        // The context of an implicit instance closure contains only one slot
        // for "this", so the instance is stored as the context and accessed
        // directly by generated code to avoid allocating a separate context.
        // Here, we create the elided context object for debugging purposes.
        ctx_ = Context::New(1);
        ctx_.SetAt(0, obj);
      } else if (obj.IsClosure()) {
        ASSERT(function().IsClosureCallDispatcher());
        // Closure.call frames.
        ctx_ = Closure::Cast(obj).GetContext();
      } else if (obj.IsContext()) {
        ctx_ = Context::Cast(obj).ptr();
      } else {
        ASSERT(obj.IsNull() || obj.ptr() == Object::optimized_out().ptr());
        ctx_ = Context::null();
      }
      return ctx_;
    }
  }
  return ctx_;
}

ActivationFrame* DebuggerStackTrace::GetHandlerFrame(
    const Instance& exc_obj) const {
  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("GetHandlerFrame(%s)\n", exc_obj.ToCString());
  }

  for (intptr_t frame_index = 0; frame_index < Length(); frame_index++) {
    ActivationFrame* frame = FrameAt(frame_index);
    const bool can_handle = frame->HandlesException(exc_obj);
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr("    #%04" Pd " (%s) %s", frame_index,
                   can_handle ? "+" : "-", frame->ToCString());
    }
    if (can_handle) {
      return frame;
    }
  }
  return nullptr;
}

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

  TokenPosition activation_token_pos = TokenPos();
  if (!activation_token_pos.IsDebugPause() || kind_ != kRegular) {
    // 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());
    UntaggedLocalVarDescriptors::VarInfo var_info;
    var_descriptors_.GetInfo(cur_idx, &var_info);
    const int8_t kind = var_info.kind();
    if ((kind != UntaggedLocalVarDescriptors::kStackVar) &&
        (kind != UntaggedLocalVarDescriptors::kContextVar)) {
      continue;
    }
    if (!activation_token_pos.IsWithin(var_info.begin_pos, var_info.end_pos)) {
      continue;
    }
    if ((kind == UntaggedLocalVarDescriptors::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;
        UntaggedLocalVarDescriptors::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 ObjectPtr GetVariableValue(uword addr) {
  return *reinterpret_cast<ObjectPtr*>(addr);
}

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

  // fp will be a nullptr if the frame isn't active on the stack.
  if (fp() == 0) {
    return Object::null();
  }

  if (function().MakesCopyOfParameters()) {
    // Function parameters are copied to a fixed place in the callee's frame.
    if (function().IsSuspendableFunction()) {
      ++index;  // Skip slot reserved for :suspend_state variable.
    }
    if (IsInterpreted()) {
      return GetStackVar(VariableIndex(-index));
    }
    return GetVariableValue(LocalVarAddress(
        fp(), runtime_frame_layout.FrameSlotForVariableIndex(-index)));
  } else {
    intptr_t reverse_index = num_parameters - index;
    if (IsInterpreted()) {
      return GetStackVar(VariableIndex(reverse_index));
    }
    return GetVariableValue(ParamAddress(fp(), reverse_index));
  }
}

ClosurePtr ActivationFrame::GetClosure() {
  ASSERT(function().IsClosureFunction());
  Object& param = Object::Handle(GetParameter(0));
  ASSERT(param.IsInstance());
  ASSERT(Instance::Cast(param).IsClosure());
  return Closure::Cast(param).ptr();
}

ObjectPtr ActivationFrame::GetSuspendStateVar() {
  ASSERT(function().IsSuspendableFunction());
  return GetStackVar(VariableIndex(SuspendState::kSuspendStateVarIndex));
}

ObjectPtr ActivationFrame::GetSuspendableFunctionData() {
  Object& suspend_state = Object::Handle(GetSuspendStateVar());
  if (suspend_state.IsSuspendState()) {
    return SuspendState::Cast(suspend_state).function_data();
  }
  return suspend_state.ptr();
}

ObjectPtr 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.ptr() == Object::optimized_out().ptr()) {
      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 != nullptr)) {
    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 != nullptr);

  *name = var_descriptors_.GetName(desc_index);

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

ObjectPtr 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);
}

ObjectPtr ActivationFrame::GetRelativeContextVar(intptr_t var_ctx_level,
                                                 intptr_t ctx_slot,
                                                 intptr_t frame_ctx_level) {
  const Context& ctx = GetSavedCurrentContext();

  // It's possible that ctx was optimized out as no locals were captured by the
  // context. See issue #38182.
  if (ctx.IsNull()) {
    return Object::optimized_out().ptr();
  }

  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 if (level_diff > 0) {
    Context& var_ctx = Context::Handle(ctx.ptr());
    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);
  } else {
    PrintContextMismatchError(ctx_slot, frame_ctx_level, var_ctx_level);
    return Object::null();
  }
}

ObjectPtr 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 = TokenPosition::kNoSource;
    VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
    if (var_name.Equals(Symbols::This())) {
      return value.ptr();
    }
  }
  return Object::optimized_out().ptr();
}

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) == '_');
}

ObjectPtr ActivationFrame::EvaluateCompiledExpression(
    const ExternalTypedData& kernel_buffer,
    const Array& type_definitions,
    const Array& arguments,
    const TypeArguments& type_arguments) {
  auto thread = Thread::Current();
  auto zone = thread->zone();

  // The expression evaluation function will get all it's captured state passed
  // as parameters (with `this` being the exception). As a result, we treat the
  // expression evaluation function as either a top-level, static or instance
  // method.
  const auto& outermost =
      Function::Handle(zone, function().GetOutermostFunction());
  const auto& klass = Class::Handle(zone, outermost.Owner());
  const auto& library = Library::Handle(zone, klass.library());

  auto& receiver = Object::Handle(zone);
  if (!klass.IsTopLevel() && !outermost.is_static()) {
    receiver = GetReceiver();
    RELEASE_ASSERT(receiver.IsInstance() ||
                   receiver.ptr() == Object::optimized_out().ptr());
  }
  return Instance::EvaluateCompiledExpression(thread, receiver, library, klass,
                                              kernel_buffer, type_definitions,
                                              arguments, type_arguments);
}

TypeArgumentsPtr ActivationFrame::BuildParameters(
    const GrowableObjectArray& param_names,
    const GrowableObjectArray& param_values,
    const GrowableObjectArray& type_params_names,
    const GrowableObjectArray& type_params_bounds,
    const GrowableObjectArray& type_params_defaults) {
  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 = TokenPosition::kNoSource;
    VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
    if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
      type_arguments_available = true;
      type_arguments ^= value.ptr();
    } else if (
        !name.Equals(Symbols::This()) && !IsSyntheticVariableName(name) &&
        value.ptr() != Object::optimized_out().ptr() &&
        // TODO(57048): We currently pretend that uninitialized late variables
        // don't exist to avoid crashing when evaluating expressions that need
        // to access the late variables' values. The CFE team is working on a
        // better solution.
        value.ptr() != Object::sentinel().ptr()) {
      if (IsPrivateVariableName(name)) {
        name = Symbols::New(Thread::Current(), 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().NumTypeArguments();
    type_params_names.Grow(num_vars);
    type_params_names.SetLength(num_vars);
    type_params_bounds.Grow(num_vars);
    type_params_bounds.SetLength(num_vars);
    type_params_defaults.Grow(num_vars);
    type_params_defaults.SetLength(num_vars);
    AbstractType& bound = AbstractType::Handle();
    AbstractType& defaultType = AbstractType::Handle();
    TypeParameters& type_params = TypeParameters::Handle();
    Function& current = Function::Handle(function().ptr());
    intptr_t mapping_offset = num_vars;
    for (; !current.IsNull(); current = current.parent_function()) {
      type_params = current.type_parameters();
      if (type_params.IsNull()) continue;
      intptr_t size = current.NumTypeParameters();
      ASSERT(size > 0 && type_params.Length() == size);
      ASSERT(mapping_offset >= size);
      mapping_offset -= size;
      for (intptr_t j = 0; j < size; ++j) {
        name = type_params.NameAt(j);
        bound = type_params.BoundAt(j);
        defaultType = type_params.DefaultAt(j);
        // 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);
        type_params_bounds.SetAt(mapping_offset + j, bound);
        type_params_defaults.SetAt(mapping_offset + j, defaultType);
      }
    }
    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.ptr();
}

const char* ActivationFrame::ToCString() {
  if (function().IsNull()) {
    return Thread::Current()->zone()->PrintToString("[ Frame kind: %s]\n",
                                                    KindToCString(kind_));
  }
  const String& url = String::Handle(SourceUrl());
  intptr_t line = LineNumber();
  const char* func_name = function().ToFullyQualifiedCString();
  if (kind_ == kRegular) {
    return Thread::Current()->zone()->PrintToString(
        "[ Frame pc(0x%" Px ") fp(0x%" Px ") sp(0x%" Px
        ")\n"
        "\t%s offset = 0x%" Px
        "\n"
        "\tfunction = %s\n"
        "\turl = %s\n"
        "\tline = %" Pd
        "\n"
        "\tcontext = %s\n"
        "\tcontext level = %" Pd " ]\n",
        pc(), fp(), sp(), IsInterpreted() ? "bytecode" : "code",
        pc() - PayloadStart(), func_name, url.ToCString(), line,
        ctx_.ToCString(), ContextLevel());
  } else {
    return Thread::Current()->zone()->PrintToString(
        "[ Frame code function = %s\n"
        "\turl = %s\n"
        "\tline = %" Pd
        "\n"
        "\tcontext = %s]\n",
        func_name, url.ToCString(), line, ctx_.ToCString());
  }
}

void ActivationFrame::PrintToJSONObject(JSONObject* jsobj) {
  if (kind_ == kRegular) {
    PrintToJSONObjectRegular(jsobj);
  } else if (kind_ == kAsyncAwaiter) {
    PrintToJSONObjectAsyncAwaiter(jsobj);
  } else if (kind_ == kAsyncSuspensionMarker) {
    PrintToJSONObjectAsyncSuspensionMarker(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();
  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::kNoSource;
      TokenPosition visible_start_token_pos = TokenPosition::kNoSource;
      TokenPosition visible_end_token_pos = TokenPosition::kNoSource;
      VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
                 &visible_end_token_pos, &var_value);
      if (!IsSyntheticVariableName(var_name)) {
        JSONObject jsvar(&jsvars);
        jsvar.AddProperty("type", "BoundVariable");
        const char* scrubbed_var_name = String::ScrubName(var_name);
        jsvar.AddProperty("name", scrubbed_var_name);
        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::PrintToJSONObjectAsyncAwaiter(JSONObject* jsobj) {
  jsobj->AddProperty("type", "Frame");
  jsobj->AddProperty("kind", KindToCString(kind_));
  const Script& script = Script::Handle(SourceScript());
  const TokenPosition& pos = TokenPos();
  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");
}

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::AddAsyncSuspension() {
  // We might start asynchronous unwinding in one of the internal
  // dart:async functions which would make synchronous part of the
  // stack empty. This would not happen normally but might happen
  // with stress flags.
  if (trace_.is_empty() ||
      trace_.Last()->kind() != ActivationFrame::kAsyncSuspensionMarker) {
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr("  async suspension\n");
    }
    trace_.Add(new ActivationFrame(ActivationFrame::kAsyncSuspensionMarker));
  } else if (FLAG_trace_debugger_stacktrace &&
             FLAG_trace_debugger_stacktrace_verbose) {
    OS::PrintErr("  skipping repeated async suspension\n");
  }
}

void DebuggerStackTrace::AddAsyncAwaiterFrame(uword pc,
                                              const Function& function,
                                              const Object& code_or_bytecode,
                                              const Closure& closure) {
  trace_.Add(new ActivationFrame(pc, function, code_or_bytecode, closure));
}

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

CodeBreakpoint::CodeBreakpoint(const Code& code,
                               BreakpointLocation* breakpoint_location,
                               uword pc,
                               UntaggedPcDescriptors::Kind kind)
    : code_(code.ptr()),
      bytecode_(Bytecode::null()),
      pc_(pc),
      enabled_count_(0),
      next_(nullptr),
      breakpoint_kind_(kind),
      saved_value_(Code::null()),
      saved_opcode_(kMaxUint32) {
  ASSERT(!code.IsNull());
  ASSERT(pc_ != 0);
  ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
  AddBreakpointLocation(breakpoint_location);
  ASSERT(breakpoint_location->token_pos().IsReal());
}

CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
                               BreakpointLocation* breakpoint_location,
                               uword pc)
    : code_(Code::null()),
      bytecode_(bytecode.ptr()),
      pc_(pc),
      enabled_count_(0),
      next_(nullptr),
      breakpoint_kind_(UntaggedPcDescriptors::kRuntimeCall),
      saved_value_(Code::null()),
      saved_opcode_(kMaxUint32) {
  ASSERT(!bytecode.IsNull());
  ASSERT(pc_ != 0);
  AddBreakpointLocation(breakpoint_location);
  ASSERT(breakpoint_location->token_pos().IsReal());
}

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;
  next_ = nullptr;
  breakpoint_kind_ = UntaggedPcDescriptors::kOther;
#endif
}

void CodeBreakpoint::Enable() {
  if (enabled_count_ == 0) {
    if (bytecode_ != Bytecode::null()) {
#if defined(DART_DYNAMIC_MODULES)
      ASSERT_EQUAL(saved_opcode_, kMaxUint32);
      saved_opcode_ =
          BytecodePatcher::AddBreakpointAt(pc_, Bytecode::Handle(bytecode_));
#else
      UNREACHABLE();
#endif
    } else {
      PatchCode();
    }
  }
  ++enabled_count_;
}

void CodeBreakpoint::Disable() {
  if (enabled_count_ == 1) {
    if (bytecode_ != Bytecode::null()) {
#if defined(DART_DYNAMIC_MODULES)
      BytecodePatcher::RemoveBreakpointAt(pc_, Bytecode::Handle(bytecode_),
                                          saved_opcode_);
      saved_opcode_ = kMaxUint32;
#else
      UNREACHABLE();
#endif
    } else {
      RestoreCode();
    }
  }
  --enabled_count_;
}

bool CodeBreakpoint::HasBreakpointLocation(
    BreakpointLocation* breakpoint_location) {
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    if (breakpoint_locations_[i] == breakpoint_location) {
      return true;
    }
  }
  return false;
}

bool CodeBreakpoint::FindAndDeleteBreakpointLocation(
    BreakpointLocation* breakpoint_location) {
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    if (breakpoint_locations_[i] == breakpoint_location) {
      breakpoint_locations_.EraseAt(i);
      return true;
    }
  }
  return false;
}

BreakpointLocation* CodeBreakpoint::FindBreakpointForDebugger(
    Debugger* debugger) {
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    if (breakpoint_locations_[i]->debugger() == debugger) {
      return breakpoint_locations_[i];
    }
  }
  return nullptr;
}

GroupDebugger::GroupDebugger(IsolateGroup* isolate_group)
    : isolate_group_(isolate_group),
      code_breakpoints_lock_(new SafepointRwLock()),
      code_breakpoints_(nullptr),
      breakpoint_locations_lock_(new SafepointRwLock()),
      single_stepping_set_lock_(new RwLock()),
      needs_breakpoint_cleanup_(false) {}

GroupDebugger::~GroupDebugger() {
  while (code_breakpoints_ != nullptr) {
    CodeBreakpoint* cbpt = code_breakpoints_;
    code_breakpoints_ = code_breakpoints_->next();
    ASSERT(!cbpt->IsEnabled());
    delete cbpt;
  }
}

Debugger::Debugger(Isolate* isolate)
    : isolate_(isolate),
      next_id_(1),
      latent_locations_(nullptr),
      breakpoint_locations_(nullptr),
      resume_action_(kContinue),
      resume_frame_index_(-1),
      post_deopt_frame_index_(-1),
      ignore_breakpoints_(false),
      pause_event_(nullptr),
      stack_trace_(nullptr),
      async_awaiter_stack_trace_(nullptr),
      stepping_fp_(0),
      last_stepping_fp_(0),
      last_stepping_pos_(TokenPosition::kNoSource),
      exc_pause_info_(kNoPauseOnExceptions) {}

Debugger::~Debugger() {
  ASSERT(!IsPaused());
  ASSERT(latent_locations_ == nullptr);
  ASSERT(breakpoint_locations_ == nullptr);
  ASSERT(stack_trace_ == nullptr);
  ASSERT(async_awaiter_stack_trace_ == nullptr);
}

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::IsSystemIsolate(isolate_)) {
    return;
  }
  {
    SafepointWriteRwLocker sl(Thread::Current(),
                              group_debugger()->breakpoint_locations_lock());
    while (breakpoint_locations_ != nullptr) {
      BreakpointLocation* loc = breakpoint_locations_;
      group_debugger()->UnlinkCodeBreakpoints(loc);
      group_debugger()->UnregisterBreakpointLocation(loc);
      breakpoint_locations_ = breakpoint_locations_->next();
      delete loc;
    }
    while (latent_locations_ != nullptr) {
      BreakpointLocation* loc = latent_locations_;
      group_debugger()->UnlinkCodeBreakpoints(loc);
      group_debugger()->UnregisterBreakpointLocation(loc);
      latent_locations_ = latent_locations_->next();
      delete loc;
    }
  }
  if (NeedsIsolateEvents()) {
    ServiceEvent event(isolate_, ServiceEvent::kIsolateExit);
    InvokeEventHandler(&event);
  }
}

static ActivationFrame* TopDartFrame();
static bool IsAtAsyncJump(ActivationFrame* top_frame);

bool Debugger::SetupStepOverAsyncSuspension(const char** error) {
  ActivationFrame* top_frame = TopDartFrame();
  if (!IsAtAsyncJump(top_frame)) {
    // Not at an async operation.
    if (error != nullptr) {
      *error = "Isolate must be paused at an async suspension point";
    }
    return false;
  }
  ASSERT(top_frame->function().IsAsyncFunction() ||
         top_frame->function().IsAsyncGenerator());
  const auto& function_data =
      Object::Handle(top_frame->GetSuspendableFunctionData());
  SetBreakpointAtResumption(function_data);
  return true;
}

static bool CanRewindFrame(intptr_t frame_index, const char** error);

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

// 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
  if (FLAG_trace_deoptimization) {
    THR_Print("Deopt for debugger\n");
  }
  isolate_->group()->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_->group()->class_table();
  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  auto zone = thread->zone();
  CallSiteResetter resetter(zone);
  Class& cls = Class::Handle(zone);
  Array& functions = Array::Handle(zone);
  Function& function = Function::Handle(zone);
  Code& code = Code::Handle(zone);

  const intptr_t num_classes = class_table.NumCids();
  const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
  SafepointWriteRwLocker ml(thread, isolate_group->program_lock());
  for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
    const intptr_t cid =
        i < num_classes ? i : ClassTable::CidFromTopLevelIndex(i - num_classes);
    if (class_table.HasValidClassAt(cid)) {
      cls = class_table.At(cid);

      // 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());
          // Force-optimized functions don't have unoptimized code and can't
          // deoptimize. Their optimized codes are still valid.
          if (!function.ForceOptimize()) {
            if (function.HasOptimizedCode()) {
              function.SwitchToUnoptimizedCode();
            }
            code = function.unoptimized_code();
            if (!code.IsNull()) {
              resetter.ResetSwitchableCalls(code);
            }
          }
          // Also disable any optimized implicit closure functions.
          if (function.HasImplicitClosureFunction()) {
            function = function.ImplicitClosureFunction();
            if (!function.ForceOptimize()) {
              if (function.HasOptimizedCode()) {
                function.SwitchToUnoptimizedCode();
              }
              code = function.unoptimized_code();
              if (!code.IsNull()) {
                resetter.ResetSwitchableCalls(code);
              }
            }
          }
        }
      }
    }
  }

  // Disable optimized closure functions.
  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& function) {
    if (!function.ForceOptimize()) {
      if (function.HasOptimizedCode()) {
        function.SwitchToUnoptimizedCode();
      }
      code = function.unoptimized_code();
      if (!code.IsNull()) {
        resetter.ResetSwitchableCalls(code);
      }
    }
    return true;  // Continue iteration.
  });
#endif  // defined(DART_PRECOMPILED_RUNTIME)
}

void Debugger::RunWithStoppedDeoptimizedWorld(std::function<void()> fun) {
#if !defined(DART_PRECOMPILED_RUNTIME)
  // RELOAD_OPERATION_SCOPE is used here because is is guaranteed that
  // isolates at reload safepoints hold no safepoint locks.
  RELOAD_OPERATION_SCOPE(Thread::Current());
  group_debugger()->isolate_group()->RunWithStoppedMutators([&]() {
    DeoptimizeWorld();
    fun();
  });
#endif
}

void Debugger::NotifySingleStepping(bool value) {
  RELEASE_ASSERT(isolate_->mutator_thread() != nullptr);
  if (value) {
    // Setting breakpoint requires unoptimized code, make sure we stop all
    // isolates to prevent racing reoptimization.
    RunWithStoppedDeoptimizedWorld([&] {
      isolate_->mutator_thread()->set_single_step(value);
      // Ensure other isolates in the isolate group keep
      // unoptimized code unoptimized, won't attempt to optimize it.
      group_debugger()->RegisterSingleSteppingDebugger(Thread::Current(), this);
    });
  } else {
    isolate_->mutator_thread()->set_single_step(value);
    group_debugger()->UnregisterSingleSteppingDebugger(Thread::Current(), this);
  }
}

static ActivationFrame* CollectDartFrame(uword pc,
                                         StackFrame* frame,
                                         const Function& function,
                                         const Object& code_or_bytecode,
                                         const Array& deopt_frame,
                                         intptr_t deopt_frame_offset) {
  ASSERT((code_or_bytecode.IsCode() &&
          Code::Cast(code_or_bytecode).ContainsInstructionAt(pc)) ||
         (code_or_bytecode.IsBytecode() &&
          Bytecode::Cast(code_or_bytecode).ContainsInstructionAt(pc)));
  ActivationFrame* activation =
      new ActivationFrame(pc, frame->fp(), frame->sp(), function,
                          code_or_bytecode, deopt_frame, deopt_frame_offset);
  if (FLAG_trace_debugger_stacktrace) {
    intptr_t index = -1;
    const Context& ctx = activation->GetSavedCurrentContext(&index);
    if (index >= 0) {
      OS::PrintErr("    Current context (index %" Pu "): %s\n", index,
                   ctx.ToCString());
    } else if (!ctx.IsNull()) {
      OS::PrintErr("    Current context: %s\n", ctx.ToCString());
    }
    OS::PrintErr("    Line number: %" Pd "\n", activation->LineNumber());
  }
  return activation;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static ArrayPtr DeoptimizeToArray(Thread* thread,
                                  StackFrame* frame,
                                  const Code& code) {
  ASSERT(code.is_optimized() && !code.is_force_optimized());
  // Create the DeoptContext for this deoptimization.
  DeoptContext* deopt_context =
      new DeoptContext(frame, code, DeoptContext::kDestIsAllocated, nullptr,
                       nullptr, true, false /* deoptimizing_code */);
  thread->set_deopt_context(deopt_context);

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

  thread->set_deopt_context(nullptr);
  delete deopt_context;

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

DebuggerStackTrace* DebuggerStackTrace::Collect() {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  auto& function = Function::Handle(zone);
  auto& code = Code::Handle(zone);
  auto& bytecode = Bytecode::Handle(zone);
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);

  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("CollectStackTrace: starting collection\n");
  }
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
                              StackFrameIterator::kNoCrossThreadIteration);
  for (StackFrame* frame = iterator.NextFrame(); frame != nullptr;
       frame = iterator.NextFrame()) {
    ASSERT(frame->IsValid());
    if (frame->IsDartFrame()) {
      if (FLAG_trace_debugger_stacktrace) {
        // StackFrame::ToCString() prepends two spaces in its output.
        OS::PrintErr("%s\n", frame->ToCString());
      }
      if (frame->is_interpreted()) {
        function = frame->LookupDartFunction();
        bytecode = frame->LookupDartBytecode();
        stack_trace->AppendBytecodeFrame(frame, function, bytecode);
      } else {
        code = frame->LookupDartCode();
        stack_trace->AppendCodeFrames(frame, code);
      }
    } else if (FLAG_trace_debugger_stacktrace &&
               FLAG_trace_debugger_stacktrace_verbose) {
      // StackFrame::ToCString() prepends two spaces in its output.
      OS::PrintErr("%s\n", frame->ToCString());
      OS::PrintErr("    non-Dart frame skipped\n");
    }
  }
  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("CollectStackTrace: collection finished\n\n");
  }

  return stack_trace;
}

// Appends at least one stack frame. Multiple frames will be appended
// if |code| at the frame's pc contains inlined functions.
void DebuggerStackTrace::AppendCodeFrames(StackFrame* frame, const Code& code) {
  auto& function = Function::Handle(zone_, code.function());
#if !defined(DART_PRECOMPILED_RUNTIME)
  if (code.is_optimized()) {
    if (code.is_force_optimized()) {
      if (FLAG_trace_debugger_stacktrace) {
        ASSERT(!function.IsNull());
        OS::PrintErr("    skipping force-optimized function: %s\n",
                     function.ToFullyQualifiedCString());
      }
      return;  // Skip frame of force-optimized (and non-debuggable) function.
    }
    // TODO(rmacnak): Use CodeSourceMap
    deopt_frame_ = DeoptimizeToArray(thread_, frame, code);
    for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
         it.Advance()) {
      inlined_code_ = it.code();
      function = it.function();
      if (FLAG_trace_debugger_stacktrace) {
        ASSERT(!function.IsNull());
        OS::PrintErr("    visiting inlined function: %s\n",
                     function.ToFullyQualifiedCString());
      }
      intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
      AddActivation(CollectDartFrame(it.pc(), frame, function, inlined_code_,
                                     deopt_frame_, deopt_frame_offset));
    }
    return;
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  AddActivation(CollectDartFrame(frame->pc(), frame, function, code,
                                 Object::null_array(), 0));
}

// Appends one interpreted stack frame.
void DebuggerStackTrace::AppendBytecodeFrame(StackFrame* frame,
                                             const Function& function,
                                             const Bytecode& bytecode) {
  AddActivation(CollectDartFrame(frame->pc(), frame, function, bytecode,
                                 Object::null_array(), 0));
}

DebuggerStackTrace* DebuggerStackTrace::CollectAsyncAwaiters() {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();

  Function& function = Function::Handle(zone);

  constexpr intptr_t kDefaultStackAllocation = 8;
  auto stack_trace = new DebuggerStackTrace(kDefaultStackAllocation);

  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("CollectStackTrace: starting async awaiters collection\n");
  }
  bool has_async = false;
  bool has_async_catch_error = false;
  StackTraceUtils::CollectFrames(
      thread, /*skip_frames=*/0,
      [&](const StackTraceUtils::Frame& frame) {
        if (frame.code.IsNull() && frame.bytecode.IsNull()) {
          return;
        }

        if (frame.frame != nullptr) {  // Synchronous portion of the stack.
          if (FLAG_trace_debugger_stacktrace) {
            // StackFrame::ToCString() prepends two spaces in its output.
            OS::PrintErr("%s\n", frame.frame->ToCString());
          }
          if (!frame.bytecode.IsNull()) {
            function = frame.frame->LookupDartFunction();
            stack_trace->AppendBytecodeFrame(frame.frame, function,
                                             frame.bytecode);
          } else {
            stack_trace->AppendCodeFrames(frame.frame, frame.code);
          }
        } else {
          has_async = true;

          if (frame.code.ptr() == StubCode::AsynchronousGapMarker().ptr()) {
            stack_trace->AddAsyncSuspension();
            return;
          }

          uword start = 0;
          const Object* obj = nullptr;
          const char* name = nullptr;
          if (!frame.bytecode.IsNull()) {
            function = frame.bytecode.function();
            start = frame.bytecode.PayloadStart();
            obj = &frame.bytecode;
            if (FLAG_trace_debugger_stacktrace) {
              name = frame.bytecode.FullyQualifiedName();
            }
          } else {
            function = frame.code.function();
            start = frame.code.PayloadStart();
            obj = &frame.code;
            if (FLAG_trace_debugger_stacktrace) {
              name = frame.code.QualifiedName(
                  NameFormattingParams(Object::kInternalName));
            }
          }
          ASSERT(!function.IsNull());
          if (!function.is_visible()) {
            return;
          }
          const uword absolute_pc = start + frame.pc_offset;
          if (FLAG_trace_debugger_stacktrace) {
            OS::PrintErr("  async awaiter: %s+%#" Px "\n", name,
                         frame.pc_offset);
          }
          stack_trace->AddAsyncAwaiterFrame(absolute_pc, function, *obj,
                                            frame.closure);
        }
      },
      &has_async_catch_error);

  // If the entire stack is sync, return no (async) trace.
  if (!has_async) {
    if (FLAG_trace_debugger_stacktrace) {
      OS::PrintErr(
          "CollectStackTrace: discarding async awaiters collection\n\n");
    }
    return nullptr;
  }

  stack_trace->set_has_async_catch_error(has_async_catch_error);

  if (FLAG_trace_debugger_stacktrace) {
    OS::PrintErr("CollectStackTrace: async awaiters collection finished\n\n");
  }
  return stack_trace;
}

static ActivationFrame* TopDartFrame() {
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  StackFrame* frame;
  while (true) {
    frame = iterator.NextFrame();
    RELEASE_ASSERT(frame != nullptr);
    if (!frame->IsDartFrame()) {
      continue;
    }
    auto& function = Function::Handle();
    auto& code_or_bytecode = Object::Handle();
    if (frame->is_interpreted()) {
      code_or_bytecode = frame->LookupDartBytecode();
      function = frame->LookupDartFunction();
    } else {
      code_or_bytecode = frame->LookupDartCode();
      function = Code::Cast(code_or_bytecode).function();
    }
    ActivationFrame* activation =
        new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), function,
                            code_or_bytecode, Object::null_array(), 0);
    return activation;
  }
}

DebuggerStackTrace* Debugger::StackTrace() {
  return (stack_trace_ != nullptr) ? stack_trace_
                                   : DebuggerStackTrace::Collect();
}

DebuggerStackTrace* Debugger::AsyncAwaiterStackTrace() {
  return (async_awaiter_stack_trace_ != nullptr)
             ? async_awaiter_stack_trace_
             : DebuggerStackTrace::CollectAsyncAwaiters();
}

DebuggerStackTrace* DebuggerStackTrace::From(const class StackTrace& ex_trace) {
  DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
  Function& function = Function::Handle();
  Object& code_object = Object::Handle();
  Code& code = Code::Handle();

  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).
    function = Function::null();
    uword start = 0;
    bool is_optimized_code = false;
    if (code_object.IsCode()) {
      const auto& code = Code::Cast(code_object);
      ASSERT(code.IsFunctionCode());
      function = code.function();
      start = code.PayloadStart();
      is_optimized_code = code.is_optimized();
    } else if (code_object.IsBytecode()) {
      const auto& bytecode = Bytecode::Cast(code_object);
      function = bytecode.function();
      start = bytecode.PayloadStart();
    }
    if (function.IsNull() || !function.is_visible()) continue;
    const uword pc = start + ex_trace.PcOffsetAtFrame(i);
    if (is_optimized_code && ex_trace.expand_inlined()) {
      // Traverse inlined frames.
      code ^= code_object.ptr();
      for (InlinedFunctionsIterator it(code, pc); !it.Done(); it.Advance()) {
        function = it.function();
        code = it.code();
        ASSERT(function.ptr() == code.function());
        uword pc = it.pc();
        ASSERT(pc != 0);
        ASSERT(code.PayloadStart() <= pc);
        ASSERT(pc < (code.PayloadStart() + code.Size()));

        auto* const activation = new ActivationFrame(
            pc, fp, sp, function, code, deopt_frame, deopt_frame_offset);
        stack_trace->AddActivation(activation);
      }
    }
    auto* const activation = new ActivationFrame(
        pc, fp, sp, function, code_object, 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);
  // There might be no Dart stack if we hit an exception in the runtime, most
  // likely OutOfMemory.
  if (stack_trace->Length() == 0) {
    return false;
  }
  // Exceptions coming from invalid token positions should be skipped
  ActivationFrame* top_frame = stack_trace->FrameAt(0);
  if (!top_frame->TokenPos().IsReal() && top_frame->TryIndex() != -1) {
    return false;
  }
  ActivationFrame* handler_frame = stack_trace->GetHandlerFrame(exception);
  if (handler_frame == nullptr) {
    // 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 !stack_trace->has_async_catch_error();
  }

  auto& handler_function = Function::Handle(handler_frame->function().ptr());

  // If handler_frame's function is annotated with
  // @pragma('vm:notify-debugger-on-exception'), we specifically want to notify
  // the debugger of this otherwise ignored exception.
  if (!handler_function.IsNull() &&
      Library::FindPragma(Thread::Current(), /*only_core=*/false,
                          handler_function,
                          Symbols::vm_notify_debugger_on_exception())) {
    return true;
  }
  return false;
}

void Debugger::PauseException(const Instance& exc) {
  if (FLAG_stress_async_stacks) {
    DebuggerStackTrace::CollectAsyncAwaiters();
  }
  // 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* async_awaiter_stack_trace =
      DebuggerStackTrace::CollectAsyncAwaiters();
  DebuggerStackTrace* stack_trace = DebuggerStackTrace::Collect();
  if (async_awaiter_stack_trace != nullptr) {
    if (!ShouldPauseOnException(async_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, async_awaiter_stack_trace);
  Pause(&event);
  HandleSteppingRequest();  // we may get a rewind request
  ClearCachedStackTraces();
}

// Helper that refines the resolved token pos.
//
// If |requested_column| is |-1|, then |exact_token_pos| must be
// |TokenPosition::kNoSource|.
static void RefineBreakpointPos(const Script& script,
                                TokenPosition pos,
                                TokenPosition next_closest_token_position,
                                TokenPosition requested_token_pos,
                                TokenPosition last_token_pos,
                                intptr_t requested_column,
                                TokenPosition exact_token_pos,
                                TokenPosition* best_fit_pos,
                                intptr_t* best_column,
                                intptr_t* best_line) {
  ASSERT(
      (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
      requested_column > -1);

  intptr_t token_start_column = -1;
  intptr_t token_line = -1;
  if (requested_column >= 0) {
    TokenPosition ignored = TokenPosition::kNoSource;
    TokenPosition end_of_line_pos = TokenPosition::kNoSource;
    script.GetTokenLocation(pos, &token_line, &token_start_column);
    script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);

    TokenPosition token_end_pos = TokenPosition::Min(
        TokenPosition::Deserialize(next_closest_token_position.Pos() - 1),
        end_of_line_pos);

    if ((token_end_pos.IsReal() && exact_token_pos.IsReal() &&
         (token_end_pos < exact_token_pos)) ||
        (token_start_column > *best_column)) {
      // We prefer the token with the lowest column number compatible with the
      // requested column. The current token under consideration either ends
      // before the requested column, and is thus incompatible with it, or
      // has a higher column number than the best token we've found so far, so
      // we reject the current token under consideration.
      return;
    }
  }

  // Prefer the lowest (first) token pos.
  if (pos < *best_fit_pos) {
    *best_fit_pos = pos;
    *best_line = token_line;
    *best_column = token_start_column;
  }
}

// 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.
//
// If |requested_column| is |-1|, then |exact_token_pos| must be
// |TokenPosition::kNoSource|.
//
// 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.
static TokenPosition ResolveBreakpointPos(const Function& func,
                                          TokenPosition requested_token_pos,
                                          TokenPosition last_token_pos,
                                          intptr_t requested_column,
                                          TokenPosition exact_token_pos) {
  ASSERT(!func.HasOptimizedCode());
  ASSERT(
      (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
      requested_column > -1);

  requested_token_pos =
      TokenPosition::Max(requested_token_pos, func.token_pos());
  last_token_pos = TokenPosition::Min(last_token_pos, func.end_token_pos());

  Zone* zone = Thread::Current()->zone();
  Script& script = Script::Handle(zone, func.script());
  PcDescriptors& desc = PcDescriptors::Handle(zone);
#if defined(DART_DYNAMIC_MODULES)
  auto& bytecode = Bytecode::Handle(zone);
#endif
  if (func.HasBytecode()) {
#if defined(DART_DYNAMIC_MODULES)
    bytecode = func.GetBytecode();
    ASSERT(!bytecode.IsNull());
    if (!bytecode.HasSourcePositions()) {
      return TokenPosition::kNoSource;
    }
#else
    UNREACHABLE();
#endif
  } else {
    ASSERT(func.HasCode());
    const auto& code = Code::Handle(zone, 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;

  if (func.HasBytecode()) {
#if defined(DART_DYNAMIC_MODULES)
    // Only compiled code has synthetic token positions.
    ASSERT(!requested_token_pos.IsSynthetic());
    bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode);
    while (iter.MoveNext()) {
      const TokenPosition& pos = iter.TokenPos();
      if (!pos.IsWithin(requested_token_pos, last_token_pos)) {
        // Token is not in the target range.
        continue;
      }
      TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
      if (requested_column >= 0) {
        // Find next closest emitted source position.
        bytecode::BytecodeSourcePositionsIterator iter2(zone, bytecode);
        while (iter2.MoveNext()) {
          const TokenPosition& next = iter2.TokenPos();
          if (!next.IsReal()) continue;
          if ((pos < next) && (next < next_closest_token_position)) {
            next_closest_token_position = next;
          }
        }
      }
      RefineBreakpointPos(script, pos, next_closest_token_position,
                          requested_token_pos, last_token_pos, requested_column,
                          exact_token_pos, &best_fit_pos, &best_column,
                          &best_line);
    }
#endif
  } else {
    PcDescriptors::Iterator iter(desc, kSafepointKind);
    while (iter.MoveNext()) {
      const TokenPosition& pos = iter.TokenPos();
      if (pos.IsSynthetic() && pos == requested_token_pos) {
        // if there's a safepoint for a synthetic function start and the start
        // was requested, we're done.
        return pos;
      }
      if (!pos.IsWithin(requested_token_pos, last_token_pos)) {
        // Token is not in the target range.
        continue;
      }
      TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
      if (requested_column >= 0) {
        // Find next closest safepoint
        PcDescriptors::Iterator iter2(desc, kSafepointKind);
        while (iter2.MoveNext()) {
          const TokenPosition& next = iter2.TokenPos();
          if (!next.IsReal()) continue;
          if ((pos < next) && (next < next_closest_token_position)) {
            next_closest_token_position = next;
          }
        }
      }
      RefineBreakpointPos(script, pos, next_closest_token_position,
                          requested_token_pos, last_token_pos, requested_column,
                          exact_token_pos, &best_fit_pos, &best_column,
                          &best_line);
    }
  }

  // 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) {
    ASSERT(best_fit_pos.IsReal());
    const Script& script = Script::Handle(zone, func.script());
    const TokenPosition begin_pos = best_fit_pos;

    TokenPosition end_of_line_pos = TokenPosition::kNoSource;
    if (best_line < 0) {
      script.GetTokenLocation(begin_pos, &best_line);
    }
    ASSERT(best_line > 0);
    TokenPosition ignored = TokenPosition::kNoSource;
    script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
    end_of_line_pos = TokenPosition::Max(end_of_line_pos, begin_pos);

    uword lowest_pc_offset = kUwordMax;
    if (func.HasBytecode()) {
#if defined(DART_DYNAMIC_MODULES)
      bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode);
      while (iter.MoveNext()) {
        const TokenPosition& pos = iter.TokenPos();
        uword pc_offset = iter.PcOffset();
        if (requested_column >= 0) {
          if (pos != best_fit_pos) {
            // Not an match for the requested column.
            continue;
          }
        } else if (!pos.IsWithin(begin_pos, end_of_line_pos)) {
          // Token is not on same line as best fit.
          continue;
        }
        // Prefer the lowest pc offset.
        if (pc_offset < lowest_pc_offset) {
          lowest_pc_offset = pc_offset;
          best_fit_pos = pos;
        }
      }
#endif
    } else {
      PcDescriptors::Iterator iter(desc, kSafepointKind);
      while (iter.MoveNext()) {
        const TokenPosition& pos = iter.TokenPos();
        if (requested_column >= 0) {
          if (pos != best_fit_pos) {
            // Not an match for the requested column.
            continue;
          }
        } else if (!pos.IsWithin(begin_pos, end_of_line_pos)) {
          // Token is not on same line as best fit.
          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;
  }

  return TokenPosition::kNoSource;
}

bool BreakpointLocation::EnsureIsResolved(const Function& target_function,
                                          TokenPosition exact_token_pos) {
  if (IsResolved()) {
    return true;
  }

  // Resolve source breakpoint in the newly compiled function.
  TokenPosition resolved_pos =
      ResolveBreakpointPos(target_function, token_pos(), end_token_pos(),
                           requested_column_number(), exact_token_pos);
  if (!resolved_pos.IsDebugPause()) {
    if (FLAG_verbose_debug) {
      OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
                   target_function.ToFullyQualifiedCString());
    }
    return false;
  }
  TokenPosition requested_pos = token_pos();
  TokenPosition requested_end_pos = end_token_pos();
  SetResolved(target_function, resolved_pos);
  Breakpoint* breakpoint = breakpoints();
  while (breakpoint != nullptr) {
    if (FLAG_verbose_debug) {
      OS::PrintErr("Resolved breakpoint %" Pd
                   " to pos %s, function '%s' (requested range %s-%s, "
                   "requested col %" Pd ")\n",
                   breakpoint->id(), token_pos().ToCString(),
                   target_function.ToFullyQualifiedCString(),
                   requested_pos.ToCString(), requested_end_pos.ToCString(),
                   requested_column_number());
    }
    debugger()->SendBreakpointEvent(ServiceEvent::kBreakpointResolved,
                                    breakpoint);
    breakpoint = breakpoint->next();
  }

  return true;
}

void GroupDebugger::MakeCodeBreakpointAtUnsafe(Thread* thread,
                                               const Function& func,
                                               BreakpointLocation* loc) {
  DEBUG_ASSERT(thread->IsInStoppedMutatorsScope() ||
               code_breakpoints_lock()->IsCurrentThreadWriter());

  ASSERT(loc->token_pos().IsReal());
  ASSERT((loc != nullptr) && loc->IsResolved());
  auto* zone = thread->zone();
  auto& code = Code::Handle(zone);
  auto& bytecode = Bytecode::Handle(zone);
  uword start = 0;
  uword lowest_pc_offset = kUwordMax;
  UntaggedPcDescriptors::Kind lowest_kind = UntaggedPcDescriptors::kAnyKind;
  // Find the safe point with the lowest compiled code address
  // that maps to the token position of the source breakpoint.
  if (func.HasBytecode()) {
#if defined(DART_DYNAMIC_MODULES)
    bytecode = func.GetBytecode();
    ASSERT(!bytecode.IsNull());
    if (!bytecode.HasSourcePositions()) {
      return;
    }
    start = bytecode.PayloadStart();
    bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode);
    while (iter.MoveNext()) {
      if (iter.TokenPos() == loc->token_pos_) {
        // Breakpoints are set and located using the address of the instruction
        // following the breakpoint instruction, since frames contain
        // return addresses.
        const uword pc_offset =
            KernelBytecode::Next(start + iter.PcOffset()) - start;
        if (pc_offset < lowest_pc_offset) {
          lowest_pc_offset = pc_offset;
        }
      }
    }
#else
    UNREACHABLE();
#endif
  } else {
    ASSERT(func.HasCode());
    ASSERT(!func.HasOptimizedCode());
    code = func.unoptimized_code();
    ASSERT(!code.IsNull());
    start = code.PayloadStart();
    const auto& desc = PcDescriptors::Handle(zone, code.pc_descriptors());
    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) {
    return;
  }

  uword lowest_pc = start + lowest_pc_offset;
  CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
  if (code_bpt == nullptr) {
    // No code breakpoint for this code exists; create one.
    if (!bytecode.IsNull()) {
      code_bpt = new CodeBreakpoint(bytecode, loc, lowest_pc);
    } else {
      code_bpt = new CodeBreakpoint(code, loc, lowest_pc, lowest_kind);
    }
    if (FLAG_verbose_debug) {
      OS::PrintErr("Setting code breakpoint at pos %s pc %#" Px " offset %#" Px
                   "\n",
                   loc->token_pos().ToCString(), lowest_pc, lowest_pc - start);
    }
    RegisterCodeBreakpoint(code_bpt);
  } else {
    if (FLAG_verbose_debug) {
      OS::PrintErr(
          "Adding location to existing code breakpoint at pos %s pc %#" Px
          " offset %#" Px "\n",
          loc->token_pos().ToCString(), lowest_pc, lowest_pc - start);
    }
    if (!code_bpt->HasBreakpointLocation(loc)) {
      code_bpt->AddBreakpointLocation(loc);
    }
  }
  if (loc->AnyEnabled()) {
    code_bpt->Enable();
  }
}

void GroupDebugger::MakeCodeBreakpointAt(const Function& func,
                                         BreakpointLocation* loc) {
  auto thread = Thread::Current();
  if (thread->IsInStoppedMutatorsScope()) {
    MakeCodeBreakpointAtUnsafe(thread, func, loc);
  } else {
    SafepointWriteRwLocker sl(thread, code_breakpoints_lock());
    MakeCodeBreakpointAtUnsafe(thread, func, loc);
  }
}

ErrorPtr Debugger::FindAndCompileMatchingFunctions(
    const GrowableHandlePtrArray<const Script>& scripts,
    TokenPosition start_pos,
    TokenPosition end_pos,
    GrowableObjectArray& code_function_list) const {
  auto thread = Thread::Current();
  auto zone = thread->zone();
  Script& script = Script::Handle(zone);
  Object& ensure_has_code_result = Object::Handle(zone);
  for (intptr_t i = 0; i < scripts.length(); ++i) {
    script = scripts.At(i).ptr();
    ClosureFunctionsCache::ForAllClosureFunctions(
        [&](const Function& function) {
          ASSERT(!function.IsNull());
          if ((function.token_pos() == start_pos) &&
              (function.end_token_pos() == end_pos) &&
              (function.script() == script.ptr()) && function.is_debuggable()) {
            // If we've found a matching function, ensure it's compiled so
            // the breakpoint currently being set can be resolved immediately.
            ensure_has_code_result = function.EnsureHasCodeNoThrow();
            if (ensure_has_code_result.IsError()) {
              return false;  // Stop iterating.
            }
            code_function_list.Add(function);
            ASSERT(!function.HasImplicitClosureFunction());
          }
          return true;  // Continue iterating.
        });
    if (ensure_has_code_result.IsError()) {
      return Error::Cast(ensure_has_code_result).ptr();
    }

    Class& cls = Class::Handle(zone);
    Array& functions = Array::Handle(zone);
    Function& function = Function::Handle(zone);
    Array& fields = Array::Handle(zone);
    Field& field = Field::Handle(zone);

    const ClassTable& class_table = *isolate_->group()->class_table();
    const intptr_t num_classes = class_table.NumCids();
    const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
    for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
      const intptr_t cid =
          i < num_classes ? i
                          : ClassTable::CidFromTopLevelIndex(i - num_classes);
      if (class_table.HasValidClassAt(cid)) {
        cls = class_table.At(cid);
        // 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.current_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());
            bool function_added = false;
            if (function.is_debuggable() && function.token_pos() == start_pos &&
                function.end_token_pos() == end_pos &&
                function.script() == script.ptr()) {
              // If we've found a matching function, ensure it's compiled so
              // the breakpoint currently being set can be resolved immediately.
              ensure_has_code_result = function.EnsureHasCodeNoThrow();
              if (ensure_has_code_result.IsError()) {
                return Error::Cast(ensure_has_code_result).ptr();
              }
              code_function_list.Add(function);
              function_added = true;
            }
            if (function_added && function.HasImplicitClosureFunction()) {
              function = function.ImplicitClosureFunction();
              if (function.is_debuggable()) {
                // Ensure that the implicit closure function is compiled so the
                // breakpoint currently being set can be resolved immediately.
                ensure_has_code_result = function.EnsureHasCodeNoThrow();
                if (ensure_has_code_result.IsError()) {
                  return Error::Cast(ensure_has_code_result).ptr();
                }
                code_function_list.Add(function);
              }
            }
          }
        }
        fields = cls.fields();
        if (!fields.IsNull()) {
          const intptr_t num_fields = fields.Length();
          for (intptr_t pos = 0; pos < num_fields; pos++) {
            field ^= fields.At(pos);
            ASSERT(!field.IsNull());
            if (field.Script() != script.ptr()) {
              continue;
            }
            if (!field.has_nontrivial_initializer()) {
              continue;
            }
            function = field.EnsureInitializerFunction();
            ASSERT(!function.IsNull());
            if (function.is_debuggable() && function.HasCode() &&
                function.token_pos() == start_pos &&
                function.end_token_pos() == end_pos &&
                function.script() == script.ptr()) {
              ensure_has_code_result = function.EnsureHasCodeNoThrow();
              if (ensure_has_code_result.IsError()) {
                return Error::Cast(ensure_has_code_result).ptr();
              }
              code_function_list.Add(function);
            }
          }
        }
      }
    }
  }
  return Error::null();
}

static void UpdateBestFit(Function* best_fit, const Function& func) {
  if (best_fit->IsNull()) {
    *best_fit = func.ptr();
  } else if ((best_fit->token_pos().IsSynthetic() ||
              func.token_pos().IsSynthetic() ||
              (best_fit->token_pos() < func.token_pos())) &&
             (func.end_token_pos() <= best_fit->end_token_pos())) {
    *best_fit = func.ptr();
  }
}

// If a best fit function is found, stores that function in |best_fit| and
// returns |true|.
// Note that in some cases, there may be a closure that is a better fit that the
// function returned in |best_fit|, because |FindBestFit| is only able to detect
// that closure if the function containing it has already been compiled.
bool Debugger::FindBestFit(const Script& script,
                           TokenPosition token_pos,
                           TokenPosition last_token_pos,
                           Function* best_fit) {
  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  Zone* zone = thread->zone();
  Class& cls = Class::Handle(zone);

  // A single script can belong to several libraries because of mixins.
  // Go through all libraries and for each that contains the script, try to find
  // a fit there.
  // Return the first fit found, but if a library doesn't contain a fit,
  // process the next one.
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      zone, isolate_group->object_store()->libraries());
  Library& lib = Library::Handle(zone);
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    ASSERT(!lib.IsNull());
    const Array& scripts = Array::Handle(zone, lib.LoadedScripts());
    bool lib_has_script = false;
    for (intptr_t j = 0; j < scripts.Length(); j++) {
      if (scripts.At(j) == script.ptr()) {
        lib_has_script = true;
        break;
      }
    }
    if (!lib_has_script) {
      continue;
    }

    if (!lib.IsDebuggable()) {
      if (FLAG_verbose_debug) {
        OS::PrintErr("Library '%s' has been marked as non-debuggable\n",
                     lib.ToCString());
      }
      continue;
    }

    const String& script_url = String::Handle(zone, script.url());
    ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& fun) {
      if (fun.script() == script.ptr() &&
          FunctionOverlaps(fun, script_url, token_pos, last_token_pos)) {
        // Select the inner most closure.
        UpdateBestFit(best_fit, fun);
      }
      return true;  // Continue iteration
    });

    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;
    }

    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 ClassTable& class_table = *isolate_->group()->class_table();
    const intptr_t num_classes = class_table.NumCids();
    const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
    for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
      const intptr_t cid =
          i < num_classes ? i
                          : ClassTable::CidFromTopLevelIndex(i - num_classes);
      if (!class_table.HasValidClassAt(cid)) {
        continue;
      }
      cls = class_table.At(cid);
      // This class is relevant to us only if it belongs to the
      // library to which |script| belongs.
      if (cls.library() != lib.ptr()) {
        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.current_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) || function.is_synthetic() ||
              !function.token_pos().IsReal() ||
              !function.end_token_pos().IsReal() || !function.is_debuggable()) {
            // We skip implicit functions and synthetic functions because they
            // do not have user specifiable source locations. We also skip
            // functions marked as undebuggable.
            continue;
          }
          if (FunctionOverlaps(function, script_url, 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.ptr();
            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.
      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::kNoSource;
          TokenPosition end = TokenPosition::kNoSource;
          field ^= fields.At(pos);
          ASSERT(!field.IsNull());
          if (field.Script() != script.ptr()) {
            // The field should be defined in the script we want to set
            // the breakpoint in.
            continue;
          }
          if (!field.has_nontrivial_initializer()) {
            continue;
          }
          start = field.token_pos();
          end = field.end_token_pos();
          if (token_pos.IsWithin(start, end) ||
              start.IsWithin(token_pos, last_token_pos)) {
            *best_fit = field.EnsureInitializerFunction();
            return true;
          }
        }
      }
    }
  }
  return false;
}

// If |requested_column| is |-1|, then |exact_token_pos| must be
// |TokenPosition::kNoSource|.
BreakpointLocation* Debugger::SetCodeBreakpoints(
    const GrowableHandlePtrArray<const Script>& scripts,
    TokenPosition token_pos,
    TokenPosition last_token_pos,
    intptr_t requested_line,
    intptr_t requested_column,
    TokenPosition exact_token_pos,
    const GrowableObjectArray& functions) {
  ASSERT(
      (requested_column == -1 && exact_token_pos == TokenPosition::kNoSource) ||
      requested_column > -1);

  Function& function = Function::Handle();
  function ^= functions.At(0);
  TokenPosition breakpoint_pos = ResolveBreakpointPos(
      function, token_pos, last_token_pos, requested_column, exact_token_pos);
  if (!breakpoint_pos.IsReal()) {
    return nullptr;
  }
  const String& script_url = String::Handle(scripts.At(0).url());
  BreakpointLocation* loc =
      GetResolvedBreakpointLocation(script_url, breakpoint_pos);
  if (loc == nullptr) {
    // Find an existing unresolved breakpoint location.
    loc = GetBreakpointLocation(script_url, token_pos, requested_line,
                                requested_column);
  }
  if (loc == nullptr) {
    loc = new BreakpointLocation(this, scripts, 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 code.
  if (loc->IsResolved()) {
    return loc;
  }
  loc->SetResolved(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(func.HasCode());
    group_debugger()->MakeCodeBreakpointAt(func, loc);
  }
  if (FLAG_verbose_debug) {
    intptr_t line_number = -1;
    intptr_t column_number = -1;
    scripts.At(0).GetTokenLocation(breakpoint_pos, &line_number,
                                   &column_number);
    OS::PrintErr("Resolved code breakpoint for function '%s' at line %" Pd
                 " col %" Pd "\n",
                 func.ToFullyQualifiedCString(), line_number, column_number);
  }
  return loc;
}

#if !defined(DART_PRECOMPILED_RUNTIME)
static TokenPosition FindExactTokenPosition(const Script& script,
                                            TokenPosition start_of_line,
                                            intptr_t column_number);
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

ErrorPtr Debugger::SetBreakpoint(
    const Script& script,
    TokenPosition token_pos,
    TokenPosition last_token_pos,
    intptr_t requested_line,
    intptr_t requested_column,
    const Function& function,
    BreakpointLocation** result_breakpoint_location) {
  GrowableHandlePtrArray<const Script> scripts(Thread::Current()->zone(), 1);
  scripts.Add(script);
  return SetBreakpoint(scripts, token_pos, last_token_pos, requested_line,
                       requested_column, function, result_breakpoint_location);
}

ErrorPtr Debugger::SetBreakpoint(
    const GrowableHandlePtrArray<const Script>& scripts,
    TokenPosition token_pos,
    TokenPosition last_token_pos,
    intptr_t requested_line,
    intptr_t requested_column,
    const Function& function,
    BreakpointLocation** result_breakpoint_location) {
  ASSERT(scripts.length() > 0);
  ASSERT(result_breakpoint_location != nullptr);
  Function& func = Function::Handle();
  const Script& script = scripts.At(0);
  if (function.IsNull()) {
    if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
      return Object::no_debuggable_code_error().ptr();
    }
    ASSERT(!func.IsNull());
    // There may be closures that were not considered by the first call to
    // |FindBestFit| because the functions containing them were not yet
    // compiled. So, we must recursively compile functions until we converge
    // at a true best fit function.
    Function& tmp = Function::Handle();
    Object& ensure_has_code_result = Object::Handle();
    do {
      ensure_has_code_result = func.EnsureHasCodeNoThrow();
      if (ensure_has_code_result.IsError()) {
        return Error::Cast(ensure_has_code_result).ptr();
      }
      tmp = func.ptr();
      FindBestFit(script, token_pos, last_token_pos, &func);
      ASSERT(!func.IsNull());
    } while (tmp.ptr() != func.ptr());
  } else {
    func = function.ptr();
    if (!func.token_pos().IsReal()) {
      // Missing source positions?
      return Object::no_debuggable_code_error().ptr();
    }
  }

  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. Compile and collect all functions whose source code
    // range matches exactly the best fit function we found. We compile all of
    // theses functions eagerly so that the breakpoint currently being set can
    // be resolved immediately.
    GrowableObjectArray& code_functions =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    const Error& error = Error::Handle(FindAndCompileMatchingFunctions(
        scripts, func.token_pos(), func.end_token_pos(), code_functions));
    if (!error.IsNull()) {
      return error.ptr();
    }

    if (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::kNoSource;
#if !defined(DART_PRECOMPILED_RUNTIME)
      if (token_pos != last_token_pos && requested_column >= 0) {
        exact_token_pos =
            FindExactTokenPosition(script, token_pos, requested_column);
      }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      BreakpointLocation* loc = nullptr;
      // Ensure that code stays deoptimized (and background compiler disabled)
      // until we have installed the breakpoint (at which point the compiler
      // will not try to optimize it anymore).
      RunWithStoppedDeoptimizedWorld([&] {
        loc = SetCodeBreakpoints(scripts, token_pos, last_token_pos,
                                 requested_line, requested_column,
                                 exact_token_pos, code_functions);
      });
      if (loc != nullptr) {
        *result_breakpoint_location = loc;
        return Error::null();
      }
    }
  }
  // There is no debuggable code at all at |token_pos|, so we leave
  // |*result_breakpoint_location| as null.
  return Error::null();
}

// Synchronize the enabled/disabled state of all code breakpoints
// associated with the breakpoint location loc.
void GroupDebugger::SyncBreakpointLocation(BreakpointLocation* loc) {
  bool any_enabled = loc->AnyEnabled();
  SafepointWriteRwLocker sl(Thread::Current(), code_breakpoints_lock());
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != nullptr) {
    if (cbpt->HasBreakpointLocation(loc)) {
      if (any_enabled) {
        cbpt->Enable();
      } else {
        cbpt->Disable();
      }
    }
    cbpt = cbpt->next();
  }
}

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

  ASSERT(bpt_location != nullptr);
  if (single_shot) {
    *result_breakpoint = bpt_location->AddSingleShot(this);
  } else {
    *result_breakpoint = bpt_location->AddRepeated(this);
  }
  return Error::null();
}

ErrorPtr Debugger::SetBreakpointAtActivation(const Instance& closure,
                                             bool single_shot,
                                             Breakpoint** result_breakpoint) {
  ASSERT(result_breakpoint != nullptr);

  if (!closure.IsClosure()) {
    return Object::no_debuggable_code_error().ptr();
  }
  const Function& func = Function::Handle(Closure::Cast(closure).function());
  const Script& script = Script::Handle(func.script());
  BreakpointLocation* bpt_location = nullptr;
  const Error& error = Error::Handle(
      SetBreakpoint(script, func.token_pos(), func.end_token_pos(), -1,
                    -1 /* no line/col */, func, &bpt_location));
  if (!error.IsNull()) {
    return error.ptr();
  }

  ASSERT(bpt_location != nullptr);
  *result_breakpoint =
      bpt_location->AddBreakpoint(this, Closure::Cast(closure), single_shot);
  return Error::null();
}

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

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

  return nullptr;
}

void Debugger::SetBreakpointAtResumption(const Object& function_data) {
  ASSERT(!function_data.IsNull());
  ASSERT(function_data.IsInstance());
  breakpoints_at_resumption_.Add(function_data.ptr());
  isolate_->set_has_resumption_breakpoints(true);
}

void Debugger::ResumptionBreakpoint() {
  ASSERT(!breakpoints_at_resumption_.is_empty());
  ASSERT(isolate_->has_resumption_breakpoints());

  ActivationFrame* top_frame = TopDartFrame();
  ASSERT(top_frame->function().IsSuspendableFunction());
  const auto& function_data =
      Object::Handle(top_frame->GetSuspendableFunctionData());

  for (intptr_t i = 0, n = breakpoints_at_resumption_.length(); i < n; ++i) {
    if (breakpoints_at_resumption_[i] == function_data.ptr()) {
      breakpoints_at_resumption_.RemoveAt(i);
      if (breakpoints_at_resumption_.is_empty()) {
        isolate_->set_has_resumption_breakpoints(false);
      }
      if (FLAG_verbose_debug) {
        OS::PrintErr(
            "ResumptionBreakpoint - hit a breakpoint, continue single "
            "stepping\n");
      }
      // Resumption breakpoints are for stepping out of await expressions,
      // so record its information to avoid pausing within it.
      SetLastSteppingInformation(top_frame);
      EnterSingleStepMode();
      return;
    }
  }
}

ErrorPtr Debugger::SetBreakpointAtLineCol(const String& script_url,
                                          intptr_t line_number,
                                          intptr_t column_number,
                                          Breakpoint** result_breakpoint) {
  // 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);
  ASSERT(result_breakpoint != nullptr);

  BreakpointLocation* loc = nullptr;
  const Error& error = Error::Handle(BreakpointLocationAtLineCol(
      script_url, line_number, column_number, &loc));
  if (!error.IsNull()) {
    return error.ptr();
  }

  ASSERT(loc != nullptr);
  *result_breakpoint = loc->AddRepeated(this);
  return Error::null();
}

ErrorPtr Debugger::BreakpointLocationAtLineCol(
    const String& script_url,
    intptr_t line_number,
    intptr_t column_number,
    BreakpointLocation** result_breakpoint_location) {
  ASSERT(result_breakpoint_location != nullptr);

  Zone* zone = Thread::Current()->zone();
  Library& lib = Library::Handle(zone);
  GrowableHandlePtrArray<const Script> scripts(zone, 1);
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      isolate_->group()->object_store()->libraries());
  bool is_package = script_url.StartsWith(Symbols::PackageScheme());
  bool is_dart_colon = script_url.StartsWith(Symbols::DartScheme());
  Script& script_for_lib = Script::Handle(zone);
  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();
    bool useResolvedUri = !is_package && !is_dart_colon;
    script_for_lib = lib.LookupScript(script_url, useResolvedUri);
    if (!script_for_lib.IsNull()) {
      scripts.Add(script_for_lib);
    }
  }
  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);
    }
    *result_breakpoint_location = latent_bpt;
    return Error::null();
  }
  TokenPosition first_token_idx = TokenPosition::kNoSource;
  TokenPosition last_token_idx = TokenPosition::kNoSource;
  // Assume all scripts with the same URL have the same token positions.
  scripts.At(0).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 Object::no_debuggable_code_error().ptr();
  } 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 Object::no_debuggable_code_error().ptr();
  }

  ASSERT(first_token_idx <= last_token_idx);
  Error& error = Error::Handle();
  while ((*result_breakpoint_location == nullptr) &&
         (first_token_idx <= last_token_idx)) {
    error = SetBreakpoint(scripts, first_token_idx, last_token_idx, line_number,
                          column_number, Function::Handle(),
                          result_breakpoint_location);
    if (!error.IsNull() &&
        error.ptr() != Object::no_debuggable_code_error().ptr()) {
      // We do not return an error immediately if |SetBreakpoint| returns
      // |Object::no_debuggable_code_error().ptr()|, because there is a chance
      // that |SetBreakpoint| will succeed if called again after
      // |first_token_idx| is advanced.
      return error.ptr();
    }
    first_token_idx = first_token_idx.Next();
  }
  if (*result_breakpoint_location == nullptr) {
    if (FLAG_verbose_debug) {
      OS::PrintErr("No executable code at line %" Pd " in '%s'\n", line_number,
                   script_url.ToCString());
    }
    return Object::no_debuggable_code_error().ptr();
  }
  return Error::null();
}

// Return innermost closure contained in 'function' that contains
// the given token position.
static FunctionPtr FindInnermostClosure(Zone* zone,
                                        const Function& function,
                                        TokenPosition token_pos) {
  ASSERT(function.end_token_pos().IsReal());
  const TokenPosition& func_start = function.token_pos();
  const Script& outer_origin = Script::Handle(zone, function.script());

  Function& best_fit = Function::Handle(zone);
  ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& closure) {
    const TokenPosition& closure_start = closure.token_pos();
    const TokenPosition& closure_end = closure.end_token_pos();
    // We're only interested in closures that have real ending token positions.
    // The starting token position can be synthetic.
    if (closure_end.IsReal() && (function.end_token_pos() > closure_end) &&
        (!closure_start.IsReal() || !func_start.IsReal() ||
         (closure_start > func_start)) &&
        token_pos.IsWithin(closure_start, closure_end) &&
        (closure.script() == outer_origin.ptr())) {
      UpdateBestFit(&best_fit, closure);
    }
    return true;  // Continue iteration.
  });
  return best_fit.ptr();
}

bool GroupDebugger::EnsureLocationIsInFunction(Zone* zone,
                                               const Function& function,
                                               BreakpointLocation* location) {
  const String& url = String::Handle(zone, location->url());
  if (!FunctionOverlaps(function, url, location->token_pos(),
                        location->end_token_pos())) {
    return false;
  }

  TokenPosition token_pos = location->token_pos();
#if !defined(DART_PRECOMPILED_RUNTIME)
  TokenPosition end_token_pos = location->end_token_pos();
  if (token_pos != end_token_pos && location->requested_column_number() >= 0) {
    // Narrow down the token position range to a single value
    // if requested column number is provided so that inner
    // Closure won't be missed.
    const Script& script = Script::Handle(location->script());
    token_pos = FindExactTokenPosition(script, token_pos,
                                       location->requested_column_number());
  }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
  const Function& inner_function =
      Function::Handle(zone, FindInnermostClosure(zone, function, token_pos));
  if (!inner_function.IsNull()) {
    if (FLAG_verbose_debug) {
      OS::PrintErr(
          "Pending breakpoint remains unresolved in "
          "inner function '%s'\n",
          inner_function.ToFullyQualifiedCString());
    }
    return false;
  }

  // There is no local function within function that contains the
  // breakpoint token position.
  return true;
}

void GroupDebugger::NotifyCompilation(const Function& function) {
  if (!function.is_debuggable()) {
    return;
  }
  Function& resolved_function = Function::Handle(function.ptr());
  auto thread = Thread::Current();
  auto zone = thread->zone();

  // Going through BreakpointLocations of all isolates and debuggers looking
  // for those that can be resolved and added code breakpoints at now.
  //
  // The check below is used instead of breakpoint_locations_lock acquisition.
  // We don't need to acquire the lock if always run with stopped mutators.
  // We can't acquire the lock if we run with stopped mutators as that could
  // result in deadlock.
  RELEASE_ASSERT(thread->IsInStoppedMutatorsScope());
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    BreakpointLocation* location = breakpoint_locations_.At(i);
    if (EnsureLocationIsInFunction(zone, resolved_function, location)) {
      // All mutators are stopped (see RELEASE_ASSERT above). We temporarily
      // enter the isolate for which the breakpoint was registered.
      // The code path below may issue service events which will use the active
      // isolate's object-id ring for naming VM objects.
      ActiveIsolateScope active_isolate(thread,
                                        location->debugger()->isolate());

      // Ensure the location is resolved for the original function.
      TokenPosition exact_token_pos = TokenPosition::kNoSource;
#if !defined(DART_PRECOMPILED_RUNTIME)
      if (location->token_pos() != location->end_token_pos() &&
          location->requested_column_number() >= 0) {
        exact_token_pos = FindExactTokenPosition(
            Script::Handle(location->script()), location->token_pos(),
            location->requested_column_number());
      }
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
      location->EnsureIsResolved(function, exact_token_pos);
      if (FLAG_verbose_debug) {
        Breakpoint* bpt = location->breakpoints();
        while (bpt != nullptr) {
          OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
                       function.IsClosureFunction() ? "closure" : "function",
                       function.ToFullyQualifiedCString());
          bpt = bpt->next();
        }
      }
      MakeCodeBreakpointAt(function, location);
    }
  }
}

void GroupDebugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  CodeBreakpoint* cbpt = code_breakpoints_;
  while (cbpt != nullptr) {
    cbpt->VisitObjectPointers(visitor);
    cbpt = cbpt->next();
  }
}

// static
void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
  ASSERT(visitor != nullptr);
  BreakpointLocation* loc = breakpoint_locations_;
  while (loc != nullptr) {
    loc->VisitObjectPointers(visitor);
    loc = loc->next();
  }
  loc = latent_locations_;
  while (loc != nullptr) {
    loc->VisitObjectPointers(visitor);
    loc = loc->next();
  }
  for (intptr_t i = 0, n = breakpoints_at_resumption_.length(); i < n; ++i) {
    visitor->VisitPointer(&breakpoints_at_resumption_[i]);
  }
}

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);
    }
  }

  group_debugger()->Pause();
  pause_event_ = nullptr;
}

void GroupDebugger::Pause() {
  SafepointWriteRwLocker sl(Thread::Current(), code_breakpoints_lock());
  if (needs_breakpoint_cleanup_) {
    RemoveUnlinkedCodeBreakpoints();
  }
}

void Debugger::EnterSingleStepMode() {
  ResetSteppingFramePointer();
  NotifySingleStepping(true);
}

void Debugger::ResetSteppingFramePointer() {
  stepping_fp_ = 0;
#if defined(DART_DYNAMIC_MODULES)
  stepping_fp_from_interpreted_frame_ = false;
#endif
}

void Debugger::ResetLastSteppingInformation() {
  last_stepping_fp_ = 0;
  last_stepping_pos_ = TokenPosition::kNoSource;
}

void Debugger::SetLastSteppingInformation(ActivationFrame* frame) {
  last_stepping_fp_ = frame->fp();
  last_stepping_pos_ = frame->TokenPos();
}

void Debugger::SetLastSteppingInformation(BreakpointLocation* bpt_location) {
  // Continue stepping until we reach a token position that is not the one at
  // which the breakpoint was set.
  last_stepping_fp_ = 0;
  last_stepping_pos_ = bpt_location->token_pos();
}

bool Debugger::MatchesLastSteppingInformation(ActivationFrame* frame) {
  // No information for the last event emitted was recorded.
  if (last_stepping_pos_ == TokenPosition::kNoSource) {
    return false;
  }
  // If a specific FP was recorded, then it must match as well.
  if (last_stepping_fp_ != 0 && last_stepping_fp_ != frame->fp()) {
    return false;
  }
  return last_stepping_pos_ == frame->TokenPos();
}

void Debugger::SetSyncSteppingFramePointer(ActivationFrame* frame) {
  stepping_fp_ = frame->fp();
#if defined(DART_DYNAMIC_MODULES)
  stepping_fp_from_interpreted_frame_ = frame->IsInterpreted();
#endif
}

void Debugger::HandleSteppingRequest() {
  ResetSteppingFramePointer();
  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.
    NotifySingleStepping(true);
    if (FLAG_verbose_debug) {
      OS::PrintErr("HandleSteppingRequest - kStepInto\n");
    }
  } else if (resume_action_ == kStepOver) {
    NotifySingleStepping(true);
    if (stack_trace_->Length() > 0) {
      SetSyncSteppingFramePointer(stack_trace_->FrameAt(0));
    }
    if (FLAG_verbose_debug) {
      OS::PrintErr("HandleSteppingRequest - kStepOver stepping_fp=%" Px "\n",
                   stepping_fp_);
    }
  } else if (resume_action_ == kStepOut) {
    auto* const trace = async_awaiter_stack_trace_ != nullptr
                            ? async_awaiter_stack_trace_
                            : stack_trace_;
    ActivationFrame* sync_caller = nullptr;
    ActivationFrame* last_awaiter = nullptr;
    for (intptr_t i = 1; i < trace->Length(); i++) {
      auto* const frame = trace->FrameAt(i);
      if (frame->kind() == ActivationFrame::kAsyncSuspensionMarker) {
        last_awaiter = async_awaiter_stack_trace_->FrameAt(i + 1);
      } else if (frame->IsDebuggable()) {
        if (last_awaiter != nullptr) {
          AsyncStepInto(last_awaiter->closure());
          if (FLAG_verbose_debug) {
            OS::PrintErr(
                "HandleSteppingRequest - continue to async awaiter %s\n",
                Function::Handle(last_awaiter->closure().function())
                    .ToFullyQualifiedCString());
          }
          return;
        }
        sync_caller = frame;
        break;
      }
    }
    // If there is no debuggable synchronous caller (i.e., an attempt to step
    // out of the main function), just use the closest caller so the debugger
    // doesn't emit another pause in the current function before exiting.
    if (sync_caller == nullptr) {
      ASSERT(trace->Length() > 1);
      if (FLAG_verbose_debug) {
        OS::PrintErr("HandleSteppingRequest - no debuggable callers\n");
      }
      sync_caller = trace->FrameAt(1);
    }
    NotifySingleStepping(true);
    SetSyncSteppingFramePointer(sync_caller);
    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 != nullptr)) {
        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_awaiter_stack_trace) {
  ASSERT(stack_trace_ == nullptr);
  stack_trace_ = stack_trace;
  ASSERT(async_awaiter_stack_trace_ == nullptr);
  async_awaiter_stack_trace_ = async_awaiter_stack_trace;
}

void Debugger::ClearCachedStackTraces() {
  stack_trace_ = nullptr;
  async_awaiter_stack_trace_ = nullptr;
}

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 we rewind to the indicated frame?
static bool CanRewindFrame(intptr_t frame_index, const char** error) {
  // 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 != nullptr) {
      *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, find the "rewind" pc, which is the pc
// before the corresponding call.
static uword LookupRewindPc(const Code& code, uword return_address) {
  ASSERT(!code.is_optimized());
  ASSERT(code.ContainsInstructionAt(return_address));

  uword pc_offset = return_address - code.PayloadStart();
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(code.pc_descriptors());
  PcDescriptors::Iterator iter(descriptors,
                               UntaggedPcDescriptors::kRewind |
                                   UntaggedPcDescriptors::kIcCall |
                                   UntaggedPcDescriptors::kUnoptStaticCall);
  intptr_t rewind_deopt_id = -1;
  uword rewind_pc = 0;
  while (iter.MoveNext()) {
    if (iter.Kind() == UntaggedPcDescriptors::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 != nullptr;
       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();
  set_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 " offset:0x%" Px ") sp(0x%" Px ") fp(0x%" Px
        ")\n"
        "===============================\n",
        rewind_pc, rewind_pc - code.PayloadStart(), 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();
  set_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 != nullptr)) {
      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 != nullptr;
       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();
}

void GroupDebugger::RegisterSingleSteppingDebugger(Thread* thread,
                                                   const Debugger* debugger) {
  WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
  single_stepping_set_.Insert(debugger);
}

void GroupDebugger::UnregisterSingleSteppingDebugger(Thread* thread,
                                                     const Debugger* debugger) {
  WriteRwLocker sl(Thread::Current(), single_stepping_set_lock());
  single_stepping_set_.Remove(debugger);
}

bool GroupDebugger::HasBreakpointUnsafe(Thread* thread,
                                        const Function& function) {
  DEBUG_ASSERT(thread->IsInStoppedMutatorsScope() ||
               breakpoint_locations_lock()->IsCurrentThreadReader());
  // Check if function has any breakpoints.
  String& url = String::Handle(thread->zone());
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    BreakpointLocation* location = breakpoint_locations_.At(i);
    url = location->url();
    if (FunctionOverlaps(function, url, location->token_pos(),
                         location->end_token_pos())) {
      return true;
    }
  }
  return false;
}

bool GroupDebugger::HasBreakpoint(Thread* thread, const Function& function) {
  bool hasBreakpoint = false;
  // Don't need to worry about the lock if mutators are stopped.
  if (thread->IsInStoppedMutatorsScope()) {
    hasBreakpoint = HasBreakpointUnsafe(thread, function);
  } else {
    SafepointReadRwLocker sl(thread, breakpoint_locations_lock());
    hasBreakpoint = HasBreakpointUnsafe(thread, function);
  }
  if (hasBreakpoint) {
    return true;
  }

  // TODO(aam): do we have to iterate over both code breakpoints and
  // breakpoint locations? Wouldn't be sufficient to iterate over only
  // one list? Could you have a CodeBreakpoint without corresponding
  // BreakpointLocation?
  if (HasCodeBreakpointInFunction(function)) {
    return true;
  }

  return false;
}

bool GroupDebugger::IsDebugging(Thread* thread, const Function& function) {
  {
    ReadRwLocker ml(thread, single_stepping_set_lock());
    if (!single_stepping_set_.IsEmpty()) {
      return true;
    }
  }
  return HasBreakpoint(thread, function);
}

void Debugger::set_resume_action(ResumeAction resume_action) {
  auto thread = Thread::Current();
  if (resume_action == kContinue) {
    group_debugger()->UnregisterSingleSteppingDebugger(thread, this);
  } else {
    group_debugger()->RegisterSingleSteppingDebugger(thread, this);
  }
  resume_action_ = resume_action;
}

void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
  set_resume_action(kContinue);
  ResetSteppingFramePointer();
  NotifySingleStepping(false);
  ASSERT(!IsPaused());
  if ((bpt != nullptr) && bpt->is_single_shot()) {
    RemoveBreakpoint(bpt->id());
    bpt = nullptr;
  }

  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);
}

static bool IsAtAsyncJump(ActivationFrame* top_frame) {
  Thread* const thread = Thread::Current();
  Zone* const zone = thread->zone();
  if (!top_frame->function().IsAsyncFunction() &&
      !top_frame->function().IsAsyncGenerator()) {
    return false;
  }
  if (top_frame->IsInterpreted()) {
#if defined(DART_DYNAMIC_MODULES)
    const auto& bytecode = top_frame->bytecode();
    ASSERT(bytecode.HasSourcePositions());
    const uword pc_offset = top_frame->pc() - bytecode.PayloadStart();
    // pc_offset could equal to bytecode size if the last instruction is Throw.
    ASSERT(pc_offset <= static_cast<uword>(bytecode.Size()));
    bytecode::BytecodeSourcePositionsIterator iter(zone, bytecode);
    bool is_yield_point = false;
    while (iter.MoveNext()) {
      if (pc_offset <= iter.PcOffset()) {
        break;
      }
      is_yield_point = iter.IsYieldPoint();
    }
    return is_yield_point;
#else
    UNREACHABLE();
#endif
  } else {
    const TokenPosition looking_for = top_frame->TokenPos();
    const auto& pc_descriptors =
        PcDescriptors::Handle(zone, top_frame->code().pc_descriptors());
    if (!pc_descriptors.IsNull()) {
      PcDescriptors::Iterator it(pc_descriptors, UntaggedPcDescriptors::kOther);
      while (it.MoveNext()) {
        if (it.TokenPos() == looking_for &&
            it.YieldIndex() != UntaggedPcDescriptors::kInvalidYieldIndex) {
          return true;
        }
      }
    }
  }
  return false;
}

static bool IsAtBytecodeAsyncReturn(ActivationFrame* top_frame) {
#if defined(DART_DYNAMIC_MODULES)
  if (!top_frame->IsInterpreted()) return false;
  const auto& bytecode = top_frame->bytecode();
  const uword return_address = top_frame->pc();
  const uword prev = bytecode.GetInstructionBefore(return_address);
  if (prev == 0) {
    const uword start = bytecode.PayloadStart();
    // Async awaiter frames have an PC offset of 0 or 1.
    ASSERT(return_address == start ||
           return_address == start + StackTraceUtils::kFutureListenerPcOffset);
    return false;
  }
  auto* const instr = reinterpret_cast<const KBCInstr*>(prev);
  // Async returns in bytecode are implemented via direct calls to
  // the appropriate Dart async return method. Note that unlike other async
  // machinery, the direct call to _returnAsync is not marked synthetic.
  if (!KernelBytecode::IsDirectCallOpcode(instr)) {
    return false;
  }
  auto const index = KernelBytecode::DecodeD(instr);
  auto* const thread = Thread::Current();
  Zone* const zone = thread->zone();
  const auto& pool = ObjectPool::Handle(zone, bytecode.object_pool());
  const auto& obj = Object::Handle(zone, pool.ObjectAt(index));
  if (obj.IsNull() || !obj.IsFunction()) {
    return false;
  }
  const auto& target = Function::Cast(obj);
  auto* const object_store = thread->isolate_group()->object_store();
  return target.ptr() == object_store->suspend_state_return_async() ||
         target.ptr() ==
             object_store->suspend_state_return_async_not_future() ||
         target.ptr() == object_store->suspend_state_return_async_star();
#else
  return false;
#endif
}

#if defined(DART_DYNAMIC_MODULES)
static ActivationFrame::Relation CompareTopDartFrameTo(uword other_fp,
                                                       bool is_interpreted) {
  StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames,
                              Thread::Current(),
                              StackFrameIterator::kNoCrossThreadIteration);
  for (auto* frame = iterator.NextFrame(); frame != nullptr;
       frame = iterator.NextFrame()) {
    if (frame->IsDartFrame() && (frame->is_interpreted() == is_interpreted)) {
      // The current frame's FP can be directly compared to the provided FP to
      // provide an answer, since they're using the same stack.
      //
      // Since this function is only called if the top Dart frame is interpreted
      // but the stepping frame is not or vice versa, the current frame is not
      // the top Dart frame, so a result of kSelf means the top Dart frame
      // is a callee.
      return ActivationFrame::CompareTo(is_interpreted, frame->fp(),
                                        other_fp) == ActivationFrame::kCaller
                 ? ActivationFrame::kCaller
                 : ActivationFrame::kCallee;
    }
  }
  // If there were no frames of the same type on the stack, this must have been
  // a caller of the original jump into the interpreter.
  ASSERT(is_interpreted);
  return ActivationFrame::kCaller;
}
#endif

ErrorPtr Debugger::PauseStepping() {
  ASSERT(Thread::Current()->single_step());
  // Don't pause recursively.
  if (IsPaused()) {
    return Error::null();
  }

  ActivationFrame* frame = TopDartFrame();
  ASSERT(frame != nullptr);
  if (stepping_fp_ != 0) {
    // 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.
#if defined(DART_DYNAMIC_MODULES)
    auto const relation =
        stepping_fp_from_interpreted_frame_ == frame->IsInterpreted()
            ? frame->CompareTo(stepping_fp_)
            // Since interpreted code and compiled code use different stacks,
            // finding the relation to the top Dart frame requires some amount
            // of stack frame iteration.
            : CompareTopDartFrameTo(stepping_fp_,
                                    stepping_fp_from_interpreted_frame_);
#else
    // Note that we assume that the stack grows towards lower addresses.
    auto const relation = frame->CompareTo(stepping_fp_);
#endif
    // There is an "interesting frame" set. Only pause at appropriate
    // locations in this frame.
    if (relation == ActivationFrame::kCallee) {
      // We are in a callee of the frame we're interested in.
      // Ignore this stepping break.
      return Error::null();
    } else if (relation == ActivationFrame::kCaller) {
      // 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.
      ResetSteppingFramePointer();
    }
  }

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

  if (MatchesLastSteppingInformation(frame)) {
    // Do not stop multiple times for the same token position.
    // Several 'debug checked' opcodes may be issued in the same token range,
    // a breakpoint could be set at a given pause point, or we could be in the
    // bytecode interpreter which checks single stepping at each instruction.
    return Error::null();
  }

  // If there is an active breakpoint at this pc, then the last stepping
  // information should have been set appropriately to bail out above.
  ASSERT(!group_debugger()->HasActiveBreakpoint(frame->pc()));

  // TODO(dartbug.com/48378): Consider aligning async/async* functions
  // with regular function wrt the first stop in the function prologue.
  if ((frame->function().IsAsyncFunction() ||
       frame->function().IsAsyncGenerator()) &&
      frame->GetSuspendStateVar() == Object::null() &&
      // The bytecode generator sets the suspend state var to null prior
      // to returning.
      !IsAtBytecodeAsyncReturn(frame)) {
    return Error::null();
  }

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

  SetLastSteppingInformation(frame);
  CacheStackTraces(DebuggerStackTrace::Collect(),
                   DebuggerStackTrace::CollectAsyncAwaiters());
  SignalPausedEvent(frame, nullptr);
  HandleSteppingRequest();
  ClearCachedStackTraces();

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

ErrorPtr 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 = DebuggerStackTrace::Collect();
  ASSERT(stack_trace->Length() > 0);
  ActivationFrame* top_frame = stack_trace->FrameAt(0);
  ASSERT(top_frame != nullptr);
  if (!Library::Handle(top_frame->Library()).IsDebuggable()) {
    return Error::null();
  }

  BreakpointLocation* bpt_location = nullptr;
  const char* cbpt_tostring = nullptr;
  {
    SafepointReadRwLocker cbl(Thread::Current(),
                              group_debugger()->code_breakpoints_lock());
    CodeBreakpoint* cbpt = nullptr;
    bpt_location = group_debugger()->GetBreakpointLocationFor(
        this, top_frame->pc(), &cbpt);
    if (bpt_location == nullptr) {
      // There might be no breakpoint locations for this isolate/debugger.
      return Error::null();
    }
    ASSERT(cbpt != nullptr);
    if (FLAG_verbose_debug) {
      cbpt_tostring = cbpt->ToCString();
    }
  }

  Breakpoint* bpt_hit = bpt_location->FindHitBreakpoint(top_frame);
  if (bpt_hit == nullptr) {
    return Error::null();
  }

  if (FLAG_verbose_debug) {
    OS::PrintErr(">>> hit %" Pd
                 " %s"
                 " (func %s token %s address %#" Px " offset %#" Px ")\n",
                 bpt_hit->id(), cbpt_tostring,
                 String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
                 bpt_location->token_pos().ToCString(), top_frame->pc(),
                 top_frame->pc() - top_frame->PayloadStart());
  }

  // Set the last stepping information before handling the stepping request in
  // case the breakpoint is disabled either because it is a one shot or because
  // a service call disables it before the next stepping request.
  SetLastSteppingInformation(bpt_location);
  CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());
  SignalPausedEvent(top_frame, bpt_hit);
  HandleSteppingRequest();
  ClearCachedStackTraces();

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

Breakpoint* BreakpointLocation::FindHitBreakpoint(ActivationFrame* top_frame) {
  // 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 = breakpoints();
  while (bpt != nullptr) {
    if (bpt->is_single_shot() && bpt->closure() == Instance::null()) {
      return bpt;
    }
    bpt = bpt->next();
  }

  // Now check for a closure-specific breakpoint.
  bpt = breakpoints();
  while (bpt != nullptr) {
    if (bpt->closure() != Instance::null() &&
        bpt->closure() == top_frame->GetClosure()) {
      return bpt;
    }
    bpt = bpt->next();
  }

  // Finally, check for a general breakpoint.
  bpt = breakpoints();
  while (bpt != nullptr) {
    if (!bpt->is_single_shot() && bpt->closure() == Instance::null()) {
      return bpt;
    }
    bpt = bpt->next();
  }

  return nullptr;
}

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.
  //
  // Also ignore it if single stepping, as the debugger already generated
  // an appropriate pause for the user call to the function before this point.
  if (ignore_breakpoints_ || IsPaused() || IsSingleStepping()) {
    return;
  }

  DebuggerStackTrace* stack_trace = DebuggerStackTrace::Collect();
  ASSERT(stack_trace->Length() > 0);
  CacheStackTraces(stack_trace, DebuggerStackTrace::CollectAsyncAwaiters());

  // 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);
  // Reset the last stepping information to ensure we pause after stepping out.
  ResetLastSteppingInformation();
  HandleSteppingRequest();
  ClearCachedStackTraces();
}

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

#if !defined(DART_PRECOMPILED_RUNTIME)
// |reference_pos_on_line| may specify the position of any column on a
// particular line. This function will return the position of column
// [column_number] on that same line.
static TokenPosition FindExactTokenPosition(const Script& script,
                                            TokenPosition reference_pos_on_line,
                                            intptr_t column_number) {
  intptr_t line;
  intptr_t col;
  if (script.GetTokenLocation(reference_pos_on_line, &line, &col)) {
    return TokenPosition::Deserialize(reference_pos_on_line.Pos() +
                                      (column_number - col));
  }
  return TokenPosition::kNoSource;
}
#endif  // !defined(DART_PRECOMPILED_RUNTIME)

void Debugger::NotifyDoneLoading() {
  if (latent_locations_ == nullptr) {
    // Common, fast path.
    return;
  }
  auto thread = Thread::Current();
  auto isolate_group = thread->isolate_group();
  auto zone = thread->zone();
  Library& lib = Library::Handle(zone);
  Script& script = Script::Handle(zone);
  String& url = String::Handle(zone);
  BreakpointLocation* loc = latent_locations_;
  BreakpointLocation* prev_loc = nullptr;
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate_group->object_store()->libraries());

  GrowableHandlePtrArray<const Script> scripts(zone, 1);
  while (loc != nullptr) {
    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()) {
        scripts.Add(script);
      }
    }
    if (scripts.length() > 0) {
      // 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 == nullptr) {
        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 = TokenPosition::kNoSource;
      TokenPosition last_token_pos = TokenPosition::kNoSource;
      scripts.At(0).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 != nullptr) {
          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(url, first_token_pos, -1, column_number);
        ASSERT(existing_loc == nullptr);
        if (existing_loc == nullptr) {
          // Create and register a new source breakpoint for the
          // latent breakpoint.
          BreakpointLocation* unresolved_loc = new BreakpointLocation(
              this, scripts, 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(nullptr);
          while (bpt != nullptr) {
            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();
          }
          group_debugger()->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 != nullptr) {
          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 GroupDebugger::HasActiveBreakpoint(uword pc) {
  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
  CodeBreakpoint* cbpt = GetCodeBreakpoint(pc);
  return (cbpt != nullptr) && (cbpt->IsEnabled());
}

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

BreakpointLocation* GroupDebugger::GetBreakpointLocationFor(
    Debugger* debugger,
    uword breakpoint_address,
    CodeBreakpoint** pcbpt) {
  ASSERT(pcbpt != nullptr);
  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
  *pcbpt = code_breakpoints_;
  while (*pcbpt != nullptr) {
    if ((*pcbpt)->pc() == breakpoint_address) {
      return (*pcbpt)->FindBreakpointForDebugger(debugger);
    }
    *pcbpt = (*pcbpt)->next();
  }
  return nullptr;
}

void GroupDebugger::RegisterCodeBreakpoint(CodeBreakpoint* cbpt) {
  ASSERT(cbpt->next() == nullptr);
  DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
               Thread::Current()->IsInStoppedMutatorsScope());
  cbpt->set_next(code_breakpoints_);
  code_breakpoints_ = cbpt;
}

CodePtr GroupDebugger::GetPatchedStubAddress(uword breakpoint_address) {
  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
  CodeBreakpoint* cbpt = GetCodeBreakpoint(breakpoint_address);
  if (cbpt != nullptr) {
    return cbpt->OrigStubAddress();
  }
  UNREACHABLE();
  return Code::null();
}

uint32_t GroupDebugger::GetPatchedOpcode(uword breakpoint_address) {
  SafepointReadRwLocker sl(Thread::Current(), code_breakpoints_lock());
  CodeBreakpoint* cbpt = GetCodeBreakpoint(breakpoint_address);
  if (cbpt != nullptr) {
    return cbpt->OrigOpcode();
  }
  UNREACHABLE();
  return kMaxUint32;
}

bool Debugger::SetBreakpointState(Breakpoint* bpt, bool enable) {
  SafepointWriteRwLocker sl(Thread::Current(),
                            group_debugger()->breakpoint_locations_lock());
  if (bpt->is_enabled() != enable) {
    if (FLAG_verbose_debug) {
      OS::PrintErr("Setting breakpoint %" Pd " to state: %s\n", bpt->id(),
                   enable ? "enabled" : "disabled");
    }
    enable ? bpt->Enable() : bpt->Disable();
    group_debugger()->SyncBreakpointLocation(bpt->bpt_location());
    return true;
  }
  return false;
}

// Remove and delete the source breakpoint bpt and its associated
// code breakpoints.
void Debugger::RemoveBreakpoint(intptr_t bp_id) {
  SafepointWriteRwLocker sl(Thread::Current(),
                            group_debugger()->breakpoint_locations_lock());
  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 = nullptr;
  BreakpointLocation* curr_loc = *list;
  while (curr_loc != nullptr) {
    Breakpoint* prev_bpt = nullptr;
    Breakpoint* curr_bpt = curr_loc->breakpoints();
    while (curr_bpt != nullptr) {
      if (curr_bpt->id() == bp_id) {
        if (prev_bpt == nullptr) {
          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(nullptr);
        curr_bpt->set_bpt_location(nullptr);
        // Remove possible references to the breakpoint.
        if (pause_event_ != nullptr && pause_event_->breakpoint() == curr_bpt) {
          pause_event_->set_breakpoint(nullptr);
        }
        delete curr_bpt;
        curr_bpt = nullptr;

        // Delete the breakpoint location object if there are no more
        // breakpoints at that location.
        if (curr_loc->breakpoints() == nullptr) {
          if (prev_loc == nullptr) {
            *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.
            group_debugger()->UnlinkCodeBreakpoints(curr_loc);
          }
          group_debugger()->UnregisterBreakpointLocation(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;
}

void GroupDebugger::RegisterBreakpointLocation(BreakpointLocation* location) {
  DEBUG_ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter() ||
               Thread::Current()->IsInStoppedMutatorsScope());
  breakpoint_locations_.Add(location);
}

void GroupDebugger::UnregisterBreakpointLocation(BreakpointLocation* location) {
  ASSERT(breakpoint_locations_lock()->IsCurrentThreadWriter());
  for (intptr_t i = 0; i < breakpoint_locations_.length(); i++) {
    if (breakpoint_locations_.At(i) == location) {
      breakpoint_locations_.EraseAt(i);
      return;
    }
  }
}

// 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 GroupDebugger::UnlinkCodeBreakpoints(BreakpointLocation* bpt_location) {
  ASSERT(bpt_location != nullptr);
  SafepointWriteRwLocker sl(Thread::Current(), code_breakpoints_lock());
  CodeBreakpoint* curr_bpt = code_breakpoints_;
  while (curr_bpt != nullptr) {
    if (curr_bpt->FindAndDeleteBreakpointLocation(bpt_location)) {
      curr_bpt->Disable();
      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 GroupDebugger::RemoveUnlinkedCodeBreakpoints() {
  DEBUG_ASSERT(code_breakpoints_lock()->IsCurrentThreadWriter() ||
               Thread::Current()->IsInStoppedMutatorsScope());
  CodeBreakpoint* prev_bpt = nullptr;
  CodeBreakpoint* curr_bpt = code_breakpoints_;
  while (curr_bpt != nullptr) {
    if (curr_bpt->HasNoBreakpointLocations()) {
      if (prev_bpt == nullptr) {
        code_breakpoints_ = code_breakpoints_->next();
      } else {
        prev_bpt->set_next(curr_bpt->next());
      }
      CodeBreakpoint* temp_bpt = curr_bpt;
      curr_bpt = curr_bpt->next();
      delete temp_bpt;
    } else {
      prev_bpt = curr_bpt;
      curr_bpt = curr_bpt->next();
    }
  }
  needs_breakpoint_cleanup_ = false;
}

BreakpointLocation* Debugger::GetResolvedBreakpointLocation(
    const String& script_url,
    TokenPosition code_token_pos) {
  BreakpointLocation* loc = breakpoint_locations_;
  String& loc_url = String::Handle();
  while (loc != nullptr) {
    loc_url = loc->url();
    if (script_url.Equals(loc_url) && loc->code_token_pos_ == code_token_pos) {
      return loc;
    }
    loc = loc->next();
  }
  return nullptr;
}

BreakpointLocation* Debugger::GetBreakpointLocation(
    const String& script_url,
    TokenPosition token_pos,
    intptr_t requested_line,
    intptr_t requested_column,
    TokenPosition code_token_pos) {
  BreakpointLocation* loc = breakpoint_locations_;
  String& loc_url = String::Handle();
  while (loc != nullptr) {
    loc_url = loc->url();
    if (script_url.Equals(loc_url) &&
        (!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)) &&
        (!code_token_pos.IsReal() ||
         (loc->code_token_pos_ == code_token_pos))) {
      return loc;
    }
    loc = loc->next();
  }
  return nullptr;
}

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

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

void Debugger::AsyncStepInto(const Closure& awaiter) {
  Zone* zone = Thread::Current()->zone();

  auto& suspend_state = SuspendState::Handle(zone);
  if (StackTraceUtils::GetSuspendState(awaiter, &suspend_state)) {
    const auto& function_data =
        Object::Handle(zone, suspend_state.function_data());
    SetBreakpointAtResumption(function_data);
  } else {
    // We intentionally discard the value stored into the following variable.
    Breakpoint* _ = nullptr;
    const Error& error = Error::Handle(
        SetBreakpointAtActivation(awaiter, /*single_shot=*/true, &_));
    // This method cannot be called while responding to a Service RPC, so we
    // know that the top error handler is an exit frame.
    DEBUG_ASSERT(Thread::Current()->TopErrorHandlerIsExitFrame());
    if (!error.IsNull()) {
      if (error.ptr() == Object::out_of_memory_error().ptr()) {
        Exceptions::ThrowOOM();
        UNREACHABLE();
      }
      if (error.IsLanguageError()) {
        Exceptions::ThrowCompileTimeError(LanguageError::Cast(error));
        UNREACHABLE();
      }
      Exceptions::PropagateError(Error::Cast(error));
      UNREACHABLE();
    }
  }
  Continue();
}

void Debugger::Continue() {
  SetResumeAction(kContinue);
  ResetSteppingFramePointer();
  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 != nullptr) {
    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(this, url, line, column);
  loc->set_next(latent_locations_);
  latent_locations_ = loc;
  return loc;
}

void Debugger::RegisterBreakpointLocationUnsafe(BreakpointLocation* loc) {
  DEBUG_ASSERT(
      group_debugger()->breakpoint_locations_lock()->IsCurrentThreadWriter() ||
      Thread::Current()->IsInStoppedMutatorsScope());
  ASSERT(loc->next() == nullptr);
  loc->set_next(breakpoint_locations_);
  breakpoint_locations_ = loc;
  group_debugger()->RegisterBreakpointLocation(loc);
}

void Debugger::RegisterBreakpointLocation(BreakpointLocation* loc) {
  auto thread = Thread::Current();
  if (thread->IsInStoppedMutatorsScope()) {
    RegisterBreakpointLocationUnsafe(loc);
  } else {
    SafepointWriteRwLocker sl(thread,
                              group_debugger()->breakpoint_locations_lock());
    RegisterBreakpointLocationUnsafe(loc);
  }
}

#endif  // !PRODUCT

}  // namespace dart
