/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "debugger.h"

#include <sys/uio.h>

#include <set>

#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/time_utils.h"
#include "class_linker.h"
#include "class_linker-inl.h"
#include "dex_file-inl.h"
#include "dex_instruction.h"
#include "gc/accounting/card_table-inl.h"
#include "gc/allocation_record.h"
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "handle_scope.h"
#include "jdwp/jdwp_priv.h"
#include "jdwp/object_registry.h"
#include "mirror/class.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
#include "mirror/throwable.h"
#include "quick/inline_method_analyser.h"
#include "reflection.h"
#include "safe_map.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "handle_scope-inl.h"
#include "thread_list.h"
#include "utf.h"
#include "verifier/method_verifier-inl.h"
#include "well_known_classes.h"

namespace art {

// The key identifying the debugger to update instrumentation.
static constexpr const char* kDbgInstrumentationKey = "Debugger";

// Limit alloc_record_count to the 2BE value (64k-1) that is the limit of the current protocol.
static uint16_t CappedAllocRecordCount(size_t alloc_record_count) {
  const size_t cap = 0xffff;
  if (alloc_record_count > cap) {
    return cap;
  }
  return alloc_record_count;
}

class Breakpoint {
 public:
  Breakpoint(ArtMethod* method, uint32_t dex_pc,
             DeoptimizationRequest::Kind deoptimization_kind)
    SHARED_REQUIRES(Locks::mutator_lock_)
    : method_(nullptr), dex_pc_(dex_pc), deoptimization_kind_(deoptimization_kind) {
    CHECK(deoptimization_kind_ == DeoptimizationRequest::kNothing ||
          deoptimization_kind_ == DeoptimizationRequest::kSelectiveDeoptimization ||
          deoptimization_kind_ == DeoptimizationRequest::kFullDeoptimization);
    ScopedObjectAccessUnchecked soa(Thread::Current());
    method_ = soa.EncodeMethod(method);
  }

  Breakpoint(const Breakpoint& other) SHARED_REQUIRES(Locks::mutator_lock_)
    : method_(nullptr), dex_pc_(other.dex_pc_),
      deoptimization_kind_(other.deoptimization_kind_) {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    method_ = soa.EncodeMethod(other.Method());
  }

  ArtMethod* Method() const SHARED_REQUIRES(Locks::mutator_lock_) {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    return soa.DecodeMethod(method_);
  }

  uint32_t DexPc() const {
    return dex_pc_;
  }

  DeoptimizationRequest::Kind GetDeoptimizationKind() const {
    return deoptimization_kind_;
  }

 private:
  // The location of this breakpoint.
  jmethodID method_;
  uint32_t dex_pc_;

  // Indicates whether breakpoint needs full deoptimization or selective deoptimization.
  DeoptimizationRequest::Kind deoptimization_kind_;
};

static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  os << StringPrintf("Breakpoint[%s @%#x]", PrettyMethod(rhs.Method()).c_str(), rhs.DexPc());
  return os;
}

class DebugInstrumentationListener FINAL : public instrumentation::InstrumentationListener {
 public:
  DebugInstrumentationListener() {}
  virtual ~DebugInstrumentationListener() {}

  void MethodEntered(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                     uint32_t dex_pc)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    if (method->IsNative()) {
      // TODO: post location events is a suspension point and native method entry stubs aren't.
      return;
    }
    if (IsListeningToDexPcMoved()) {
      // We also listen to kDexPcMoved instrumentation event so we know the DexPcMoved method is
      // going to be called right after us. To avoid sending JDWP events twice for this location,
      // we report the event in DexPcMoved. However, we must remind this is method entry so we
      // send the METHOD_ENTRY event. And we can also group it with other events for this location
      // like BREAKPOINT or SINGLE_STEP (or even METHOD_EXIT if this is a RETURN instruction).
      thread->SetDebugMethodEntry();
    } else if (IsListeningToMethodExit() && IsReturn(method, dex_pc)) {
      // We also listen to kMethodExited instrumentation event and the current instruction is a
      // RETURN so we know the MethodExited method is going to be called right after us. To avoid
      // sending JDWP events twice for this location, we report the event(s) in MethodExited.
      // However, we must remind this is method entry so we send the METHOD_ENTRY event. And we can
      // also group it with other events for this location like BREAKPOINT or SINGLE_STEP.
      thread->SetDebugMethodEntry();
    } else {
      Dbg::UpdateDebugger(thread, this_object, method, 0, Dbg::kMethodEntry, nullptr);
    }
  }

  void MethodExited(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                    uint32_t dex_pc, const JValue& return_value)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    if (method->IsNative()) {
      // TODO: post location events is a suspension point and native method entry stubs aren't.
      return;
    }
    uint32_t events = Dbg::kMethodExit;
    if (thread->IsDebugMethodEntry()) {
      // It is also the method entry.
      DCHECK(IsReturn(method, dex_pc));
      events |= Dbg::kMethodEntry;
      thread->ClearDebugMethodEntry();
    }
    Dbg::UpdateDebugger(thread, this_object, method, dex_pc, events, &return_value);
  }

  void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object ATTRIBUTE_UNUSED,
                    ArtMethod* method, uint32_t dex_pc)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    // We're not recorded to listen to this kind of event, so complain.
    LOG(ERROR) << "Unexpected method unwind event in debugger " << PrettyMethod(method)
               << " " << dex_pc;
  }

  void DexPcMoved(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                  uint32_t new_dex_pc)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    if (IsListeningToMethodExit() && IsReturn(method, new_dex_pc)) {
      // We also listen to kMethodExited instrumentation event and the current instruction is a
      // RETURN so we know the MethodExited method is going to be called right after us. Like in
      // MethodEntered, we delegate event reporting to MethodExited.
      // Besides, if this RETURN instruction is the only one in the method, we can send multiple
      // JDWP events in the same packet: METHOD_ENTRY, METHOD_EXIT, BREAKPOINT and/or SINGLE_STEP.
      // Therefore, we must not clear the debug method entry flag here.
    } else {
      uint32_t events = 0;
      if (thread->IsDebugMethodEntry()) {
        // It is also the method entry.
        events = Dbg::kMethodEntry;
        thread->ClearDebugMethodEntry();
      }
      Dbg::UpdateDebugger(thread, this_object, method, new_dex_pc, events, nullptr);
    }
  }

  void FieldRead(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
                 ArtMethod* method, uint32_t dex_pc, ArtField* field)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field);
  }

  void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
                    ArtMethod* method, uint32_t dex_pc, ArtField* field,
                    const JValue& field_value)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value);
  }

  void ExceptionCaught(Thread* thread ATTRIBUTE_UNUSED, mirror::Throwable* exception_object)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    Dbg::PostException(exception_object);
  }

  // We only care about how many backward branches were executed in the Jit.
  void BackwardBranch(Thread* /*thread*/, ArtMethod* method, int32_t dex_pc_offset)
      OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    LOG(ERROR) << "Unexpected backward branch event in debugger " << PrettyMethod(method)
               << " " << dex_pc_offset;
  }

 private:
  static bool IsReturn(ArtMethod* method, uint32_t dex_pc)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    const DexFile::CodeItem* code_item = method->GetCodeItem();
    const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]);
    return instruction->IsReturn();
  }

  static bool IsListeningToDexPcMoved() SHARED_REQUIRES(Locks::mutator_lock_) {
    return IsListeningTo(instrumentation::Instrumentation::kDexPcMoved);
  }

  static bool IsListeningToMethodExit() SHARED_REQUIRES(Locks::mutator_lock_) {
    return IsListeningTo(instrumentation::Instrumentation::kMethodExited);
  }

  static bool IsListeningTo(instrumentation::Instrumentation::InstrumentationEvent event)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    return (Dbg::GetInstrumentationEvents() & event) != 0;
  }

  DISALLOW_COPY_AND_ASSIGN(DebugInstrumentationListener);
} gDebugInstrumentationListener;

// JDWP is allowed unless the Zygote forbids it.
static bool gJdwpAllowed = true;

// Was there a -Xrunjdwp or -agentlib:jdwp= argument on the command line?
static bool gJdwpConfigured = false;

// JDWP options for debugging. Only valid if IsJdwpConfigured() is true.
static JDWP::JdwpOptions gJdwpOptions;

// Runtime JDWP state.
static JDWP::JdwpState* gJdwpState = nullptr;
static bool gDebuggerConnected;  // debugger or DDMS is connected.

static bool gDdmThreadNotification = false;

// DDMS GC-related settings.
static Dbg::HpifWhen gDdmHpifWhen = Dbg::HPIF_WHEN_NEVER;
static Dbg::HpsgWhen gDdmHpsgWhen = Dbg::HPSG_WHEN_NEVER;
static Dbg::HpsgWhat gDdmHpsgWhat;
static Dbg::HpsgWhen gDdmNhsgWhen = Dbg::HPSG_WHEN_NEVER;
static Dbg::HpsgWhat gDdmNhsgWhat;

bool Dbg::gDebuggerActive = false;
bool Dbg::gDisposed = false;
ObjectRegistry* Dbg::gRegistry = nullptr;

// Deoptimization support.
std::vector<DeoptimizationRequest> Dbg::deoptimization_requests_;
size_t Dbg::full_deoptimization_event_count_ = 0;

// Instrumentation event reference counters.
size_t Dbg::dex_pc_change_event_ref_count_ = 0;
size_t Dbg::method_enter_event_ref_count_ = 0;
size_t Dbg::method_exit_event_ref_count_ = 0;
size_t Dbg::field_read_event_ref_count_ = 0;
size_t Dbg::field_write_event_ref_count_ = 0;
size_t Dbg::exception_catch_event_ref_count_ = 0;
uint32_t Dbg::instrumentation_events_ = 0;

// Breakpoints.
static std::vector<Breakpoint> gBreakpoints GUARDED_BY(Locks::breakpoint_lock_);

void DebugInvokeReq::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
  receiver.VisitRootIfNonNull(visitor, root_info);  // null for static method call.
  klass.VisitRoot(visitor, root_info);
}

void SingleStepControl::AddDexPc(uint32_t dex_pc) {
  dex_pcs_.insert(dex_pc);
}

bool SingleStepControl::ContainsDexPc(uint32_t dex_pc) const {
  return dex_pcs_.find(dex_pc) == dex_pcs_.end();
}

static bool IsBreakpoint(const ArtMethod* m, uint32_t dex_pc)
    REQUIRES(!Locks::breakpoint_lock_)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
  for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
    if (gBreakpoints[i].DexPc() == dex_pc && gBreakpoints[i].Method() == m) {
      VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
      return true;
    }
  }
  return false;
}

static bool IsSuspendedForDebugger(ScopedObjectAccessUnchecked& soa, Thread* thread)
    REQUIRES(!Locks::thread_suspend_count_lock_) {
  MutexLock mu(soa.Self(), *Locks::thread_suspend_count_lock_);
  // A thread may be suspended for GC; in this code, we really want to know whether
  // there's a debugger suspension active.
  return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0;
}

static mirror::Array* DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
  if (o == nullptr) {
    *error = JDWP::ERR_INVALID_OBJECT;
    return nullptr;
  }
  if (!o->IsArrayInstance()) {
    *error = JDWP::ERR_INVALID_ARRAY;
    return nullptr;
  }
  *error = JDWP::ERR_NONE;
  return o->AsArray();
}

static mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
  if (o == nullptr) {
    *error = JDWP::ERR_INVALID_OBJECT;
    return nullptr;
  }
  if (!o->IsClass()) {
    *error = JDWP::ERR_INVALID_CLASS;
    return nullptr;
  }
  *error = JDWP::ERR_NONE;
  return o->AsClass();
}

static Thread* DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id,
                            JDWP::JdwpError* error)
    SHARED_REQUIRES(Locks::mutator_lock_)
    REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) {
  mirror::Object* thread_peer = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error);
  if (thread_peer == nullptr) {
    // This isn't even an object.
    *error = JDWP::ERR_INVALID_OBJECT;
    return nullptr;
  }

  mirror::Class* java_lang_Thread = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
  if (!java_lang_Thread->IsAssignableFrom(thread_peer->GetClass())) {
    // This isn't a thread.
    *error = JDWP::ERR_INVALID_THREAD;
    return nullptr;
  }

  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
  Thread* thread = Thread::FromManagedThread(soa, thread_peer);
  // If thread is null then this a java.lang.Thread without a Thread*. Must be a un-started or a
  // zombie.
  *error = (thread == nullptr) ? JDWP::ERR_THREAD_NOT_ALIVE : JDWP::ERR_NONE;
  return thread;
}

static JDWP::JdwpTag BasicTagFromDescriptor(const char* descriptor) {
  // JDWP deliberately uses the descriptor characters' ASCII values for its enum.
  // Note that by "basic" we mean that we don't get more specific than JT_OBJECT.
  return static_cast<JDWP::JdwpTag>(descriptor[0]);
}

static JDWP::JdwpTag BasicTagFromClass(mirror::Class* klass)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  std::string temp;
  const char* descriptor = klass->GetDescriptor(&temp);
  return BasicTagFromDescriptor(descriptor);
}

static JDWP::JdwpTag TagFromClass(const ScopedObjectAccessUnchecked& soa, mirror::Class* c)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  CHECK(c != nullptr);
  if (c->IsArrayClass()) {
    return JDWP::JT_ARRAY;
  }
  if (c->IsStringClass()) {
    return JDWP::JT_STRING;
  }
  if (c->IsClassClass()) {
    return JDWP::JT_CLASS_OBJECT;
  }
  {
    mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
    if (thread_class->IsAssignableFrom(c)) {
      return JDWP::JT_THREAD;
    }
  }
  {
    mirror::Class* thread_group_class =
        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
    if (thread_group_class->IsAssignableFrom(c)) {
      return JDWP::JT_THREAD_GROUP;
    }
  }
  {
    mirror::Class* class_loader_class =
        soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
    if (class_loader_class->IsAssignableFrom(c)) {
      return JDWP::JT_CLASS_LOADER;
    }
  }
  return JDWP::JT_OBJECT;
}

/*
 * Objects declared to hold Object might actually hold a more specific
 * type.  The debugger may take a special interest in these (e.g. it
 * wants to display the contents of Strings), so we want to return an
 * appropriate tag.
 *
 * Null objects are tagged JT_OBJECT.
 */
JDWP::JdwpTag Dbg::TagFromObject(const ScopedObjectAccessUnchecked& soa, mirror::Object* o) {
  return (o == nullptr) ? JDWP::JT_OBJECT : TagFromClass(soa, o->GetClass());
}

static bool IsPrimitiveTag(JDWP::JdwpTag tag) {
  switch (tag) {
  case JDWP::JT_BOOLEAN:
  case JDWP::JT_BYTE:
  case JDWP::JT_CHAR:
  case JDWP::JT_FLOAT:
  case JDWP::JT_DOUBLE:
  case JDWP::JT_INT:
  case JDWP::JT_LONG:
  case JDWP::JT_SHORT:
  case JDWP::JT_VOID:
    return true;
  default:
    return false;
  }
}

void Dbg::StartJdwp() {
  if (!gJdwpAllowed || !IsJdwpConfigured()) {
    // No JDWP for you!
    return;
  }

  CHECK(gRegistry == nullptr);
  gRegistry = new ObjectRegistry;

  // Init JDWP if the debugger is enabled. This may connect out to a
  // debugger, passively listen for a debugger, or block waiting for a
  // debugger.
  gJdwpState = JDWP::JdwpState::Create(&gJdwpOptions);
  if (gJdwpState == nullptr) {
    // We probably failed because some other process has the port already, which means that
    // if we don't abort the user is likely to think they're talking to us when they're actually
    // talking to that other process.
    LOG(FATAL) << "Debugger thread failed to initialize";
  }

  // If a debugger has already attached, send the "welcome" message.
  // This may cause us to suspend all threads.
  if (gJdwpState->IsActive()) {
    ScopedObjectAccess soa(Thread::Current());
    gJdwpState->PostVMStart();
  }
}

void Dbg::StopJdwp() {
  // Post VM_DEATH event before the JDWP connection is closed (either by the JDWP thread or the
  // destruction of gJdwpState).
  if (gJdwpState != nullptr && gJdwpState->IsActive()) {
    gJdwpState->PostVMDeath();
  }
  // Prevent the JDWP thread from processing JDWP incoming packets after we close the connection.
  Dispose();
  delete gJdwpState;
  gJdwpState = nullptr;
  delete gRegistry;
  gRegistry = nullptr;
}

void Dbg::GcDidFinish() {
  if (gDdmHpifWhen != HPIF_WHEN_NEVER) {
    ScopedObjectAccess soa(Thread::Current());
    VLOG(jdwp) << "Sending heap info to DDM";
    DdmSendHeapInfo(gDdmHpifWhen);
  }
  if (gDdmHpsgWhen != HPSG_WHEN_NEVER) {
    ScopedObjectAccess soa(Thread::Current());
    VLOG(jdwp) << "Dumping heap to DDM";
    DdmSendHeapSegments(false);
  }
  if (gDdmNhsgWhen != HPSG_WHEN_NEVER) {
    ScopedObjectAccess soa(Thread::Current());
    VLOG(jdwp) << "Dumping native heap to DDM";
    DdmSendHeapSegments(true);
  }
}

void Dbg::SetJdwpAllowed(bool allowed) {
  gJdwpAllowed = allowed;
}

DebugInvokeReq* Dbg::GetInvokeReq() {
  return Thread::Current()->GetInvokeReq();
}

Thread* Dbg::GetDebugThread() {
  return (gJdwpState != nullptr) ? gJdwpState->GetDebugThread() : nullptr;
}

void Dbg::ClearWaitForEventThread() {
  gJdwpState->ReleaseJdwpTokenForEvent();
}

void Dbg::Connected() {
  CHECK(!gDebuggerConnected);
  VLOG(jdwp) << "JDWP has attached";
  gDebuggerConnected = true;
  gDisposed = false;
}

bool Dbg::RequiresDeoptimization() {
  // We don't need deoptimization if everything runs with interpreter after
  // enabling -Xint mode.
  return !Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly();
}

void Dbg::GoActive() {
  // Enable all debugging features, including scans for breakpoints.
  // This is a no-op if we're already active.
  // Only called from the JDWP handler thread.
  if (IsDebuggerActive()) {
    return;
  }

  {
    // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected?
    ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
    CHECK_EQ(gBreakpoints.size(), 0U);
  }

  {
    MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
    CHECK_EQ(deoptimization_requests_.size(), 0U);
    CHECK_EQ(full_deoptimization_event_count_, 0U);
    CHECK_EQ(dex_pc_change_event_ref_count_, 0U);
    CHECK_EQ(method_enter_event_ref_count_, 0U);
    CHECK_EQ(method_exit_event_ref_count_, 0U);
    CHECK_EQ(field_read_event_ref_count_, 0U);
    CHECK_EQ(field_write_event_ref_count_, 0U);
    CHECK_EQ(exception_catch_event_ref_count_, 0U);
  }

  Runtime* runtime = Runtime::Current();
  runtime->GetThreadList()->SuspendAll(__FUNCTION__);
  Thread* self = Thread::Current();
  ThreadState old_state = self->SetStateUnsafe(kRunnable);
  CHECK_NE(old_state, kRunnable);
  if (RequiresDeoptimization()) {
    runtime->GetInstrumentation()->EnableDeoptimization();
  }
  instrumentation_events_ = 0;
  gDebuggerActive = true;
  CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
  runtime->GetThreadList()->ResumeAll();

  LOG(INFO) << "Debugger is active";
}

void Dbg::Disconnected() {
  CHECK(gDebuggerConnected);

  LOG(INFO) << "Debugger is no longer active";

  // Suspend all threads and exclusively acquire the mutator lock. Set the state of the thread
  // to kRunnable to avoid scoped object access transitions. Remove the debugger as a listener
  // and clear the object registry.
  Runtime* runtime = Runtime::Current();
  runtime->GetThreadList()->SuspendAll(__FUNCTION__);
  Thread* self = Thread::Current();
  ThreadState old_state = self->SetStateUnsafe(kRunnable);

  // Debugger may not be active at this point.
  if (IsDebuggerActive()) {
    {
      // Since we're going to disable deoptimization, we clear the deoptimization requests queue.
      // This prevents us from having any pending deoptimization request when the debugger attaches
      // to us again while no event has been requested yet.
      MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
      deoptimization_requests_.clear();
      full_deoptimization_event_count_ = 0U;
    }
    if (instrumentation_events_ != 0) {
      runtime->GetInstrumentation()->RemoveListener(&gDebugInstrumentationListener,
                                                    instrumentation_events_);
      instrumentation_events_ = 0;
    }
    if (RequiresDeoptimization()) {
      runtime->GetInstrumentation()->DisableDeoptimization(kDbgInstrumentationKey);
    }
    gDebuggerActive = false;
  }
  CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
  runtime->GetThreadList()->ResumeAll();

  {
    ScopedObjectAccess soa(self);
    gRegistry->Clear();
  }

  gDebuggerConnected = false;
}

void Dbg::ConfigureJdwp(const JDWP::JdwpOptions& jdwp_options) {
  CHECK_NE(jdwp_options.transport, JDWP::kJdwpTransportUnknown);
  gJdwpOptions = jdwp_options;
  gJdwpConfigured = true;
}

bool Dbg::IsJdwpConfigured() {
  return gJdwpConfigured;
}

int64_t Dbg::LastDebuggerActivity() {
  return gJdwpState->LastDebuggerActivity();
}

void Dbg::UndoDebuggerSuspensions() {
  Runtime::Current()->GetThreadList()->UndoDebuggerSuspensions();
}

std::string Dbg::GetClassName(JDWP::RefTypeId class_id) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id, &error);
  if (o == nullptr) {
    if (error == JDWP::ERR_NONE) {
      return "null";
    } else {
      return StringPrintf("invalid object %p", reinterpret_cast<void*>(class_id));
    }
  }
  if (!o->IsClass()) {
    return StringPrintf("non-class %p", o);  // This is only used for debugging output anyway.
  }
  return GetClassName(o->AsClass());
}

std::string Dbg::GetClassName(mirror::Class* klass) {
  if (klass == nullptr) {
    return "null";
  }
  std::string temp;
  return DescriptorToName(klass->GetDescriptor(&temp));
}

JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) {
  JDWP::JdwpError status;
  mirror::Class* c = DecodeClass(id, &status);
  if (c == nullptr) {
    *class_object_id = 0;
    return status;
  }
  *class_object_id = gRegistry->Add(c);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) {
  JDWP::JdwpError status;
  mirror::Class* c = DecodeClass(id, &status);
  if (c == nullptr) {
    *superclass_id = 0;
    return status;
  }
  if (c->IsInterface()) {
    // http://code.google.com/p/android/issues/detail?id=20856
    *superclass_id = 0;
  } else {
    *superclass_id = gRegistry->Add(c->GetSuperClass());
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error);
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  expandBufAddObjectId(pReply, gRegistry->Add(o->GetClass()->GetClassLoader()));
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(id, &error);
  if (c == nullptr) {
    return error;
  }

  uint32_t access_flags = c->GetAccessFlags() & kAccJavaFlagsMask;

  // Set ACC_SUPER. Dex files don't contain this flag but only classes are supposed to have it set,
  // not interfaces.
  // Class.getModifiers doesn't return it, but JDWP does, so we set it here.
  if ((access_flags & kAccInterface) == 0) {
    access_flags |= kAccSuper;
  }

  expandBufAdd4BE(pReply, access_flags);

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }

  // Ensure all threads are suspended while we read objects' lock words.
  Thread* self = Thread::Current();
  CHECK_EQ(self->GetState(), kRunnable);
  self->TransitionFromRunnableToSuspended(kSuspended);
  Runtime::Current()->GetThreadList()->SuspendAll(__FUNCTION__);

  MonitorInfo monitor_info(o);

  Runtime::Current()->GetThreadList()->ResumeAll();
  self->TransitionFromSuspendedToRunnable();

  if (monitor_info.owner_ != nullptr) {
    expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeer()));
  } else {
    expandBufAddObjectId(reply, gRegistry->Add(nullptr));
  }
  expandBufAdd4BE(reply, monitor_info.entry_count_);
  expandBufAdd4BE(reply, monitor_info.waiters_.size());
  for (size_t i = 0; i < monitor_info.waiters_.size(); ++i) {
    expandBufAddObjectId(reply, gRegistry->Add(monitor_info.waiters_[i]->GetPeer()));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetOwnedMonitors(JDWP::ObjectId thread_id,
                                      std::vector<JDWP::ObjectId>* monitors,
                                      std::vector<uint32_t>* stack_depths) {
  struct OwnedMonitorVisitor : public StackVisitor {
    OwnedMonitorVisitor(Thread* thread, Context* context,
                        std::vector<JDWP::ObjectId>* monitor_vector,
                        std::vector<uint32_t>* stack_depth_vector)
        SHARED_REQUIRES(Locks::mutator_lock_)
      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
        current_stack_depth(0),
        monitors(monitor_vector),
        stack_depths(stack_depth_vector) {}

    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
    // annotalysis.
    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
      if (!GetMethod()->IsRuntimeMethod()) {
        Monitor::VisitLocks(this, AppendOwnedMonitors, this);
        ++current_stack_depth;
      }
      return true;
    }

    static void AppendOwnedMonitors(mirror::Object* owned_monitor, void* arg)
        SHARED_REQUIRES(Locks::mutator_lock_) {
      OwnedMonitorVisitor* visitor = reinterpret_cast<OwnedMonitorVisitor*>(arg);
      visitor->monitors->push_back(gRegistry->Add(owned_monitor));
      visitor->stack_depths->push_back(visitor->current_stack_depth);
    }

    size_t current_stack_depth;
    std::vector<JDWP::ObjectId>* const monitors;
    std::vector<uint32_t>* const stack_depths;
  };

  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (thread == nullptr) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  std::unique_ptr<Context> context(Context::Create());
  OwnedMonitorVisitor visitor(thread, context.get(), monitors, stack_depths);
  visitor.WalkStack();
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id,
                                         JDWP::ObjectId* contended_monitor) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  *contended_monitor = 0;
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (thread == nullptr) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  mirror::Object* contended_monitor_obj = Monitor::GetContendedMonitor(thread);
  // Add() requires the thread_list_lock_ not held to avoid the lock
  // level violation.
  *contended_monitor = gRegistry->Add(contended_monitor_obj);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
                                       std::vector<uint64_t>* counts) {
  gc::Heap* heap = Runtime::Current()->GetHeap();
  heap->CollectGarbage(false);
  std::vector<mirror::Class*> classes;
  counts->clear();
  for (size_t i = 0; i < class_ids.size(); ++i) {
    JDWP::JdwpError error;
    mirror::Class* c = DecodeClass(class_ids[i], &error);
    if (c == nullptr) {
      return error;
    }
    classes.push_back(c);
    counts->push_back(0);
  }
  heap->CountInstances(classes, false, &(*counts)[0]);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
                                  std::vector<JDWP::ObjectId>* instances) {
  gc::Heap* heap = Runtime::Current()->GetHeap();
  // We only want reachable instances, so do a GC.
  heap->CollectGarbage(false);
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }
  std::vector<mirror::Object*> raw_instances;
  Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances);
  for (size_t i = 0; i < raw_instances.size(); ++i) {
    instances->push_back(gRegistry->Add(raw_instances[i]));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
                                         std::vector<JDWP::ObjectId>* referring_objects) {
  gc::Heap* heap = Runtime::Current()->GetHeap();
  heap->CollectGarbage(false);
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  std::vector<mirror::Object*> raw_instances;
  heap->GetReferringObjects(o, max_count, raw_instances);
  for (size_t i = 0; i < raw_instances.size(); ++i) {
    referring_objects->push_back(gRegistry->Add(raw_instances[i]));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  gRegistry->DisableCollection(object_id);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI
  // also ignores these cases and never return an error. However it's not obvious why this command
  // should behave differently from DisableCollection and IsCollected commands. So let's be more
  // strict and return an error if this happens.
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  gRegistry->EnableCollection(object_id);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool* is_collected) {
  *is_collected = true;
  if (object_id == 0) {
    // Null object id is invalid.
    return JDWP::ERR_INVALID_OBJECT;
  }
  // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However
  // the RI seems to ignore this and assume object has been collected.
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (o != nullptr) {
    *is_collected = gRegistry->IsCollected(object_id);
  }
  return JDWP::ERR_NONE;
}

void Dbg::DisposeObject(JDWP::ObjectId object_id, uint32_t reference_count) {
  gRegistry->DisposeObject(object_id, reference_count);
}

JDWP::JdwpTypeTag Dbg::GetTypeTag(mirror::Class* klass) {
  DCHECK(klass != nullptr);
  if (klass->IsArrayClass()) {
    return JDWP::TT_ARRAY;
  } else if (klass->IsInterface()) {
    return JDWP::TT_INTERFACE;
  } else {
    return JDWP::TT_CLASS;
  }
}

JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }

  JDWP::JdwpTypeTag type_tag = GetTypeTag(c);
  expandBufAdd1(pReply, type_tag);
  expandBufAddRefTypeId(pReply, class_id);
  return JDWP::ERR_NONE;
}

// Get the complete list of reference classes (i.e. all classes except
// the primitive types).
// Returns a newly-allocated buffer full of RefTypeId values.
class ClassListCreator : public ClassVisitor {
 public:
  explicit ClassListCreator(std::vector<JDWP::RefTypeId>* classes) : classes_(classes) {}

  bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    if (!c->IsPrimitive()) {
      classes_->push_back(Dbg::GetObjectRegistry()->AddRefType(c));
    }
    return true;
  }

 private:
  std::vector<JDWP::RefTypeId>* const classes_;
};

void Dbg::GetClassList(std::vector<JDWP::RefTypeId>* classes) {
  ClassListCreator clc(classes);
  Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&clc);
}

JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
                                  uint32_t* pStatus, std::string* pDescriptor) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }

  if (c->IsArrayClass()) {
    *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
    *pTypeTag = JDWP::TT_ARRAY;
  } else {
    if (c->IsErroneous()) {
      *pStatus = JDWP::CS_ERROR;
    } else {
      *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED | JDWP::CS_INITIALIZED;
    }
    *pTypeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
  }

  if (pDescriptor != nullptr) {
    std::string temp;
    *pDescriptor = c->GetDescriptor(&temp);
  }
  return JDWP::ERR_NONE;
}

void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>* ids) {
  std::vector<mirror::Class*> classes;
  Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes);
  ids->clear();
  for (size_t i = 0; i < classes.size(); ++i) {
    ids->push_back(gRegistry->Add(classes[i]));
  }
}

JDWP::JdwpError Dbg::GetReferenceType(JDWP::ObjectId object_id, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (o == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }

  JDWP::JdwpTypeTag type_tag = GetTypeTag(o->GetClass());
  JDWP::RefTypeId type_id = gRegistry->AddRefType(o->GetClass());

  expandBufAdd1(pReply, type_tag);
  expandBufAddRefTypeId(pReply, type_id);

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }
  std::string temp;
  *signature = c->GetDescriptor(&temp);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }
  const char* source_file = c->GetSourceFile();
  if (source_file == nullptr) {
    return JDWP::ERR_ABSENT_INFORMATION;
  }
  *result = source_file;
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
  if (error != JDWP::ERR_NONE) {
    *tag = JDWP::JT_VOID;
    return error;
  }
  *tag = TagFromObject(soa, o);
  return JDWP::ERR_NONE;
}

size_t Dbg::GetTagWidth(JDWP::JdwpTag tag) {
  switch (tag) {
  case JDWP::JT_VOID:
    return 0;
  case JDWP::JT_BYTE:
  case JDWP::JT_BOOLEAN:
    return 1;
  case JDWP::JT_CHAR:
  case JDWP::JT_SHORT:
    return 2;
  case JDWP::JT_FLOAT:
  case JDWP::JT_INT:
    return 4;
  case JDWP::JT_ARRAY:
  case JDWP::JT_OBJECT:
  case JDWP::JT_STRING:
  case JDWP::JT_THREAD:
  case JDWP::JT_THREAD_GROUP:
  case JDWP::JT_CLASS_LOADER:
  case JDWP::JT_CLASS_OBJECT:
    return sizeof(JDWP::ObjectId);
  case JDWP::JT_DOUBLE:
  case JDWP::JT_LONG:
    return 8;
  default:
    LOG(FATAL) << "Unknown tag " << tag;
    return -1;
  }
}

JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int32_t* length) {
  JDWP::JdwpError error;
  mirror::Array* a = DecodeNonNullArray(array_id, &error);
  if (a == nullptr) {
    return error;
  }
  *length = a->GetLength();
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Array* a = DecodeNonNullArray(array_id, &error);
  if (a == nullptr) {
    return error;
  }

  if (offset < 0 || count < 0 || offset > a->GetLength() || a->GetLength() - offset < count) {
    LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
    return JDWP::ERR_INVALID_LENGTH;
  }
  JDWP::JdwpTag element_tag = BasicTagFromClass(a->GetClass()->GetComponentType());
  expandBufAdd1(pReply, element_tag);
  expandBufAdd4BE(pReply, count);

  if (IsPrimitiveTag(element_tag)) {
    size_t width = GetTagWidth(element_tag);
    uint8_t* dst = expandBufAddSpace(pReply, count * width);
    if (width == 8) {
      const uint64_t* src8 = reinterpret_cast<uint64_t*>(a->GetRawData(sizeof(uint64_t), 0));
      for (int i = 0; i < count; ++i) JDWP::Write8BE(&dst, src8[offset + i]);
    } else if (width == 4) {
      const uint32_t* src4 = reinterpret_cast<uint32_t*>(a->GetRawData(sizeof(uint32_t), 0));
      for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[offset + i]);
    } else if (width == 2) {
      const uint16_t* src2 = reinterpret_cast<uint16_t*>(a->GetRawData(sizeof(uint16_t), 0));
      for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[offset + i]);
    } else {
      const uint8_t* src = reinterpret_cast<uint8_t*>(a->GetRawData(sizeof(uint8_t), 0));
      memcpy(dst, &src[offset * width], count * width);
    }
  } else {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>();
    for (int i = 0; i < count; ++i) {
      mirror::Object* element = oa->Get(offset + i);
      JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element)
                                                        : element_tag;
      expandBufAdd1(pReply, specific_tag);
      expandBufAddObjectId(pReply, gRegistry->Add(element));
    }
  }

  return JDWP::ERR_NONE;
}

template <typename T>
static void CopyArrayData(mirror::Array* a, JDWP::Request* src, int offset, int count)
    NO_THREAD_SAFETY_ANALYSIS {
  // TODO: fix when annotalysis correctly handles non-member functions.
  DCHECK(a->GetClass()->IsPrimitiveArray());

  T* dst = reinterpret_cast<T*>(a->GetRawData(sizeof(T), offset));
  for (int i = 0; i < count; ++i) {
    *dst++ = src->ReadValue(sizeof(T));
  }
}

JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
                                      JDWP::Request* request) {
  JDWP::JdwpError error;
  mirror::Array* dst = DecodeNonNullArray(array_id, &error);
  if (dst == nullptr) {
    return error;
  }

  if (offset < 0 || count < 0 || offset > dst->GetLength() || dst->GetLength() - offset < count) {
    LOG(WARNING) << __FUNCTION__ << " access out of bounds: offset=" << offset << "; count=" << count;
    return JDWP::ERR_INVALID_LENGTH;
  }
  JDWP::JdwpTag element_tag = BasicTagFromClass(dst->GetClass()->GetComponentType());

  if (IsPrimitiveTag(element_tag)) {
    size_t width = GetTagWidth(element_tag);
    if (width == 8) {
      CopyArrayData<uint64_t>(dst, request, offset, count);
    } else if (width == 4) {
      CopyArrayData<uint32_t>(dst, request, offset, count);
    } else if (width == 2) {
      CopyArrayData<uint16_t>(dst, request, offset, count);
    } else {
      CopyArrayData<uint8_t>(dst, request, offset, count);
    }
  } else {
    mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>();
    for (int i = 0; i < count; ++i) {
      JDWP::ObjectId id = request->ReadObjectId();
      mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error);
      if (error != JDWP::ERR_NONE) {
        return error;
      }
      oa->Set<false>(offset + i, o);
    }
  }

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::CreateString(const std::string& str, JDWP::ObjectId* new_string_id) {
  Thread* self = Thread::Current();
  mirror::String* new_string = mirror::String::AllocFromModifiedUtf8(self, str.c_str());
  if (new_string == nullptr) {
    DCHECK(self->IsExceptionPending());
    self->ClearException();
    LOG(ERROR) << "Could not allocate string";
    *new_string_id = 0;
    return JDWP::ERR_OUT_OF_MEMORY;
  }
  *new_string_id = gRegistry->Add(new_string);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object_id) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    *new_object_id = 0;
    return error;
  }
  Thread* self = Thread::Current();
  mirror::Object* new_object = c->AllocObject(self);
  if (new_object == nullptr) {
    DCHECK(self->IsExceptionPending());
    self->ClearException();
    LOG(ERROR) << "Could not allocate object of type " << PrettyDescriptor(c);
    *new_object_id = 0;
    return JDWP::ERR_OUT_OF_MEMORY;
  }
  *new_object_id = gRegistry->Add(new_object);
  return JDWP::ERR_NONE;
}

/*
 * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]".
 */
JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length,
                                       JDWP::ObjectId* new_array_id) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(array_class_id, &error);
  if (c == nullptr) {
    *new_array_id = 0;
    return error;
  }
  Thread* self = Thread::Current();
  gc::Heap* heap = Runtime::Current()->GetHeap();
  mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length,
                                                        c->GetComponentSizeShift(),
                                                        heap->GetCurrentAllocator());
  if (new_array == nullptr) {
    DCHECK(self->IsExceptionPending());
    self->ClearException();
    LOG(ERROR) << "Could not allocate array of type " << PrettyDescriptor(c);
    *new_array_id = 0;
    return JDWP::ERR_OUT_OF_MEMORY;
  }
  *new_array_id = gRegistry->Add(new_array);
  return JDWP::ERR_NONE;
}

JDWP::FieldId Dbg::ToFieldId(const ArtField* f) {
  return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f));
}

static JDWP::MethodId ToMethodId(const ArtMethod* m)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m));
}

static ArtField* FromFieldId(JDWP::FieldId fid)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid));
}

static ArtMethod* FromMethodId(JDWP::MethodId mid)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(mid));
}

bool Dbg::MatchThread(JDWP::ObjectId expected_thread_id, Thread* event_thread) {
  CHECK(event_thread != nullptr);
  JDWP::JdwpError error;
  mirror::Object* expected_thread_peer = gRegistry->Get<mirror::Object*>(
      expected_thread_id, &error);
  return expected_thread_peer == event_thread->GetPeer();
}

bool Dbg::MatchLocation(const JDWP::JdwpLocation& expected_location,
                        const JDWP::EventLocation& event_location) {
  if (expected_location.dex_pc != event_location.dex_pc) {
    return false;
  }
  ArtMethod* m = FromMethodId(expected_location.method_id);
  return m == event_location.method;
}

bool Dbg::MatchType(mirror::Class* event_class, JDWP::RefTypeId class_id) {
  if (event_class == nullptr) {
    return false;
  }
  JDWP::JdwpError error;
  mirror::Class* expected_class = DecodeClass(class_id, &error);
  CHECK(expected_class != nullptr);
  return expected_class->IsAssignableFrom(event_class);
}

bool Dbg::MatchField(JDWP::RefTypeId expected_type_id, JDWP::FieldId expected_field_id,
                     ArtField* event_field) {
  ArtField* expected_field = FromFieldId(expected_field_id);
  if (expected_field != event_field) {
    return false;
  }
  return Dbg::MatchType(event_field->GetDeclaringClass(), expected_type_id);
}

bool Dbg::MatchInstance(JDWP::ObjectId expected_instance_id, mirror::Object* event_instance) {
  JDWP::JdwpError error;
  mirror::Object* modifier_instance = gRegistry->Get<mirror::Object*>(expected_instance_id, &error);
  return modifier_instance == event_instance;
}

void Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, ArtMethod* m, uint32_t dex_pc) {
  if (m == nullptr) {
    memset(location, 0, sizeof(*location));
  } else {
    mirror::Class* c = m->GetDeclaringClass();
    location->type_tag = GetTypeTag(c);
    location->class_id = gRegistry->AddRefType(c);
    location->method_id = ToMethodId(m);
    location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint64_t>(-1) : dex_pc;
  }
}

std::string Dbg::GetMethodName(JDWP::MethodId method_id) {
  ArtMethod* m = FromMethodId(method_id);
  if (m == nullptr) {
    return "null";
  }
  return m->GetInterfaceMethodIfProxy(sizeof(void*))->GetName();
}

std::string Dbg::GetFieldName(JDWP::FieldId field_id) {
  ArtField* f = FromFieldId(field_id);
  if (f == nullptr) {
    return "null";
  }
  return f->GetName();
}

/*
 * Augment the access flags for synthetic methods and fields by setting
 * the (as described by the spec) "0xf0000000 bit".  Also, strip out any
 * flags not specified by the Java programming language.
 */
static uint32_t MangleAccessFlags(uint32_t accessFlags) {
  accessFlags &= kAccJavaFlagsMask;
  if ((accessFlags & kAccSynthetic) != 0) {
    accessFlags |= 0xf0000000;
  }
  return accessFlags;
}

/*
 * Circularly shifts registers so that arguments come first. Debuggers
 * expect slots to begin with arguments, but dex code places them at
 * the end.
 */
static uint16_t MangleSlot(uint16_t slot, ArtMethod* m)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  const DexFile::CodeItem* code_item = m->GetCodeItem();
  if (code_item == nullptr) {
    // We should not get here for a method without code (native, proxy or abstract). Log it and
    // return the slot as is since all registers are arguments.
    LOG(WARNING) << "Trying to mangle slot for method without code " << PrettyMethod(m);
    return slot;
  }
  uint16_t ins_size = code_item->ins_size_;
  uint16_t locals_size = code_item->registers_size_ - ins_size;
  if (slot >= locals_size) {
    return slot - locals_size;
  } else {
    return slot + ins_size;
  }
}

/*
 * Circularly shifts registers so that arguments come last. Reverts
 * slots to dex style argument placement.
 */
static uint16_t DemangleSlot(uint16_t slot, ArtMethod* m, JDWP::JdwpError* error)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  const DexFile::CodeItem* code_item = m->GetCodeItem();
  if (code_item == nullptr) {
    // We should not get here for a method without code (native, proxy or abstract). Log it and
    // return the slot as is since all registers are arguments.
    LOG(WARNING) << "Trying to demangle slot for method without code " << PrettyMethod(m);
    uint16_t vreg_count = ArtMethod::NumArgRegisters(m->GetShorty());
    if (slot < vreg_count) {
      *error = JDWP::ERR_NONE;
      return slot;
    }
  } else {
    if (slot < code_item->registers_size_) {
      uint16_t ins_size = code_item->ins_size_;
      uint16_t locals_size = code_item->registers_size_ - ins_size;
      *error = JDWP::ERR_NONE;
      return (slot < ins_size) ? slot + locals_size : slot - ins_size;
    }
  }

  // Slot is invalid in the method.
  LOG(ERROR) << "Invalid local slot " << slot << " for method " << PrettyMethod(m);
  *error = JDWP::ERR_INVALID_SLOT;
  return DexFile::kDexNoIndex16;
}

JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic,
                                          JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }

  size_t instance_field_count = c->NumInstanceFields();
  size_t static_field_count = c->NumStaticFields();

  expandBufAdd4BE(pReply, instance_field_count + static_field_count);

  for (size_t i = 0; i < instance_field_count + static_field_count; ++i) {
    ArtField* f = (i < instance_field_count) ? c->GetInstanceField(i) :
        c->GetStaticField(i - instance_field_count);
    expandBufAddFieldId(pReply, ToFieldId(f));
    expandBufAddUtf8String(pReply, f->GetName());
    expandBufAddUtf8String(pReply, f->GetTypeDescriptor());
    if (with_generic) {
      static const char genericSignature[1] = "";
      expandBufAddUtf8String(pReply, genericSignature);
    }
    expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags()));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic,
                                           JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(class_id, &error);
  if (c == nullptr) {
    return error;
  }

  size_t direct_method_count = c->NumDirectMethods();
  size_t virtual_method_count = c->NumVirtualMethods();

  expandBufAdd4BE(pReply, direct_method_count + virtual_method_count);

  auto* cl = Runtime::Current()->GetClassLinker();
  auto ptr_size = cl->GetImagePointerSize();
  for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) {
    ArtMethod* m = i < direct_method_count ?
        c->GetDirectMethod(i, ptr_size) : c->GetVirtualMethod(i - direct_method_count, ptr_size);
    expandBufAddMethodId(pReply, ToMethodId(m));
    expandBufAddUtf8String(pReply, m->GetInterfaceMethodIfProxy(sizeof(void*))->GetName());
    expandBufAddUtf8String(pReply,
                           m->GetInterfaceMethodIfProxy(sizeof(void*))->GetSignature().ToString());
    if (with_generic) {
      const char* generic_signature = "";
      expandBufAddUtf8String(pReply, generic_signature);
    }
    expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags()));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError error;
  Thread* self = Thread::Current();
  StackHandleScope<1> hs(self);
  Handle<mirror::Class> c(hs.NewHandle(DecodeClass(class_id, &error)));
  if (c.Get() == nullptr) {
    return error;
  }
  size_t interface_count = c->NumDirectInterfaces();
  expandBufAdd4BE(pReply, interface_count);
  for (size_t i = 0; i < interface_count; ++i) {
    expandBufAddRefTypeId(pReply,
                          gRegistry->AddRefType(mirror::Class::GetDirectInterface(self, c, i)));
  }
  return JDWP::ERR_NONE;
}

void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId method_id, JDWP::ExpandBuf* pReply) {
  struct DebugCallbackContext {
    int numItems;
    JDWP::ExpandBuf* pReply;

    static bool Callback(void* context, uint32_t address, uint32_t line_number) {
      DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
      expandBufAdd8BE(pContext->pReply, address);
      expandBufAdd4BE(pContext->pReply, line_number);
      pContext->numItems++;
      return false;
    }
  };
  ArtMethod* m = FromMethodId(method_id);
  const DexFile::CodeItem* code_item = m->GetCodeItem();
  uint64_t start, end;
  if (code_item == nullptr) {
    DCHECK(m->IsNative() || m->IsProxyMethod());
    start = -1;
    end = -1;
  } else {
    start = 0;
    // Return the index of the last instruction
    end = code_item->insns_size_in_code_units_ - 1;
  }

  expandBufAdd8BE(pReply, start);
  expandBufAdd8BE(pReply, end);

  // Add numLines later
  size_t numLinesOffset = expandBufGetLength(pReply);
  expandBufAdd4BE(pReply, 0);

  DebugCallbackContext context;
  context.numItems = 0;
  context.pReply = pReply;

  if (code_item != nullptr) {
    m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
                                     DebugCallbackContext::Callback, nullptr, &context);
  }

  JDWP::Set4BE(expandBufGetBuffer(pReply) + numLinesOffset, context.numItems);
}

void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic,
                              JDWP::ExpandBuf* pReply) {
  struct DebugCallbackContext {
    ArtMethod* method;
    JDWP::ExpandBuf* pReply;
    size_t variable_count;
    bool with_generic;

    static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress,
                         const char* name, const char* descriptor, const char* signature)
        SHARED_REQUIRES(Locks::mutator_lock_) {
      DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);

      VLOG(jdwp) << StringPrintf("    %2zd: %d(%d) '%s' '%s' '%s' actual slot=%d mangled slot=%d",
                                 pContext->variable_count, startAddress, endAddress - startAddress,
                                 name, descriptor, signature, slot,
                                 MangleSlot(slot, pContext->method));

      slot = MangleSlot(slot, pContext->method);

      expandBufAdd8BE(pContext->pReply, startAddress);
      expandBufAddUtf8String(pContext->pReply, name);
      expandBufAddUtf8String(pContext->pReply, descriptor);
      if (pContext->with_generic) {
        expandBufAddUtf8String(pContext->pReply, signature);
      }
      expandBufAdd4BE(pContext->pReply, endAddress - startAddress);
      expandBufAdd4BE(pContext->pReply, slot);

      ++pContext->variable_count;
    }
  };
  ArtMethod* m = FromMethodId(method_id);

  // arg_count considers doubles and longs to take 2 units.
  // variable_count considers everything to take 1 unit.
  std::string shorty(m->GetShorty());
  expandBufAdd4BE(pReply, ArtMethod::NumArgRegisters(shorty));

  // We don't know the total number of variables yet, so leave a blank and update it later.
  size_t variable_count_offset = expandBufGetLength(pReply);
  expandBufAdd4BE(pReply, 0);

  DebugCallbackContext context;
  context.method = m;
  context.pReply = pReply;
  context.variable_count = 0;
  context.with_generic = with_generic;

  const DexFile::CodeItem* code_item = m->GetCodeItem();
  if (code_item != nullptr) {
    m->GetDexFile()->DecodeDebugInfo(
        code_item, m->IsStatic(), m->GetDexMethodIndex(), nullptr, DebugCallbackContext::Callback,
        &context);
  }

  JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
}

void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
                                  JDWP::ExpandBuf* pReply) {
  ArtMethod* m = FromMethodId(method_id);
  JDWP::JdwpTag tag = BasicTagFromDescriptor(m->GetShorty());
  OutputJValue(tag, return_value, pReply);
}

void Dbg::OutputFieldValue(JDWP::FieldId field_id, const JValue* field_value,
                           JDWP::ExpandBuf* pReply) {
  ArtField* f = FromFieldId(field_id);
  JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
  OutputJValue(tag, field_value, pReply);
}

JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id,
                                  std::vector<uint8_t>* bytecodes) {
  ArtMethod* m = FromMethodId(method_id);
  if (m == nullptr) {
    return JDWP::ERR_INVALID_METHODID;
  }
  const DexFile::CodeItem* code_item = m->GetCodeItem();
  size_t byte_count = code_item->insns_size_in_code_units_ * 2;
  const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_);
  const uint8_t* end = begin + byte_count;
  for (const uint8_t* p = begin; p != end; ++p) {
    bytecodes->push_back(*p);
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId field_id) {
  return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor());
}

JDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId field_id) {
  return BasicTagFromDescriptor(FromFieldId(field_id)->GetTypeDescriptor());
}

static JValue GetArtFieldValue(ArtField* f, mirror::Object* o)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  Primitive::Type fieldType = f->GetTypeAsPrimitiveType();
  JValue field_value;
  switch (fieldType) {
    case Primitive::kPrimBoolean:
      field_value.SetZ(f->GetBoolean(o));
      return field_value;

    case Primitive::kPrimByte:
      field_value.SetB(f->GetByte(o));
      return field_value;

    case Primitive::kPrimChar:
      field_value.SetC(f->GetChar(o));
      return field_value;

    case Primitive::kPrimShort:
      field_value.SetS(f->GetShort(o));
      return field_value;

    case Primitive::kPrimInt:
    case Primitive::kPrimFloat:
      // Int and Float must be treated as 32-bit values in JDWP.
      field_value.SetI(f->GetInt(o));
      return field_value;

    case Primitive::kPrimLong:
    case Primitive::kPrimDouble:
      // Long and Double must be treated as 64-bit values in JDWP.
      field_value.SetJ(f->GetLong(o));
      return field_value;

    case Primitive::kPrimNot:
      field_value.SetL(f->GetObject(o));
      return field_value;

    case Primitive::kPrimVoid:
      LOG(FATAL) << "Attempt to read from field of type 'void'";
      UNREACHABLE();
  }
  LOG(FATAL) << "Attempt to read from field of unknown type";
  UNREACHABLE();
}

static JDWP::JdwpError GetFieldValueImpl(JDWP::RefTypeId ref_type_id, JDWP::ObjectId object_id,
                                         JDWP::FieldId field_id, JDWP::ExpandBuf* pReply,
                                         bool is_static)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  JDWP::JdwpError error;
  mirror::Class* c = DecodeClass(ref_type_id, &error);
  if (ref_type_id != 0 && c == nullptr) {
    return error;
  }

  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error);
  if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  ArtField* f = FromFieldId(field_id);

  mirror::Class* receiver_class = c;
  if (receiver_class == nullptr && o != nullptr) {
    receiver_class = o->GetClass();
  }
  // TODO: should we give up now if receiver_class is null?
  if (receiver_class != nullptr && !f->GetDeclaringClass()->IsAssignableFrom(receiver_class)) {
    LOG(INFO) << "ERR_INVALID_FIELDID: " << PrettyField(f) << " " << PrettyClass(receiver_class);
    return JDWP::ERR_INVALID_FIELDID;
  }

  // The RI only enforces the static/non-static mismatch in one direction.
  // TODO: should we change the tests and check both?
  if (is_static) {
    if (!f->IsStatic()) {
      return JDWP::ERR_INVALID_FIELDID;
    }
  } else {
    if (f->IsStatic()) {
      LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.GetValues"
                   << " on static field " << PrettyField(f);
    }
  }
  if (f->IsStatic()) {
    o = f->GetDeclaringClass();
  }

  JValue field_value(GetArtFieldValue(f, o));
  JDWP::JdwpTag tag = BasicTagFromDescriptor(f->GetTypeDescriptor());
  Dbg::OutputJValue(tag, &field_value, pReply);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id,
                                   JDWP::ExpandBuf* pReply) {
  return GetFieldValueImpl(0, object_id, field_id, pReply, false);
}

JDWP::JdwpError Dbg::GetStaticFieldValue(JDWP::RefTypeId ref_type_id, JDWP::FieldId field_id,
                                         JDWP::ExpandBuf* pReply) {
  return GetFieldValueImpl(ref_type_id, 0, field_id, pReply, true);
}

static JDWP::JdwpError SetArtFieldValue(ArtField* f, mirror::Object* o, uint64_t value, int width)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  Primitive::Type fieldType = f->GetTypeAsPrimitiveType();
  // Debugging only happens at runtime so we know we are not running in a transaction.
  static constexpr bool kNoTransactionMode = false;
  switch (fieldType) {
    case Primitive::kPrimBoolean:
      CHECK_EQ(width, 1);
      f->SetBoolean<kNoTransactionMode>(o, static_cast<uint8_t>(value));
      return JDWP::ERR_NONE;

    case Primitive::kPrimByte:
      CHECK_EQ(width, 1);
      f->SetByte<kNoTransactionMode>(o, static_cast<uint8_t>(value));
      return JDWP::ERR_NONE;

    case Primitive::kPrimChar:
      CHECK_EQ(width, 2);
      f->SetChar<kNoTransactionMode>(o, static_cast<uint16_t>(value));
      return JDWP::ERR_NONE;

    case Primitive::kPrimShort:
      CHECK_EQ(width, 2);
      f->SetShort<kNoTransactionMode>(o, static_cast<int16_t>(value));
      return JDWP::ERR_NONE;

    case Primitive::kPrimInt:
    case Primitive::kPrimFloat:
      CHECK_EQ(width, 4);
      // Int and Float must be treated as 32-bit values in JDWP.
      f->SetInt<kNoTransactionMode>(o, static_cast<int32_t>(value));
      return JDWP::ERR_NONE;

    case Primitive::kPrimLong:
    case Primitive::kPrimDouble:
      CHECK_EQ(width, 8);
      // Long and Double must be treated as 64-bit values in JDWP.
      f->SetLong<kNoTransactionMode>(o, value);
      return JDWP::ERR_NONE;

    case Primitive::kPrimNot: {
      JDWP::JdwpError error;
      mirror::Object* v = Dbg::GetObjectRegistry()->Get<mirror::Object*>(value, &error);
      if (error != JDWP::ERR_NONE) {
        return JDWP::ERR_INVALID_OBJECT;
      }
      if (v != nullptr) {
        mirror::Class* field_type;
        {
          StackHandleScope<2> hs(Thread::Current());
          HandleWrapper<mirror::Object> h_v(hs.NewHandleWrapper(&v));
          HandleWrapper<mirror::Object> h_o(hs.NewHandleWrapper(&o));
          field_type = f->GetType<true>();
        }
        if (!field_type->IsAssignableFrom(v->GetClass())) {
          return JDWP::ERR_INVALID_OBJECT;
        }
      }
      f->SetObject<kNoTransactionMode>(o, v);
      return JDWP::ERR_NONE;
    }

    case Primitive::kPrimVoid:
      LOG(FATAL) << "Attempt to write to field of type 'void'";
      UNREACHABLE();
  }
  LOG(FATAL) << "Attempt to write to field of unknown type";
  UNREACHABLE();
}

static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId object_id, JDWP::FieldId field_id,
                                         uint64_t value, int width, bool is_static)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  JDWP::JdwpError error;
  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(object_id, &error);
  if ((!is_static && o == nullptr) || error != JDWP::ERR_NONE) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  ArtField* f = FromFieldId(field_id);

  // The RI only enforces the static/non-static mismatch in one direction.
  // TODO: should we change the tests and check both?
  if (is_static) {
    if (!f->IsStatic()) {
      return JDWP::ERR_INVALID_FIELDID;
    }
  } else {
    if (f->IsStatic()) {
      LOG(WARNING) << "Ignoring non-nullptr receiver for ObjectReference.SetValues"
                   << " on static field " << PrettyField(f);
    }
  }
  if (f->IsStatic()) {
    o = f->GetDeclaringClass();
  }
  return SetArtFieldValue(f, o, value, width);
}

JDWP::JdwpError Dbg::SetFieldValue(JDWP::ObjectId object_id, JDWP::FieldId field_id, uint64_t value,
                                   int width) {
  return SetFieldValueImpl(object_id, field_id, value, width, false);
}

JDWP::JdwpError Dbg::SetStaticFieldValue(JDWP::FieldId field_id, uint64_t value, int width) {
  return SetFieldValueImpl(0, field_id, value, width, true);
}

JDWP::JdwpError Dbg::StringToUtf8(JDWP::ObjectId string_id, std::string* str) {
  JDWP::JdwpError error;
  mirror::Object* obj = gRegistry->Get<mirror::Object*>(string_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (obj == nullptr) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    mirror::Class* java_lang_String = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_String);
    if (!java_lang_String->IsAssignableFrom(obj->GetClass())) {
      // This isn't a string.
      return JDWP::ERR_INVALID_STRING;
    }
  }
  *str = obj->AsString()->ToModifiedUtf8();
  return JDWP::ERR_NONE;
}

void Dbg::OutputJValue(JDWP::JdwpTag tag, const JValue* return_value, JDWP::ExpandBuf* pReply) {
  if (IsPrimitiveTag(tag)) {
    expandBufAdd1(pReply, tag);
    if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
      expandBufAdd1(pReply, return_value->GetI());
    } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
      expandBufAdd2BE(pReply, return_value->GetI());
    } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
      expandBufAdd4BE(pReply, return_value->GetI());
    } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
      expandBufAdd8BE(pReply, return_value->GetJ());
    } else {
      CHECK_EQ(tag, JDWP::JT_VOID);
    }
  } else {
    ScopedObjectAccessUnchecked soa(Thread::Current());
    mirror::Object* value = return_value->GetL();
    expandBufAdd1(pReply, TagFromObject(soa, value));
    expandBufAddObjectId(pReply, gRegistry->Add(value));
  }
}

JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  UNUSED(thread);
  if (error != JDWP::ERR_NONE && error != JDWP::ERR_THREAD_NOT_ALIVE) {
    return error;
  }

  // We still need to report the zombie threads' names, so we can't just call Thread::GetThreadName.
  mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error);
  CHECK(thread_object != nullptr) << error;
  ArtField* java_lang_Thread_name_field =
      soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
  mirror::String* s =
      reinterpret_cast<mirror::String*>(java_lang_Thread_name_field->GetObject(thread_object));
  if (s != nullptr) {
    *name = s->ToModifiedUtf8();
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* thread_object = gRegistry->Get<mirror::Object*>(thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroup");
  // Okay, so it's an object, but is it actually a thread?
  Thread* thread = DecodeThread(soa, thread_id, &error);
  UNUSED(thread);
  if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
    // Zombie threads are in the null group.
    expandBufAddObjectId(pReply, JDWP::ObjectId(0));
    error = JDWP::ERR_NONE;
  } else if (error == JDWP::ERR_NONE) {
    mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
    CHECK(c != nullptr);
    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
    CHECK(f != nullptr);
    mirror::Object* group = f->GetObject(thread_object);
    CHECK(group != nullptr);
    JDWP::ObjectId thread_group_id = gRegistry->Add(group);
    expandBufAddObjectId(pReply, thread_group_id);
  }
  return error;
}

static mirror::Object* DecodeThreadGroup(ScopedObjectAccessUnchecked& soa,
                                         JDWP::ObjectId thread_group_id, JDWP::JdwpError* error)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  mirror::Object* thread_group = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_group_id,
                                                                                error);
  if (*error != JDWP::ERR_NONE) {
    return nullptr;
  }
  if (thread_group == nullptr) {
    *error = JDWP::ERR_INVALID_OBJECT;
    return nullptr;
  }
  mirror::Class* c = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ThreadGroup);
  CHECK(c != nullptr);
  if (!c->IsAssignableFrom(thread_group->GetClass())) {
    // This is not a java.lang.ThreadGroup.
    *error = JDWP::ERR_INVALID_THREAD_GROUP;
    return nullptr;
  }
  *error = JDWP::ERR_NONE;
  return thread_group;
}

JDWP::JdwpError Dbg::GetThreadGroupName(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupName");
  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_name);
  CHECK(f != nullptr);
  mirror::String* s = reinterpret_cast<mirror::String*>(f->GetObject(thread_group));

  std::string thread_group_name(s->ToModifiedUtf8());
  expandBufAddUtf8String(pReply, thread_group_name);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetThreadGroupParent(JDWP::ObjectId thread_group_id, JDWP::ExpandBuf* pReply) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  mirror::Object* parent;
  {
    ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroupParent");
    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_parent);
    CHECK(f != nullptr);
    parent = f->GetObject(thread_group);
  }
  JDWP::ObjectId parent_group_id = gRegistry->Add(parent);
  expandBufAddObjectId(pReply, parent_group_id);
  return JDWP::ERR_NONE;
}

static void GetChildThreadGroups(ScopedObjectAccessUnchecked& soa, mirror::Object* thread_group,
                                 std::vector<JDWP::ObjectId>* child_thread_group_ids)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  CHECK(thread_group != nullptr);

  // Get the ArrayList<ThreadGroup> "groups" out of this thread group...
  ArtField* groups_field = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_groups);
  mirror::Object* groups_array_list = groups_field->GetObject(thread_group);
  {
    // The "groups" field is declared as a java.util.List: check it really is
    // an instance of java.util.ArrayList.
    CHECK(groups_array_list != nullptr);
    mirror::Class* java_util_ArrayList_class =
        soa.Decode<mirror::Class*>(WellKnownClasses::java_util_ArrayList);
    CHECK(groups_array_list->InstanceOf(java_util_ArrayList_class));
  }

  // Get the array and size out of the ArrayList<ThreadGroup>...
  ArtField* array_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_array);
  ArtField* size_field = soa.DecodeField(WellKnownClasses::java_util_ArrayList_size);
  mirror::ObjectArray<mirror::Object>* groups_array =
      array_field->GetObject(groups_array_list)->AsObjectArray<mirror::Object>();
  const int32_t size = size_field->GetInt(groups_array_list);

  // Copy the first 'size' elements out of the array into the result.
  ObjectRegistry* registry = Dbg::GetObjectRegistry();
  for (int32_t i = 0; i < size; ++i) {
    child_thread_group_ids->push_back(registry->Add(groups_array->Get(i)));
  }
}

JDWP::JdwpError Dbg::GetThreadGroupChildren(JDWP::ObjectId thread_group_id,
                                            JDWP::ExpandBuf* pReply) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* thread_group = DecodeThreadGroup(soa, thread_group_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }

  // Add child threads.
  {
    std::vector<JDWP::ObjectId> child_thread_ids;
    GetThreads(thread_group, &child_thread_ids);
    expandBufAdd4BE(pReply, child_thread_ids.size());
    for (JDWP::ObjectId child_thread_id : child_thread_ids) {
      expandBufAddObjectId(pReply, child_thread_id);
    }
  }

  // Add child thread groups.
  {
    std::vector<JDWP::ObjectId> child_thread_groups_ids;
    GetChildThreadGroups(soa, thread_group, &child_thread_groups_ids);
    expandBufAdd4BE(pReply, child_thread_groups_ids.size());
    for (JDWP::ObjectId child_thread_group_id : child_thread_groups_ids) {
      expandBufAddObjectId(pReply, child_thread_group_id);
    }
  }

  return JDWP::ERR_NONE;
}

JDWP::ObjectId Dbg::GetSystemThreadGroupId() {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup);
  mirror::Object* group = f->GetObject(f->GetDeclaringClass());
  return gRegistry->Add(group);
}

JDWP::JdwpThreadStatus Dbg::ToJdwpThreadStatus(ThreadState state) {
  switch (state) {
    case kBlocked:
      return JDWP::TS_MONITOR;
    case kNative:
    case kRunnable:
    case kSuspended:
      return JDWP::TS_RUNNING;
    case kSleeping:
      return JDWP::TS_SLEEPING;
    case kStarting:
    case kTerminated:
      return JDWP::TS_ZOMBIE;
    case kTimedWaiting:
    case kWaitingForCheckPointsToRun:
    case kWaitingForDebuggerSend:
    case kWaitingForDebuggerSuspension:
    case kWaitingForDebuggerToAttach:
    case kWaitingForDeoptimization:
    case kWaitingForGcToComplete:
    case kWaitingForGetObjectsAllocated:
    case kWaitingForJniOnLoad:
    case kWaitingForMethodTracingStart:
    case kWaitingForSignalCatcherOutput:
    case kWaitingForVisitObjects:
    case kWaitingInMainDebuggerLoop:
    case kWaitingInMainSignalCatcherLoop:
    case kWaitingPerformingGc:
    case kWaitingWeakGcRootRead:
    case kWaiting:
      return JDWP::TS_WAIT;
      // Don't add a 'default' here so the compiler can spot incompatible enum changes.
  }
  LOG(FATAL) << "Unknown thread state: " << state;
  return JDWP::TS_ZOMBIE;
}

JDWP::JdwpError Dbg::GetThreadStatus(JDWP::ObjectId thread_id, JDWP::JdwpThreadStatus* pThreadStatus,
                                     JDWP::JdwpSuspendStatus* pSuspendStatus) {
  ScopedObjectAccess soa(Thread::Current());

  *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED;

  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
      *pThreadStatus = JDWP::TS_ZOMBIE;
      return JDWP::ERR_NONE;
    }
    return error;
  }

  if (IsSuspendedForDebugger(soa, thread)) {
    *pSuspendStatus = JDWP::SUSPEND_STATUS_SUSPENDED;
  }

  *pThreadStatus = ToJdwpThreadStatus(thread->GetState());
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) {
  ScopedObjectAccess soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
  expandBufAdd4BE(pReply, thread->GetDebugSuspendCount());
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) {
  ScopedObjectAccess soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  thread->Interrupt(soa.Self());
  return JDWP::ERR_NONE;
}

static bool IsInDesiredThreadGroup(ScopedObjectAccessUnchecked& soa,
                                   mirror::Object* desired_thread_group, mirror::Object* peer)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  // Do we want threads from all thread groups?
  if (desired_thread_group == nullptr) {
    return true;
  }
  ArtField* thread_group_field = soa.DecodeField(WellKnownClasses::java_lang_Thread_group);
  DCHECK(thread_group_field != nullptr);
  mirror::Object* group = thread_group_field->GetObject(peer);
  return (group == desired_thread_group);
}

void Dbg::GetThreads(mirror::Object* thread_group, std::vector<JDWP::ObjectId>* thread_ids) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  std::list<Thread*> all_threads_list;
  {
    MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
    all_threads_list = Runtime::Current()->GetThreadList()->GetList();
  }
  for (Thread* t : all_threads_list) {
    if (t == Dbg::GetDebugThread()) {
      // Skip the JDWP thread. Some debuggers get bent out of shape when they can't suspend and
      // query all threads, so it's easier if we just don't tell them about this thread.
      continue;
    }
    if (t->IsStillStarting()) {
      // This thread is being started (and has been registered in the thread list). However, it is
      // not completely started yet so we must ignore it.
      continue;
    }
    mirror::Object* peer = t->GetPeer();
    if (peer == nullptr) {
      // peer might be null if the thread is still starting up. We can't tell the debugger about
      // this thread yet.
      // TODO: if we identified threads to the debugger by their Thread*
      // rather than their peer's mirror::Object*, we could fix this.
      // Doing so might help us report ZOMBIE threads too.
      continue;
    }
    if (IsInDesiredThreadGroup(soa, thread_group, peer)) {
      thread_ids->push_back(gRegistry->Add(peer));
    }
  }
}

static int GetStackDepth(Thread* thread) SHARED_REQUIRES(Locks::mutator_lock_) {
  struct CountStackDepthVisitor : public StackVisitor {
    explicit CountStackDepthVisitor(Thread* thread_in)
        : StackVisitor(thread_in, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
          depth(0) {}

    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
    // annotalysis.
    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
      if (!GetMethod()->IsRuntimeMethod()) {
        ++depth;
      }
      return true;
    }
    size_t depth;
  };

  CountStackDepthVisitor visitor(thread);
  visitor.WalkStack();
  return visitor.depth;
}

JDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) {
  ScopedObjectAccess soa(Thread::Current());
  JDWP::JdwpError error;
  *result = 0;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  *result = GetStackDepth(thread);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame,
                                     size_t frame_count, JDWP::ExpandBuf* buf) {
  class GetFrameVisitor : public StackVisitor {
   public:
    GetFrameVisitor(Thread* thread, size_t start_frame_in, size_t frame_count_in,
                    JDWP::ExpandBuf* buf_in)
        SHARED_REQUIRES(Locks::mutator_lock_)
        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
          depth_(0),
          start_frame_(start_frame_in),
          frame_count_(frame_count_in),
          buf_(buf_in) {
      expandBufAdd4BE(buf_, frame_count_);
    }

    bool VisitFrame() OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
      if (GetMethod()->IsRuntimeMethod()) {
        return true;  // The debugger can't do anything useful with a frame that has no Method*.
      }
      if (depth_ >= start_frame_ + frame_count_) {
        return false;
      }
      if (depth_ >= start_frame_) {
        JDWP::FrameId frame_id(GetFrameId());
        JDWP::JdwpLocation location;
        SetJdwpLocation(&location, GetMethod(), GetDexPc());
        VLOG(jdwp) << StringPrintf("    Frame %3zd: id=%3" PRIu64 " ", depth_, frame_id) << location;
        expandBufAdd8BE(buf_, frame_id);
        expandBufAddLocation(buf_, location);
      }
      ++depth_;
      return true;
    }

   private:
    size_t depth_;
    const size_t start_frame_;
    const size_t frame_count_;
    JDWP::ExpandBuf* buf_;
  };

  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  GetFrameVisitor visitor(thread, start_frame, frame_count, buf);
  visitor.WalkStack();
  return JDWP::ERR_NONE;
}

JDWP::ObjectId Dbg::GetThreadSelfId() {
  return GetThreadId(Thread::Current());
}

JDWP::ObjectId Dbg::GetThreadId(Thread* thread) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  return gRegistry->Add(thread->GetPeer());
}

void Dbg::SuspendVM() {
  Runtime::Current()->GetThreadList()->SuspendAllForDebugger();
}

void Dbg::ResumeVM() {
  Runtime::Current()->GetThreadList()->ResumeAllForDebugger();
}

JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId thread_id, bool request_suspension) {
  Thread* self = Thread::Current();
  ScopedLocalRef<jobject> peer(self->GetJniEnv(), nullptr);
  {
    ScopedObjectAccess soa(self);
    JDWP::JdwpError error;
    peer.reset(soa.AddLocalReference<jobject>(gRegistry->Get<mirror::Object*>(thread_id, &error)));
  }
  if (peer.get() == nullptr) {
    return JDWP::ERR_THREAD_NOT_ALIVE;
  }
  // Suspend thread to build stack trace.
  bool timed_out;
  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  Thread* thread = thread_list->SuspendThreadByPeer(peer.get(), request_suspension, true,
                                                    &timed_out);
  if (thread != nullptr) {
    return JDWP::ERR_NONE;
  } else if (timed_out) {
    return JDWP::ERR_INTERNAL;
  } else {
    return JDWP::ERR_THREAD_NOT_ALIVE;
  }
}

void Dbg::ResumeThread(JDWP::ObjectId thread_id) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  mirror::Object* peer = gRegistry->Get<mirror::Object*>(thread_id, &error);
  CHECK(peer != nullptr) << error;
  Thread* thread;
  {
    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
    thread = Thread::FromManagedThread(soa, peer);
  }
  if (thread == nullptr) {
    LOG(WARNING) << "No such thread for resume: " << peer;
    return;
  }
  bool needs_resume;
  {
    MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
    needs_resume = thread->GetSuspendCount() > 0;
  }
  if (needs_resume) {
    Runtime::Current()->GetThreadList()->Resume(thread, true);
  }
}

void Dbg::SuspendSelf() {
  Runtime::Current()->GetThreadList()->SuspendSelfForDebugger();
}

struct GetThisVisitor : public StackVisitor {
  GetThisVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id_in)
      SHARED_REQUIRES(Locks::mutator_lock_)
      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
        this_object(nullptr),
        frame_id(frame_id_in) {}

  // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
  // annotalysis.
  virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
    if (frame_id != GetFrameId()) {
      return true;  // continue
    } else {
      this_object = GetThisObject();
      return false;
    }
  }

  mirror::Object* this_object;
  JDWP::FrameId frame_id;
};

JDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id,
                                   JDWP::ObjectId* result) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  std::unique_ptr<Context> context(Context::Create());
  GetThisVisitor visitor(thread, context.get(), frame_id);
  visitor.WalkStack();
  *result = gRegistry->Add(visitor.this_object);
  return JDWP::ERR_NONE;
}

// Walks the stack until we find the frame with the given FrameId.
class FindFrameVisitor FINAL : public StackVisitor {
 public:
  FindFrameVisitor(Thread* thread, Context* context, JDWP::FrameId frame_id)
      SHARED_REQUIRES(Locks::mutator_lock_)
      : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
        frame_id_(frame_id),
        error_(JDWP::ERR_INVALID_FRAMEID) {}

  // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
  // annotalysis.
  bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
    if (GetFrameId() != frame_id_) {
      return true;  // Not our frame, carry on.
    }
    ArtMethod* m = GetMethod();
    if (m->IsNative()) {
      // We can't read/write local value from/into native method.
      error_ = JDWP::ERR_OPAQUE_FRAME;
    } else {
      // We found our frame.
      error_ = JDWP::ERR_NONE;
    }
    return false;
  }

  JDWP::JdwpError GetError() const {
    return error_;
  }

 private:
  const JDWP::FrameId frame_id_;
  JDWP::JdwpError error_;
};

JDWP::JdwpError Dbg::GetLocalValues(JDWP::Request* request, JDWP::ExpandBuf* pReply) {
  JDWP::ObjectId thread_id = request->ReadThreadId();
  JDWP::FrameId frame_id = request->ReadFrameId();

  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  // Find the frame with the given frame_id.
  std::unique_ptr<Context> context(Context::Create());
  FindFrameVisitor visitor(thread, context.get(), frame_id);
  visitor.WalkStack();
  if (visitor.GetError() != JDWP::ERR_NONE) {
    return visitor.GetError();
  }

  // Read the values from visitor's context.
  int32_t slot_count = request->ReadSigned32("slot count");
  expandBufAdd4BE(pReply, slot_count);     /* "int values" */
  for (int32_t i = 0; i < slot_count; ++i) {
    uint32_t slot = request->ReadUnsigned32("slot");
    JDWP::JdwpTag reqSigByte = request->ReadTag();

    VLOG(jdwp) << "    --> slot " << slot << " " << reqSigByte;

    size_t width = Dbg::GetTagWidth(reqSigByte);
    uint8_t* ptr = expandBufAddSpace(pReply, width + 1);
    error = Dbg::GetLocalValue(visitor, soa, slot, reqSigByte, ptr, width);
    if (error != JDWP::ERR_NONE) {
      return error;
    }
  }
  return JDWP::ERR_NONE;
}

constexpr JDWP::JdwpError kStackFrameLocalAccessError = JDWP::ERR_ABSENT_INFORMATION;

static std::string GetStackContextAsString(const StackVisitor& visitor)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  return StringPrintf(" at DEX pc 0x%08x in method %s", visitor.GetDexPc(false),
                      PrettyMethod(visitor.GetMethod()).c_str());
}

static JDWP::JdwpError FailGetLocalValue(const StackVisitor& visitor, uint16_t vreg,
                                         JDWP::JdwpTag tag)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  LOG(ERROR) << "Failed to read " << tag << " local from register v" << vreg
             << GetStackContextAsString(visitor);
  return kStackFrameLocalAccessError;
}

JDWP::JdwpError Dbg::GetLocalValue(const StackVisitor& visitor, ScopedObjectAccessUnchecked& soa,
                                   int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
  ArtMethod* m = visitor.GetMethod();
  JDWP::JdwpError error = JDWP::ERR_NONE;
  uint16_t vreg = DemangleSlot(slot, m, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  // TODO: check that the tag is compatible with the actual type of the slot!
  switch (tag) {
    case JDWP::JT_BOOLEAN: {
      CHECK_EQ(width, 1U);
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get boolean local " << vreg << " = " << intVal;
      JDWP::Set1(buf + 1, intVal != 0);
      break;
    }
    case JDWP::JT_BYTE: {
      CHECK_EQ(width, 1U);
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get byte local " << vreg << " = " << intVal;
      JDWP::Set1(buf + 1, intVal);
      break;
    }
    case JDWP::JT_SHORT:
    case JDWP::JT_CHAR: {
      CHECK_EQ(width, 2U);
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get short/char local " << vreg << " = " << intVal;
      JDWP::Set2BE(buf + 1, intVal);
      break;
    }
    case JDWP::JT_INT: {
      CHECK_EQ(width, 4U);
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kIntVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get int local " << vreg << " = " << intVal;
      JDWP::Set4BE(buf + 1, intVal);
      break;
    }
    case JDWP::JT_FLOAT: {
      CHECK_EQ(width, 4U);
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kFloatVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get float local " << vreg << " = " << intVal;
      JDWP::Set4BE(buf + 1, intVal);
      break;
    }
    case JDWP::JT_ARRAY:
    case JDWP::JT_CLASS_LOADER:
    case JDWP::JT_CLASS_OBJECT:
    case JDWP::JT_OBJECT:
    case JDWP::JT_STRING:
    case JDWP::JT_THREAD:
    case JDWP::JT_THREAD_GROUP: {
      CHECK_EQ(width, sizeof(JDWP::ObjectId));
      uint32_t intVal;
      if (!visitor.GetVReg(m, vreg, kReferenceVReg, &intVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      mirror::Object* o = reinterpret_cast<mirror::Object*>(intVal);
      VLOG(jdwp) << "get " << tag << " object local " << vreg << " = " << o;
      if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
        LOG(FATAL) << StringPrintf("Found invalid object %#" PRIxPTR " in register v%u",
                                   reinterpret_cast<uintptr_t>(o), vreg)
                                   << GetStackContextAsString(visitor);
        UNREACHABLE();
      }
      tag = TagFromObject(soa, o);
      JDWP::SetObjectId(buf + 1, gRegistry->Add(o));
      break;
    }
    case JDWP::JT_DOUBLE: {
      CHECK_EQ(width, 8U);
      uint64_t longVal;
      if (!visitor.GetVRegPair(m, vreg, kDoubleLoVReg, kDoubleHiVReg, &longVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get double local " << vreg << " = " << longVal;
      JDWP::Set8BE(buf + 1, longVal);
      break;
    }
    case JDWP::JT_LONG: {
      CHECK_EQ(width, 8U);
      uint64_t longVal;
      if (!visitor.GetVRegPair(m, vreg, kLongLoVReg, kLongHiVReg, &longVal)) {
        return FailGetLocalValue(visitor, vreg, tag);
      }
      VLOG(jdwp) << "get long local " << vreg << " = " << longVal;
      JDWP::Set8BE(buf + 1, longVal);
      break;
    }
    default:
      LOG(FATAL) << "Unknown tag " << tag;
      UNREACHABLE();
  }

  // Prepend tag, which may have been updated.
  JDWP::Set1(buf, tag);
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::SetLocalValues(JDWP::Request* request) {
  JDWP::ObjectId thread_id = request->ReadThreadId();
  JDWP::FrameId frame_id = request->ReadFrameId();

  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  if (!IsSuspendedForDebugger(soa, thread)) {
    return JDWP::ERR_THREAD_NOT_SUSPENDED;
  }
  // Find the frame with the given frame_id.
  std::unique_ptr<Context> context(Context::Create());
  FindFrameVisitor visitor(thread, context.get(), frame_id);
  visitor.WalkStack();
  if (visitor.GetError() != JDWP::ERR_NONE) {
    return visitor.GetError();
  }

  // Writes the values into visitor's context.
  int32_t slot_count = request->ReadSigned32("slot count");
  for (int32_t i = 0; i < slot_count; ++i) {
    uint32_t slot = request->ReadUnsigned32("slot");
    JDWP::JdwpTag sigByte = request->ReadTag();
    size_t width = Dbg::GetTagWidth(sigByte);
    uint64_t value = request->ReadValue(width);

    VLOG(jdwp) << "    --> slot " << slot << " " << sigByte << " " << value;
    error = Dbg::SetLocalValue(visitor, slot, sigByte, value, width);
    if (error != JDWP::ERR_NONE) {
      return error;
    }
  }
  return JDWP::ERR_NONE;
}

template<typename T>
static JDWP::JdwpError FailSetLocalValue(const StackVisitor& visitor, uint16_t vreg,
                                         JDWP::JdwpTag tag, T value)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  LOG(ERROR) << "Failed to write " << tag << " local " << value
             << " (0x" << std::hex << value << ") into register v" << vreg
             << GetStackContextAsString(visitor);
  return kStackFrameLocalAccessError;
}

JDWP::JdwpError Dbg::SetLocalValue(StackVisitor& visitor, int slot, JDWP::JdwpTag tag,
                                   uint64_t value, size_t width) {
  ArtMethod* m = visitor.GetMethod();
  JDWP::JdwpError error = JDWP::ERR_NONE;
  uint16_t vreg = DemangleSlot(slot, m, &error);
  if (error != JDWP::ERR_NONE) {
    return error;
  }
  // TODO: check that the tag is compatible with the actual type of the slot!
  switch (tag) {
    case JDWP::JT_BOOLEAN:
    case JDWP::JT_BYTE:
      CHECK_EQ(width, 1U);
      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
      }
      break;
    case JDWP::JT_SHORT:
    case JDWP::JT_CHAR:
      CHECK_EQ(width, 2U);
      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
      }
      break;
    case JDWP::JT_INT:
      CHECK_EQ(width, 4U);
      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kIntVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
      }
      break;
    case JDWP::JT_FLOAT:
      CHECK_EQ(width, 4U);
      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(value), kFloatVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, static_cast<uint32_t>(value));
      }
      break;
    case JDWP::JT_ARRAY:
    case JDWP::JT_CLASS_LOADER:
    case JDWP::JT_CLASS_OBJECT:
    case JDWP::JT_OBJECT:
    case JDWP::JT_STRING:
    case JDWP::JT_THREAD:
    case JDWP::JT_THREAD_GROUP: {
      CHECK_EQ(width, sizeof(JDWP::ObjectId));
      mirror::Object* o = gRegistry->Get<mirror::Object*>(static_cast<JDWP::ObjectId>(value),
                                                          &error);
      if (error != JDWP::ERR_NONE) {
        VLOG(jdwp) << tag << " object " << o << " is an invalid object";
        return JDWP::ERR_INVALID_OBJECT;
      }
      if (!visitor.SetVReg(m, vreg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)),
                                 kReferenceVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, reinterpret_cast<uintptr_t>(o));
      }
      break;
    }
    case JDWP::JT_DOUBLE: {
      CHECK_EQ(width, 8U);
      if (!visitor.SetVRegPair(m, vreg, value, kDoubleLoVReg, kDoubleHiVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, value);
      }
      break;
    }
    case JDWP::JT_LONG: {
      CHECK_EQ(width, 8U);
      if (!visitor.SetVRegPair(m, vreg, value, kLongLoVReg, kLongHiVReg)) {
        return FailSetLocalValue(visitor, vreg, tag, value);
      }
      break;
    }
    default:
      LOG(FATAL) << "Unknown tag " << tag;
      UNREACHABLE();
  }
  return JDWP::ERR_NONE;
}

static void SetEventLocation(JDWP::EventLocation* location, ArtMethod* m, uint32_t dex_pc)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  DCHECK(location != nullptr);
  if (m == nullptr) {
    memset(location, 0, sizeof(*location));
  } else {
    location->method = m;
    location->dex_pc = (m->IsNative() || m->IsProxyMethod()) ? static_cast<uint32_t>(-1) : dex_pc;
  }
}

void Dbg::PostLocationEvent(ArtMethod* m, int dex_pc, mirror::Object* this_object,
                            int event_flags, const JValue* return_value) {
  if (!IsDebuggerActive()) {
    return;
  }
  DCHECK(m != nullptr);
  DCHECK_EQ(m->IsStatic(), this_object == nullptr);
  JDWP::EventLocation location;
  SetEventLocation(&location, m, dex_pc);

  // We need to be sure no exception is pending when calling JdwpState::PostLocationEvent.
  // This is required to be able to call JNI functions to create JDWP ids. To achieve this,
  // we temporarily clear the current thread's exception (if any) and will restore it after
  // the call.
  // Note: the only way to get a pending exception here is to suspend on a move-exception
  // instruction.
  Thread* const self = Thread::Current();
  StackHandleScope<1> hs(self);
  Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException()));
  self->ClearException();
  if (kIsDebugBuild && pending_exception.Get() != nullptr) {
    const DexFile::CodeItem* code_item = location.method->GetCodeItem();
    const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]);
    CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode());
  }

  gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value);

  if (pending_exception.Get() != nullptr) {
    self->SetException(pending_exception.Get());
  }
}

void Dbg::PostFieldAccessEvent(ArtMethod* m, int dex_pc,
                               mirror::Object* this_object, ArtField* f) {
  if (!IsDebuggerActive()) {
    return;
  }
  DCHECK(m != nullptr);
  DCHECK(f != nullptr);
  JDWP::EventLocation location;
  SetEventLocation(&location, m, dex_pc);

  gJdwpState->PostFieldEvent(&location, f, this_object, nullptr, false);
}

void Dbg::PostFieldModificationEvent(ArtMethod* m, int dex_pc,
                                     mirror::Object* this_object, ArtField* f,
                                     const JValue* field_value) {
  if (!IsDebuggerActive()) {
    return;
  }
  DCHECK(m != nullptr);
  DCHECK(f != nullptr);
  DCHECK(field_value != nullptr);
  JDWP::EventLocation location;
  SetEventLocation(&location, m, dex_pc);

  gJdwpState->PostFieldEvent(&location, f, this_object, field_value, true);
}

/**
 * Finds the location where this exception will be caught. We search until we reach the top
 * frame, in which case this exception is considered uncaught.
 */
class CatchLocationFinder : public StackVisitor {
 public:
  CatchLocationFinder(Thread* self, const Handle<mirror::Throwable>& exception, Context* context)
      SHARED_REQUIRES(Locks::mutator_lock_)
    : StackVisitor(self, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
      self_(self),
      exception_(exception),
      handle_scope_(self),
      this_at_throw_(handle_scope_.NewHandle<mirror::Object>(nullptr)),
      catch_method_(nullptr),
      throw_method_(nullptr),
      catch_dex_pc_(DexFile::kDexNoIndex),
      throw_dex_pc_(DexFile::kDexNoIndex) {
  }

  bool VisitFrame() OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
    ArtMethod* method = GetMethod();
    DCHECK(method != nullptr);
    if (method->IsRuntimeMethod()) {
      // Ignore callee save method.
      DCHECK(method->IsCalleeSaveMethod());
      return true;
    }

    uint32_t dex_pc = GetDexPc();
    if (throw_method_ == nullptr) {
      // First Java method found. It is either the method that threw the exception,
      // or the Java native method that is reporting an exception thrown by
      // native code.
      this_at_throw_.Assign(GetThisObject());
      throw_method_ = method;
      throw_dex_pc_ = dex_pc;
    }

    if (dex_pc != DexFile::kDexNoIndex) {
      StackHandleScope<1> hs(self_);
      uint32_t found_dex_pc;
      Handle<mirror::Class> exception_class(hs.NewHandle(exception_->GetClass()));
      bool unused_clear_exception;
      found_dex_pc = method->FindCatchBlock(exception_class, dex_pc, &unused_clear_exception);
      if (found_dex_pc != DexFile::kDexNoIndex) {
        catch_method_ = method;
        catch_dex_pc_ = found_dex_pc;
        return false;  // End stack walk.
      }
    }
    return true;  // Continue stack walk.
  }

  ArtMethod* GetCatchMethod() SHARED_REQUIRES(Locks::mutator_lock_) {
    return catch_method_;
  }

  ArtMethod* GetThrowMethod() SHARED_REQUIRES(Locks::mutator_lock_) {
    return throw_method_;
  }

  mirror::Object* GetThisAtThrow() SHARED_REQUIRES(Locks::mutator_lock_) {
    return this_at_throw_.Get();
  }

  uint32_t GetCatchDexPc() const {
    return catch_dex_pc_;
  }

  uint32_t GetThrowDexPc() const {
    return throw_dex_pc_;
  }

 private:
  Thread* const self_;
  const Handle<mirror::Throwable>& exception_;
  StackHandleScope<1> handle_scope_;
  MutableHandle<mirror::Object> this_at_throw_;
  ArtMethod* catch_method_;
  ArtMethod* throw_method_;
  uint32_t catch_dex_pc_;
  uint32_t throw_dex_pc_;

  DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
};

void Dbg::PostException(mirror::Throwable* exception_object) {
  if (!IsDebuggerActive()) {
    return;
  }
  Thread* const self = Thread::Current();
  StackHandleScope<1> handle_scope(self);
  Handle<mirror::Throwable> h_exception(handle_scope.NewHandle(exception_object));
  std::unique_ptr<Context> context(Context::Create());
  CatchLocationFinder clf(self, h_exception, context.get());
  clf.WalkStack(/* include_transitions */ false);
  JDWP::EventLocation exception_throw_location;
  SetEventLocation(&exception_throw_location, clf.GetThrowMethod(), clf.GetThrowDexPc());
  JDWP::EventLocation exception_catch_location;
  SetEventLocation(&exception_catch_location, clf.GetCatchMethod(), clf.GetCatchDexPc());

  gJdwpState->PostException(&exception_throw_location, h_exception.Get(), &exception_catch_location,
                            clf.GetThisAtThrow());
}

void Dbg::PostClassPrepare(mirror::Class* c) {
  if (!IsDebuggerActive()) {
    return;
  }
  gJdwpState->PostClassPrepare(c);
}

void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
                         ArtMethod* m, uint32_t dex_pc,
                         int event_flags, const JValue* return_value) {
  if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) {
    return;
  }

  if (IsBreakpoint(m, dex_pc)) {
    event_flags |= kBreakpoint;
  }

  // If the debugger is single-stepping one of our threads, check to
  // see if we're that thread and we've reached a step point.
  const SingleStepControl* single_step_control = thread->GetSingleStepControl();
  if (single_step_control != nullptr) {
    CHECK(!m->IsNative());
    if (single_step_control->GetStepDepth() == JDWP::SD_INTO) {
      // Step into method calls.  We break when the line number
      // or method pointer changes.  If we're in SS_MIN mode, we
      // always stop.
      if (single_step_control->GetMethod() != m) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new method";
      } else if (single_step_control->GetStepSize() == JDWP::SS_MIN) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new instruction";
      } else if (single_step_control->ContainsDexPc(dex_pc)) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new line";
      }
    } else if (single_step_control->GetStepDepth() == JDWP::SD_OVER) {
      // Step over method calls.  We break when the line number is
      // different and the frame depth is <= the original frame
      // depth.  (We can't just compare on the method, because we
      // might get unrolled past it by an exception, and it's tricky
      // to identify recursion.)

      int stack_depth = GetStackDepth(thread);

      if (stack_depth < single_step_control->GetStackDepth()) {
        // Popped up one or more frames, always trigger.
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS method pop";
      } else if (stack_depth == single_step_control->GetStackDepth()) {
        // Same depth, see if we moved.
        if (single_step_control->GetStepSize() == JDWP::SS_MIN) {
          event_flags |= kSingleStep;
          VLOG(jdwp) << "SS new instruction";
        } else if (single_step_control->ContainsDexPc(dex_pc)) {
          event_flags |= kSingleStep;
          VLOG(jdwp) << "SS new line";
        }
      }
    } else {
      CHECK_EQ(single_step_control->GetStepDepth(), JDWP::SD_OUT);
      // Return from the current method.  We break when the frame
      // depth pops up.

      // This differs from the "method exit" break in that it stops
      // with the PC at the next instruction in the returned-to
      // function, rather than the end of the returning function.

      int stack_depth = GetStackDepth(thread);
      if (stack_depth < single_step_control->GetStackDepth()) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS method pop";
      }
    }
  }

  // If there's something interesting going on, see if it matches one
  // of the debugger filters.
  if (event_flags != 0) {
    Dbg::PostLocationEvent(m, dex_pc, this_object, event_flags, return_value);
  }
}

size_t* Dbg::GetReferenceCounterForEvent(uint32_t instrumentation_event) {
  switch (instrumentation_event) {
    case instrumentation::Instrumentation::kMethodEntered:
      return &method_enter_event_ref_count_;
    case instrumentation::Instrumentation::kMethodExited:
      return &method_exit_event_ref_count_;
    case instrumentation::Instrumentation::kDexPcMoved:
      return &dex_pc_change_event_ref_count_;
    case instrumentation::Instrumentation::kFieldRead:
      return &field_read_event_ref_count_;
    case instrumentation::Instrumentation::kFieldWritten:
      return &field_write_event_ref_count_;
    case instrumentation::Instrumentation::kExceptionCaught:
      return &exception_catch_event_ref_count_;
    default:
      return nullptr;
  }
}

// Process request while all mutator threads are suspended.
void Dbg::ProcessDeoptimizationRequest(const DeoptimizationRequest& request) {
  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
  switch (request.GetKind()) {
    case DeoptimizationRequest::kNothing:
      LOG(WARNING) << "Ignoring empty deoptimization request.";
      break;
    case DeoptimizationRequest::kRegisterForEvent:
      VLOG(jdwp) << StringPrintf("Add debugger as listener for instrumentation event 0x%x",
                                 request.InstrumentationEvent());
      instrumentation->AddListener(&gDebugInstrumentationListener, request.InstrumentationEvent());
      instrumentation_events_ |= request.InstrumentationEvent();
      break;
    case DeoptimizationRequest::kUnregisterForEvent:
      VLOG(jdwp) << StringPrintf("Remove debugger as listener for instrumentation event 0x%x",
                                 request.InstrumentationEvent());
      instrumentation->RemoveListener(&gDebugInstrumentationListener,
                                      request.InstrumentationEvent());
      instrumentation_events_ &= ~request.InstrumentationEvent();
      break;
    case DeoptimizationRequest::kFullDeoptimization:
      VLOG(jdwp) << "Deoptimize the world ...";
      instrumentation->DeoptimizeEverything(kDbgInstrumentationKey);
      VLOG(jdwp) << "Deoptimize the world DONE";
      break;
    case DeoptimizationRequest::kFullUndeoptimization:
      VLOG(jdwp) << "Undeoptimize the world ...";
      instrumentation->UndeoptimizeEverything(kDbgInstrumentationKey);
      VLOG(jdwp) << "Undeoptimize the world DONE";
      break;
    case DeoptimizationRequest::kSelectiveDeoptimization:
      VLOG(jdwp) << "Deoptimize method " << PrettyMethod(request.Method()) << " ...";
      instrumentation->Deoptimize(request.Method());
      VLOG(jdwp) << "Deoptimize method " << PrettyMethod(request.Method()) << " DONE";
      break;
    case DeoptimizationRequest::kSelectiveUndeoptimization:
      VLOG(jdwp) << "Undeoptimize method " << PrettyMethod(request.Method()) << " ...";
      instrumentation->Undeoptimize(request.Method());
      VLOG(jdwp) << "Undeoptimize method " << PrettyMethod(request.Method()) << " DONE";
      break;
    default:
      LOG(FATAL) << "Unsupported deoptimization request kind " << request.GetKind();
      break;
  }
}

void Dbg::RequestDeoptimization(const DeoptimizationRequest& req) {
  if (req.GetKind() == DeoptimizationRequest::kNothing) {
    // Nothing to do.
    return;
  }
  MutexLock mu(Thread::Current(), *Locks::deoptimization_lock_);
  RequestDeoptimizationLocked(req);
}

void Dbg::RequestDeoptimizationLocked(const DeoptimizationRequest& req) {
  switch (req.GetKind()) {
    case DeoptimizationRequest::kRegisterForEvent: {
      DCHECK_NE(req.InstrumentationEvent(), 0u);
      size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent());
      CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x",
                                                req.InstrumentationEvent());
      if (*counter == 0) {
        VLOG(jdwp) << StringPrintf("Queue request #%zd to start listening to instrumentation event 0x%x",
                                   deoptimization_requests_.size(), req.InstrumentationEvent());
        deoptimization_requests_.push_back(req);
      }
      *counter = *counter + 1;
      break;
    }
    case DeoptimizationRequest::kUnregisterForEvent: {
      DCHECK_NE(req.InstrumentationEvent(), 0u);
      size_t* counter = GetReferenceCounterForEvent(req.InstrumentationEvent());
      CHECK(counter != nullptr) << StringPrintf("No counter for instrumentation event 0x%x",
                                                req.InstrumentationEvent());
      *counter = *counter - 1;
      if (*counter == 0) {
        VLOG(jdwp) << StringPrintf("Queue request #%zd to stop listening to instrumentation event 0x%x",
                                   deoptimization_requests_.size(), req.InstrumentationEvent());
        deoptimization_requests_.push_back(req);
      }
      break;
    }
    case DeoptimizationRequest::kFullDeoptimization: {
      DCHECK(req.Method() == nullptr);
      if (full_deoptimization_event_count_ == 0) {
        VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
                   << " for full deoptimization";
        deoptimization_requests_.push_back(req);
      }
      ++full_deoptimization_event_count_;
      break;
    }
    case DeoptimizationRequest::kFullUndeoptimization: {
      DCHECK(req.Method() == nullptr);
      DCHECK_GT(full_deoptimization_event_count_, 0U);
      --full_deoptimization_event_count_;
      if (full_deoptimization_event_count_ == 0) {
        VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
                   << " for full undeoptimization";
        deoptimization_requests_.push_back(req);
      }
      break;
    }
    case DeoptimizationRequest::kSelectiveDeoptimization: {
      DCHECK(req.Method() != nullptr);
      VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
                 << " for deoptimization of " << PrettyMethod(req.Method());
      deoptimization_requests_.push_back(req);
      break;
    }
    case DeoptimizationRequest::kSelectiveUndeoptimization: {
      DCHECK(req.Method() != nullptr);
      VLOG(jdwp) << "Queue request #" << deoptimization_requests_.size()
                 << " for undeoptimization of " << PrettyMethod(req.Method());
      deoptimization_requests_.push_back(req);
      break;
    }
    default: {
      LOG(FATAL) << "Unknown deoptimization request kind " << req.GetKind();
      break;
    }
  }
}

void Dbg::ManageDeoptimization() {
  Thread* const self = Thread::Current();
  {
    // Avoid suspend/resume if there is no pending request.
    MutexLock mu(self, *Locks::deoptimization_lock_);
    if (deoptimization_requests_.empty()) {
      return;
    }
  }
  CHECK_EQ(self->GetState(), kRunnable);
  self->TransitionFromRunnableToSuspended(kWaitingForDeoptimization);
  // We need to suspend mutator threads first.
  Runtime* const runtime = Runtime::Current();
  runtime->GetThreadList()->SuspendAll(__FUNCTION__);
  const ThreadState old_state = self->SetStateUnsafe(kRunnable);
  {
    MutexLock mu(self, *Locks::deoptimization_lock_);
    size_t req_index = 0;
    for (DeoptimizationRequest& request : deoptimization_requests_) {
      VLOG(jdwp) << "Process deoptimization request #" << req_index++;
      ProcessDeoptimizationRequest(request);
    }
    deoptimization_requests_.clear();
  }
  CHECK_EQ(self->SetStateUnsafe(old_state), kRunnable);
  runtime->GetThreadList()->ResumeAll();
  self->TransitionFromSuspendedToRunnable();
}

static bool IsMethodPossiblyInlined(Thread* self, ArtMethod* m)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  const DexFile::CodeItem* code_item = m->GetCodeItem();
  if (code_item == nullptr) {
    // TODO We should not be asked to watch location in a native or abstract method so the code item
    // should never be null. We could just check we never encounter this case.
    return false;
  }
  // Note: method verifier may cause thread suspension.
  self->AssertThreadSuspensionIsAllowable();
  StackHandleScope<2> hs(self);
  mirror::Class* declaring_class = m->GetDeclaringClass();
  Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
  verifier::MethodVerifier verifier(self, dex_cache->GetDexFile(), dex_cache, class_loader,
                                    &m->GetClassDef(), code_item, m->GetDexMethodIndex(), m,
                                    m->GetAccessFlags(), false, true, false, true);
  // Note: we don't need to verify the method.
  return InlineMethodAnalyser::AnalyseMethodCode(&verifier, nullptr);
}

static const Breakpoint* FindFirstBreakpointForMethod(ArtMethod* m)
    SHARED_REQUIRES(Locks::mutator_lock_, Locks::breakpoint_lock_) {
  for (Breakpoint& breakpoint : gBreakpoints) {
    if (breakpoint.Method() == m) {
      return &breakpoint;
    }
  }
  return nullptr;
}

bool Dbg::MethodHasAnyBreakpoints(ArtMethod* method) {
  ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
  return FindFirstBreakpointForMethod(method) != nullptr;
}

// Sanity checks all existing breakpoints on the same method.
static void SanityCheckExistingBreakpoints(ArtMethod* m,
                                           DeoptimizationRequest::Kind deoptimization_kind)
    SHARED_REQUIRES(Locks::mutator_lock_, Locks::breakpoint_lock_) {
  for (const Breakpoint& breakpoint : gBreakpoints) {
    if (breakpoint.Method() == m) {
      CHECK_EQ(deoptimization_kind, breakpoint.GetDeoptimizationKind());
    }
  }
  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
  if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) {
    // We should have deoptimized everything but not "selectively" deoptimized this method.
    CHECK(instrumentation->AreAllMethodsDeoptimized());
    CHECK(!instrumentation->IsDeoptimized(m));
  } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
    // We should have "selectively" deoptimized this method.
    // Note: while we have not deoptimized everything for this method, we may have done it for
    // another event.
    CHECK(instrumentation->IsDeoptimized(m));
  } else {
    // This method does not require deoptimization.
    CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing);
    CHECK(!instrumentation->IsDeoptimized(m));
  }
}

// Returns the deoptimization kind required to set a breakpoint in a method.
// If a breakpoint has already been set, we also return the first breakpoint
// through the given 'existing_brkpt' pointer.
static DeoptimizationRequest::Kind GetRequiredDeoptimizationKind(Thread* self,
                                                                 ArtMethod* m,
                                                                 const Breakpoint** existing_brkpt)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  if (!Dbg::RequiresDeoptimization()) {
    // We already run in interpreter-only mode so we don't need to deoptimize anything.
    VLOG(jdwp) << "No need for deoptimization when fully running with interpreter for method "
               << PrettyMethod(m);
    return DeoptimizationRequest::kNothing;
  }
  const Breakpoint* first_breakpoint;
  {
    ReaderMutexLock mu(self, *Locks::breakpoint_lock_);
    first_breakpoint = FindFirstBreakpointForMethod(m);
    *existing_brkpt = first_breakpoint;
  }

  if (first_breakpoint == nullptr) {
    // There is no breakpoint on this method yet: we need to deoptimize. If this method may be
    // inlined, we deoptimize everything; otherwise we deoptimize only this method.
    // Note: IsMethodPossiblyInlined goes into the method verifier and may cause thread suspension.
    // Therefore we must not hold any lock when we call it.
    bool need_full_deoptimization = IsMethodPossiblyInlined(self, m);
    if (need_full_deoptimization) {
      VLOG(jdwp) << "Need full deoptimization because of possible inlining of method "
                 << PrettyMethod(m);
      return DeoptimizationRequest::kFullDeoptimization;
    } else {
      // We don't need to deoptimize if the method has not been compiled.
      ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
      const bool is_compiled = class_linker->GetOatMethodQuickCodeFor(m) != nullptr;
      if (is_compiled) {
        // If the method may be called through its direct code pointer (without loading
        // its updated entrypoint), we need full deoptimization to not miss the breakpoint.
        if (class_linker->MayBeCalledWithDirectCodePointer(m)) {
          VLOG(jdwp) << "Need full deoptimization because of possible direct code call "
                     << "into image for compiled method " << PrettyMethod(m);
          return DeoptimizationRequest::kFullDeoptimization;
        } else {
          VLOG(jdwp) << "Need selective deoptimization for compiled method " << PrettyMethod(m);
          return DeoptimizationRequest::kSelectiveDeoptimization;
        }
      } else {
        // Method is not compiled: we don't need to deoptimize.
        VLOG(jdwp) << "No need for deoptimization for non-compiled method " << PrettyMethod(m);
        return DeoptimizationRequest::kNothing;
      }
    }
  } else {
    // There is at least one breakpoint for this method: we don't need to deoptimize.
    // Let's check that all breakpoints are configured the same way for deoptimization.
    VLOG(jdwp) << "Breakpoint already set: no deoptimization is required";
    DeoptimizationRequest::Kind deoptimization_kind = first_breakpoint->GetDeoptimizationKind();
    if (kIsDebugBuild) {
      ReaderMutexLock mu(self, *Locks::breakpoint_lock_);
      SanityCheckExistingBreakpoints(m, deoptimization_kind);
    }
    return DeoptimizationRequest::kNothing;
  }
}

// Installs a breakpoint at the specified location. Also indicates through the deoptimization
// request if we need to deoptimize.
void Dbg::WatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
  Thread* const self = Thread::Current();
  ArtMethod* m = FromMethodId(location->method_id);
  DCHECK(m != nullptr) << "No method for method id " << location->method_id;

  const Breakpoint* existing_breakpoint = nullptr;
  const DeoptimizationRequest::Kind deoptimization_kind =
      GetRequiredDeoptimizationKind(self, m, &existing_breakpoint);
  req->SetKind(deoptimization_kind);
  if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
    req->SetMethod(m);
  } else {
    CHECK(deoptimization_kind == DeoptimizationRequest::kNothing ||
          deoptimization_kind == DeoptimizationRequest::kFullDeoptimization);
    req->SetMethod(nullptr);
  }

  {
    WriterMutexLock mu(self, *Locks::breakpoint_lock_);
    // If there is at least one existing breakpoint on the same method, the new breakpoint
    // must have the same deoptimization kind than the existing breakpoint(s).
    DeoptimizationRequest::Kind breakpoint_deoptimization_kind;
    if (existing_breakpoint != nullptr) {
      breakpoint_deoptimization_kind = existing_breakpoint->GetDeoptimizationKind();
    } else {
      breakpoint_deoptimization_kind = deoptimization_kind;
    }
    gBreakpoints.push_back(Breakpoint(m, location->dex_pc, breakpoint_deoptimization_kind));
    VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": "
               << gBreakpoints[gBreakpoints.size() - 1];
  }
}

// Uninstalls a breakpoint at the specified location. Also indicates through the deoptimization
// request if we need to undeoptimize.
void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
  WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
  ArtMethod* m = FromMethodId(location->method_id);
  DCHECK(m != nullptr) << "No method for method id " << location->method_id;
  DeoptimizationRequest::Kind deoptimization_kind = DeoptimizationRequest::kNothing;
  for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
    if (gBreakpoints[i].DexPc() == location->dex_pc && gBreakpoints[i].Method() == m) {
      VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i];
      deoptimization_kind = gBreakpoints[i].GetDeoptimizationKind();
      DCHECK_EQ(deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization,
                Runtime::Current()->GetInstrumentation()->IsDeoptimized(m));
      gBreakpoints.erase(gBreakpoints.begin() + i);
      break;
    }
  }
  const Breakpoint* const existing_breakpoint = FindFirstBreakpointForMethod(m);
  if (existing_breakpoint == nullptr) {
    // There is no more breakpoint on this method: we need to undeoptimize.
    if (deoptimization_kind == DeoptimizationRequest::kFullDeoptimization) {
      // This method required full deoptimization: we need to undeoptimize everything.
      req->SetKind(DeoptimizationRequest::kFullUndeoptimization);
      req->SetMethod(nullptr);
    } else if (deoptimization_kind == DeoptimizationRequest::kSelectiveDeoptimization) {
      // This method required selective deoptimization: we need to undeoptimize only that method.
      req->SetKind(DeoptimizationRequest::kSelectiveUndeoptimization);
      req->SetMethod(m);
    } else {
      // This method had no need for deoptimization: do nothing.
      CHECK_EQ(deoptimization_kind, DeoptimizationRequest::kNothing);
      req->SetKind(DeoptimizationRequest::kNothing);
      req->SetMethod(nullptr);
    }
  } else {
    // There is at least one breakpoint for this method: we don't need to undeoptimize.
    req->SetKind(DeoptimizationRequest::kNothing);
    req->SetMethod(nullptr);
    if (kIsDebugBuild) {
      SanityCheckExistingBreakpoints(m, deoptimization_kind);
    }
  }
}

bool Dbg::IsForcedInterpreterNeededForCallingImpl(Thread* thread, ArtMethod* m) {
  const SingleStepControl* const ssc = thread->GetSingleStepControl();
  if (ssc == nullptr) {
    // If we are not single-stepping, then we don't have to force interpreter.
    return false;
  }
  if (Runtime::Current()->GetInstrumentation()->InterpretOnly()) {
    // If we are in interpreter only mode, then we don't have to force interpreter.
    return false;
  }

  if (!m->IsNative() && !m->IsProxyMethod()) {
    // If we want to step into a method, then we have to force interpreter on that call.
    if (ssc->GetStepDepth() == JDWP::SD_INTO) {
      return true;
    }
  }
  return false;
}

bool Dbg::IsForcedInterpreterNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
  instrumentation::Instrumentation* const instrumentation =
      Runtime::Current()->GetInstrumentation();
  // If we are in interpreter only mode, then we don't have to force interpreter.
  if (instrumentation->InterpretOnly()) {
    return false;
  }
  // We can only interpret pure Java method.
  if (m->IsNative() || m->IsProxyMethod()) {
    return false;
  }
  const SingleStepControl* const ssc = thread->GetSingleStepControl();
  if (ssc != nullptr) {
    // If we want to step into a method, then we have to force interpreter on that call.
    if (ssc->GetStepDepth() == JDWP::SD_INTO) {
      return true;
    }
    // If we are stepping out from a static initializer, by issuing a step
    // in or step over, that was implicitly invoked by calling a static method,
    // then we need to step into that method. Having a lower stack depth than
    // the one the single step control has indicates that the step originates
    // from the static initializer.
    if (ssc->GetStepDepth() != JDWP::SD_OUT &&
        ssc->GetStackDepth() > GetStackDepth(thread)) {
      return true;
    }
  }
  // There are cases where we have to force interpreter on deoptimized methods,
  // because in some cases the call will not be performed by invoking an entry
  // point that has been replaced by the deoptimization, but instead by directly
  // invoking the compiled code of the method, for example.
  return instrumentation->IsDeoptimized(m);
}

bool Dbg::IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
  // The upcall can be null and in that case we don't need to do anything.
  if (m == nullptr) {
    return false;
  }
  instrumentation::Instrumentation* const instrumentation =
      Runtime::Current()->GetInstrumentation();
  // If we are in interpreter only mode, then we don't have to force interpreter.
  if (instrumentation->InterpretOnly()) {
    return false;
  }
  // We can only interpret pure Java method.
  if (m->IsNative() || m->IsProxyMethod()) {
    return false;
  }
  const SingleStepControl* const ssc = thread->GetSingleStepControl();
  if (ssc != nullptr) {
    // If we are stepping out from a static initializer, by issuing a step
    // out, that was implicitly invoked by calling a static method, then we
    // need to step into the caller of that method. Having a lower stack
    // depth than the one the single step control has indicates that the
    // step originates from the static initializer.
    if (ssc->GetStepDepth() == JDWP::SD_OUT &&
        ssc->GetStackDepth() > GetStackDepth(thread)) {
      return true;
    }
  }
  // If we are returning from a static intializer, that was implicitly
  // invoked by calling a static method and the caller is deoptimized,
  // then we have to deoptimize the stack without forcing interpreter
  // on the static method that was called originally. This problem can
  // be solved easily by forcing instrumentation on the called method,
  // because the instrumentation exit hook will recognise the need of
  // stack deoptimization by calling IsForcedInterpreterNeededForUpcall.
  return instrumentation->IsDeoptimized(m);
}

bool Dbg::IsForcedInterpreterNeededForUpcallImpl(Thread* thread, ArtMethod* m) {
  // The upcall can be null and in that case we don't need to do anything.
  if (m == nullptr) {
    return false;
  }
  instrumentation::Instrumentation* const instrumentation =
      Runtime::Current()->GetInstrumentation();
  // If we are in interpreter only mode, then we don't have to force interpreter.
  if (instrumentation->InterpretOnly()) {
    return false;
  }
  // We can only interpret pure Java method.
  if (m->IsNative() || m->IsProxyMethod()) {
    return false;
  }
  const SingleStepControl* const ssc = thread->GetSingleStepControl();
  if (ssc != nullptr) {
    // The debugger is not interested in what is happening under the level
    // of the step, thus we only force interpreter when we are not below of
    // the step.
    if (ssc->GetStackDepth() >= GetStackDepth(thread)) {
      return true;
    }
  }
  // We have to require stack deoptimization if the upcall is deoptimized.
  return instrumentation->IsDeoptimized(m);
}

// Scoped utility class to suspend a thread so that we may do tasks such as walk its stack. Doesn't
// cause suspension if the thread is the current thread.
class ScopedThreadSuspension {
 public:
  ScopedThreadSuspension(Thread* self, JDWP::ObjectId thread_id)
      REQUIRES(!Locks::thread_list_lock_)
      SHARED_REQUIRES(Locks::mutator_lock_) :
      thread_(nullptr),
      error_(JDWP::ERR_NONE),
      self_suspend_(false),
      other_suspend_(false) {
    ScopedObjectAccessUnchecked soa(self);
    thread_ = DecodeThread(soa, thread_id, &error_);
    if (error_ == JDWP::ERR_NONE) {
      if (thread_ == soa.Self()) {
        self_suspend_ = true;
      } else {
        soa.Self()->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension);
        jobject thread_peer = Dbg::GetObjectRegistry()->GetJObject(thread_id);
        bool timed_out;
        ThreadList* thread_list = Runtime::Current()->GetThreadList();
        Thread* suspended_thread = thread_list->SuspendThreadByPeer(thread_peer, true, true,
                                                                    &timed_out);
        CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kWaitingForDebuggerSuspension);
        if (suspended_thread == nullptr) {
          // Thread terminated from under us while suspending.
          error_ = JDWP::ERR_INVALID_THREAD;
        } else {
          CHECK_EQ(suspended_thread, thread_);
          other_suspend_ = true;
        }
      }
    }
  }

  Thread* GetThread() const {
    return thread_;
  }

  JDWP::JdwpError GetError() const {
    return error_;
  }

  ~ScopedThreadSuspension() {
    if (other_suspend_) {
      Runtime::Current()->GetThreadList()->Resume(thread_, true);
    }
  }

 private:
  Thread* thread_;
  JDWP::JdwpError error_;
  bool self_suspend_;
  bool other_suspend_;
};

JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize step_size,
                                   JDWP::JdwpStepDepth step_depth) {
  Thread* self = Thread::Current();
  ScopedThreadSuspension sts(self, thread_id);
  if (sts.GetError() != JDWP::ERR_NONE) {
    return sts.GetError();
  }

  // Work out what ArtMethod* we're in, the current line number, and how deep the stack currently
  // is for step-out.
  struct SingleStepStackVisitor : public StackVisitor {
    explicit SingleStepStackVisitor(Thread* thread) SHARED_REQUIRES(Locks::mutator_lock_)
        : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
          stack_depth(0),
          method(nullptr),
          line_number(-1) {}

    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
    // annotalysis.
    bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
      ArtMethod* m = GetMethod();
      if (!m->IsRuntimeMethod()) {
        ++stack_depth;
        if (method == nullptr) {
          mirror::DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
          method = m;
          if (dex_cache != nullptr) {
            const DexFile& dex_file = *dex_cache->GetDexFile();
            line_number = dex_file.GetLineNumFromPC(m, GetDexPc());
          }
        }
      }
      return true;
    }

    int stack_depth;
    ArtMethod* method;
    int32_t line_number;
  };

  Thread* const thread = sts.GetThread();
  SingleStepStackVisitor visitor(thread);
  visitor.WalkStack();

  // Find the dex_pc values that correspond to the current line, for line-based single-stepping.
  struct DebugCallbackContext {
    explicit DebugCallbackContext(SingleStepControl* single_step_control_cb,
                                  int32_t line_number_cb, const DexFile::CodeItem* code_item)
      : single_step_control_(single_step_control_cb), line_number_(line_number_cb),
        code_item_(code_item), last_pc_valid(false), last_pc(0) {
    }

    static bool Callback(void* raw_context, uint32_t address, uint32_t line_number_cb) {
      DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context);
      if (static_cast<int32_t>(line_number_cb) == context->line_number_) {
        if (!context->last_pc_valid) {
          // Everything from this address until the next line change is ours.
          context->last_pc = address;
          context->last_pc_valid = true;
        }
        // Otherwise, if we're already in a valid range for this line,
        // just keep going (shouldn't really happen)...
      } else if (context->last_pc_valid) {  // and the line number is new
        // Add everything from the last entry up until here to the set
        for (uint32_t dex_pc = context->last_pc; dex_pc < address; ++dex_pc) {
          context->single_step_control_->AddDexPc(dex_pc);
        }
        context->last_pc_valid = false;
      }
      return false;  // There may be multiple entries for any given line.
    }

    ~DebugCallbackContext() {
      // If the line number was the last in the position table...
      if (last_pc_valid) {
        size_t end = code_item_->insns_size_in_code_units_;
        for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) {
          single_step_control_->AddDexPc(dex_pc);
        }
      }
    }

    SingleStepControl* const single_step_control_;
    const int32_t line_number_;
    const DexFile::CodeItem* const code_item_;
    bool last_pc_valid;
    uint32_t last_pc;
  };

  // Allocate single step.
  SingleStepControl* single_step_control =
      new (std::nothrow) SingleStepControl(step_size, step_depth,
                                           visitor.stack_depth, visitor.method);
  if (single_step_control == nullptr) {
    LOG(ERROR) << "Failed to allocate SingleStepControl";
    return JDWP::ERR_OUT_OF_MEMORY;
  }

  ArtMethod* m = single_step_control->GetMethod();
  const int32_t line_number = visitor.line_number;
  // Note: if the thread is not running Java code (pure native thread), there is no "current"
  // method on the stack (and no line number either).
  if (m != nullptr && !m->IsNative()) {
    const DexFile::CodeItem* const code_item = m->GetCodeItem();
    DebugCallbackContext context(single_step_control, line_number, code_item);
    m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
                                     DebugCallbackContext::Callback, nullptr, &context);
  }

  // Activate single-step in the thread.
  thread->ActivateSingleStepControl(single_step_control);

  if (VLOG_IS_ON(jdwp)) {
    VLOG(jdwp) << "Single-step thread: " << *thread;
    VLOG(jdwp) << "Single-step step size: " << single_step_control->GetStepSize();
    VLOG(jdwp) << "Single-step step depth: " << single_step_control->GetStepDepth();
    VLOG(jdwp) << "Single-step current method: " << PrettyMethod(single_step_control->GetMethod());
    VLOG(jdwp) << "Single-step current line: " << line_number;
    VLOG(jdwp) << "Single-step current stack depth: " << single_step_control->GetStackDepth();
    VLOG(jdwp) << "Single-step dex_pc values:";
    for (uint32_t dex_pc : single_step_control->GetDexPcs()) {
      VLOG(jdwp) << StringPrintf(" %#x", dex_pc);
    }
  }

  return JDWP::ERR_NONE;
}

void Dbg::UnconfigureStep(JDWP::ObjectId thread_id) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  JDWP::JdwpError error;
  Thread* thread = DecodeThread(soa, thread_id, &error);
  if (error == JDWP::ERR_NONE) {
    thread->DeactivateSingleStepControl();
  }
}

static char JdwpTagToShortyChar(JDWP::JdwpTag tag) {
  switch (tag) {
    default:
      LOG(FATAL) << "unknown JDWP tag: " << PrintableChar(tag);
      UNREACHABLE();

    // Primitives.
    case JDWP::JT_BYTE:    return 'B';
    case JDWP::JT_CHAR:    return 'C';
    case JDWP::JT_FLOAT:   return 'F';
    case JDWP::JT_DOUBLE:  return 'D';
    case JDWP::JT_INT:     return 'I';
    case JDWP::JT_LONG:    return 'J';
    case JDWP::JT_SHORT:   return 'S';
    case JDWP::JT_VOID:    return 'V';
    case JDWP::JT_BOOLEAN: return 'Z';

    // Reference types.
    case JDWP::JT_ARRAY:
    case JDWP::JT_OBJECT:
    case JDWP::JT_STRING:
    case JDWP::JT_THREAD:
    case JDWP::JT_THREAD_GROUP:
    case JDWP::JT_CLASS_LOADER:
    case JDWP::JT_CLASS_OBJECT:
      return 'L';
  }
}

JDWP::JdwpError Dbg::PrepareInvokeMethod(uint32_t request_id, JDWP::ObjectId thread_id,
                                         JDWP::ObjectId object_id, JDWP::RefTypeId class_id,
                                         JDWP::MethodId method_id, uint32_t arg_count,
                                         uint64_t arg_values[], JDWP::JdwpTag* arg_types,
                                         uint32_t options) {
  Thread* const self = Thread::Current();
  CHECK_EQ(self, GetDebugThread()) << "This must be called by the JDWP thread";

  ThreadList* thread_list = Runtime::Current()->GetThreadList();
  Thread* targetThread = nullptr;
  {
    ScopedObjectAccessUnchecked soa(self);
    JDWP::JdwpError error;
    targetThread = DecodeThread(soa, thread_id, &error);
    if (error != JDWP::ERR_NONE) {
      LOG(ERROR) << "InvokeMethod request for invalid thread id " << thread_id;
      return error;
    }
    if (targetThread->GetInvokeReq() != nullptr) {
      // Thread is already invoking a method on behalf of the debugger.
      LOG(ERROR) << "InvokeMethod request for thread already invoking a method: " << *targetThread;
      return JDWP::ERR_ALREADY_INVOKING;
    }
    if (!targetThread->IsReadyForDebugInvoke()) {
      // Thread is not suspended by an event so it cannot invoke a method.
      LOG(ERROR) << "InvokeMethod request for thread not stopped by event: " << *targetThread;
      return JDWP::ERR_INVALID_THREAD;
    }

    /*
     * We currently have a bug where we don't successfully resume the
     * target thread if the suspend count is too deep.  We're expected to
     * require one "resume" for each "suspend", but when asked to execute
     * a method we have to resume fully and then re-suspend it back to the
     * same level.  (The easiest way to cause this is to type "suspend"
     * multiple times in jdb.)
     *
     * It's unclear what this means when the event specifies "resume all"
     * and some threads are suspended more deeply than others.  This is
     * a rare problem, so for now we just prevent it from hanging forever
     * by rejecting the method invocation request.  Without this, we will
     * be stuck waiting on a suspended thread.
     */
    int suspend_count;
    {
      MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_);
      suspend_count = targetThread->GetSuspendCount();
    }
    if (suspend_count > 1) {
      LOG(ERROR) << *targetThread << " suspend count too deep for method invocation: " << suspend_count;
      return JDWP::ERR_THREAD_SUSPENDED;  // Probably not expected here.
    }

    mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id, &error);
    if (error != JDWP::ERR_NONE) {
      return JDWP::ERR_INVALID_OBJECT;
    }

    gRegistry->Get<mirror::Object*>(thread_id, &error);
    if (error != JDWP::ERR_NONE) {
      return JDWP::ERR_INVALID_OBJECT;
    }

    mirror::Class* c = DecodeClass(class_id, &error);
    if (c == nullptr) {
      return error;
    }

    ArtMethod* m = FromMethodId(method_id);
    if (m->IsStatic() != (receiver == nullptr)) {
      return JDWP::ERR_INVALID_METHODID;
    }
    if (m->IsStatic()) {
      if (m->GetDeclaringClass() != c) {
        return JDWP::ERR_INVALID_METHODID;
      }
    } else {
      if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
        return JDWP::ERR_INVALID_METHODID;
      }
    }

    // Check the argument list matches the method.
    uint32_t shorty_len = 0;
    const char* shorty = m->GetShorty(&shorty_len);
    if (shorty_len - 1 != arg_count) {
      return JDWP::ERR_ILLEGAL_ARGUMENT;
    }

    {
      StackHandleScope<2> hs(soa.Self());
      HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver));
      HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c));
      const DexFile::TypeList* types = m->GetParameterTypeList();
      for (size_t i = 0; i < arg_count; ++i) {
        if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) {
          return JDWP::ERR_ILLEGAL_ARGUMENT;
        }

        if (shorty[i + 1] == 'L') {
          // Did we really get an argument of an appropriate reference type?
          mirror::Class* parameter_type =
              m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true);
          mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error);
          if (error != JDWP::ERR_NONE) {
            return JDWP::ERR_INVALID_OBJECT;
          }
          if (argument != nullptr && !argument->InstanceOf(parameter_type)) {
            return JDWP::ERR_ILLEGAL_ARGUMENT;
          }

          // Turn the on-the-wire ObjectId into a jobject.
          jvalue& v = reinterpret_cast<jvalue&>(arg_values[i]);
          v.l = gRegistry->GetJObject(arg_values[i]);
        }
      }
    }

    // Allocates a DebugInvokeReq.
    DebugInvokeReq* req = new (std::nothrow) DebugInvokeReq(request_id, thread_id, receiver, c, m,
                                                            options, arg_values, arg_count);
    if (req == nullptr) {
      LOG(ERROR) << "Failed to allocate DebugInvokeReq";
      return JDWP::ERR_OUT_OF_MEMORY;
    }

    // Attaches the DebugInvokeReq to the target thread so it executes the method when
    // it is resumed. Once the invocation completes, the target thread will delete it before
    // suspending itself (see ThreadList::SuspendSelfForDebugger).
    targetThread->SetDebugInvokeReq(req);
  }

  // The fact that we've released the thread list lock is a bit risky --- if the thread goes
  // away we're sitting high and dry -- but we must release this before the UndoDebuggerSuspensions
  // call.

  if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
    VLOG(jdwp) << "      Resuming all threads";
    thread_list->UndoDebuggerSuspensions();
  } else {
    VLOG(jdwp) << "      Resuming event thread only";
    thread_list->Resume(targetThread, true);
  }

  return JDWP::ERR_NONE;
}

void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
  Thread* const self = Thread::Current();
  CHECK_NE(self, GetDebugThread()) << "This must be called by the event thread";

  ScopedObjectAccess soa(self);

  // We can be called while an exception is pending. We need
  // to preserve that across the method invocation.
  StackHandleScope<1> hs(soa.Self());
  Handle<mirror::Throwable> old_exception = hs.NewHandle(soa.Self()->GetException());
  soa.Self()->ClearException();

  // Execute the method then sends reply to the debugger.
  ExecuteMethodWithoutPendingException(soa, pReq);

  // If an exception was pending before the invoke, restore it now.
  if (old_exception.Get() != nullptr) {
    soa.Self()->SetException(old_exception.Get());
  }
}

// Helper function: write a variable-width value into the output input buffer.
static void WriteValue(JDWP::ExpandBuf* pReply, int width, uint64_t value) {
  switch (width) {
    case 1:
      expandBufAdd1(pReply, value);
      break;
    case 2:
      expandBufAdd2BE(pReply, value);
      break;
    case 4:
      expandBufAdd4BE(pReply, value);
      break;
    case 8:
      expandBufAdd8BE(pReply, value);
      break;
    default:
      LOG(FATAL) << width;
      UNREACHABLE();
  }
}

void Dbg::ExecuteMethodWithoutPendingException(ScopedObjectAccess& soa, DebugInvokeReq* pReq) {
  soa.Self()->AssertNoPendingException();

  // Translate the method through the vtable, unless the debugger wants to suppress it.
  ArtMethod* m = pReq->method;
  size_t image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
  if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver.Read() != nullptr) {
    ArtMethod* actual_method =
        pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m, image_pointer_size);
    if (actual_method != m) {
      VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m)
                 << " to " << PrettyMethod(actual_method);
      m = actual_method;
    }
  }
  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m)
             << " receiver=" << pReq->receiver.Read()
             << " arg_count=" << pReq->arg_count;
  CHECK(m != nullptr);

  static_assert(sizeof(jvalue) == sizeof(uint64_t), "jvalue and uint64_t have different sizes.");

  // Invoke the method.
  ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(pReq->receiver.Read()));
  JValue result = InvokeWithJValues(soa, ref.get(), soa.EncodeMethod(m),
                                    reinterpret_cast<jvalue*>(pReq->arg_values.get()));

  // Prepare JDWP ids for the reply.
  JDWP::JdwpTag result_tag = BasicTagFromDescriptor(m->GetShorty());
  const bool is_object_result = (result_tag == JDWP::JT_OBJECT);
  StackHandleScope<2> hs(soa.Self());
  Handle<mirror::Object> object_result = hs.NewHandle(is_object_result ? result.GetL() : nullptr);
  Handle<mirror::Throwable> exception = hs.NewHandle(soa.Self()->GetException());
  soa.Self()->ClearException();

  if (!IsDebuggerActive()) {
    // The debugger detached: we must not re-suspend threads. We also don't need to fill the reply
    // because it won't be sent either.
    return;
  }

  JDWP::ObjectId exceptionObjectId = gRegistry->Add(exception);
  uint64_t result_value = 0;
  if (exceptionObjectId != 0) {
    VLOG(jdwp) << "  JDWP invocation returning with exception=" << exception.Get()
               << " " << exception->Dump();
    result_value = 0;
  } else if (is_object_result) {
    /* if no exception was thrown, examine object result more closely */
    JDWP::JdwpTag new_tag = TagFromObject(soa, object_result.Get());
    if (new_tag != result_tag) {
      VLOG(jdwp) << "  JDWP promoted result from " << result_tag << " to " << new_tag;
      result_tag = new_tag;
    }

    // Register the object in the registry and reference its ObjectId. This ensures
    // GC safety and prevents from accessing stale reference if the object is moved.
    result_value = gRegistry->Add(object_result.Get());
  } else {
    // Primitive result.
    DCHECK(IsPrimitiveTag(result_tag));
    result_value = result.GetJ();
  }
  const bool is_constructor = m->IsConstructor() && !m->IsStatic();
  if (is_constructor) {
    // If we invoked a constructor (which actually returns void), return the receiver,
    // unless we threw, in which case we return null.
    result_tag = JDWP::JT_OBJECT;
    if (exceptionObjectId == 0) {
      // TODO we could keep the receiver ObjectId in the DebugInvokeReq to avoid looking into the
      // object registry.
      result_value = GetObjectRegistry()->Add(pReq->receiver.Read());
    } else {
      result_value = 0;
    }
  }

  // Suspend other threads if the invoke is not single-threaded.
  if ((pReq->options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
    soa.Self()->TransitionFromRunnableToSuspended(kWaitingForDebuggerSuspension);
    VLOG(jdwp) << "      Suspending all threads";
    Runtime::Current()->GetThreadList()->SuspendAllForDebugger();
    soa.Self()->TransitionFromSuspendedToRunnable();
  }

  VLOG(jdwp) << "  --> returned " << result_tag
             << StringPrintf(" %#" PRIx64 " (except=%#" PRIx64 ")", result_value,
                             exceptionObjectId);

  // Show detailed debug output.
  if (result_tag == JDWP::JT_STRING && exceptionObjectId == 0) {
    if (result_value != 0) {
      if (VLOG_IS_ON(jdwp)) {
        std::string result_string;
        JDWP::JdwpError error = Dbg::StringToUtf8(result_value, &result_string);
        CHECK_EQ(error, JDWP::ERR_NONE);
        VLOG(jdwp) << "      string '" << result_string << "'";
      }
    } else {
      VLOG(jdwp) << "      string (null)";
    }
  }

  // Attach the reply to DebugInvokeReq so it can be sent to the debugger when the event thread
  // is ready to suspend.
  BuildInvokeReply(pReq->reply, pReq->request_id, result_tag, result_value, exceptionObjectId);
}

void Dbg::BuildInvokeReply(JDWP::ExpandBuf* pReply, uint32_t request_id, JDWP::JdwpTag result_tag,
                           uint64_t result_value, JDWP::ObjectId exception) {
  // Make room for the JDWP header since we do not know the size of the reply yet.
  JDWP::expandBufAddSpace(pReply, kJDWPHeaderLen);

  size_t width = GetTagWidth(result_tag);
  JDWP::expandBufAdd1(pReply, result_tag);
  if (width != 0) {
    WriteValue(pReply, width, result_value);
  }
  JDWP::expandBufAdd1(pReply, JDWP::JT_OBJECT);
  JDWP::expandBufAddObjectId(pReply, exception);

  // Now we know the size, we can complete the JDWP header.
  uint8_t* buf = expandBufGetBuffer(pReply);
  JDWP::Set4BE(buf + kJDWPHeaderSizeOffset, expandBufGetLength(pReply));
  JDWP::Set4BE(buf + kJDWPHeaderIdOffset, request_id);
  JDWP::Set1(buf + kJDWPHeaderFlagsOffset, kJDWPFlagReply);  // flags
  JDWP::Set2BE(buf + kJDWPHeaderErrorCodeOffset, JDWP::ERR_NONE);
}

void Dbg::FinishInvokeMethod(DebugInvokeReq* pReq) {
  CHECK_NE(Thread::Current(), GetDebugThread()) << "This must be called by the event thread";

  JDWP::ExpandBuf* const pReply = pReq->reply;
  CHECK(pReply != nullptr) << "No reply attached to DebugInvokeReq";

  // We need to prevent other threads (including JDWP thread) from interacting with the debugger
  // while we send the reply but are not yet suspended. The JDWP token will be released just before
  // we suspend ourself again (see ThreadList::SuspendSelfForDebugger).
  gJdwpState->AcquireJdwpTokenForEvent(pReq->thread_id);

  // Send the reply unless the debugger detached before the completion of the method.
  if (IsDebuggerActive()) {
    const size_t replyDataLength = expandBufGetLength(pReply) - kJDWPHeaderLen;
    VLOG(jdwp) << StringPrintf("REPLY INVOKE id=0x%06x (length=%zu)",
                               pReq->request_id, replyDataLength);

    gJdwpState->SendRequest(pReply);
  } else {
    VLOG(jdwp) << "Not sending invoke reply because debugger detached";
  }
}

/*
 * "request" contains a full JDWP packet, possibly with multiple chunks.  We
 * need to process each, accumulate the replies, and ship the whole thing
 * back.
 *
 * Returns "true" if we have a reply.  The reply buffer is newly allocated,
 * and includes the chunk type/length, followed by the data.
 *
 * OLD-TODO: we currently assume that the request and reply include a single
 * chunk.  If this becomes inconvenient we will need to adapt.
 */
bool Dbg::DdmHandlePacket(JDWP::Request* request, uint8_t** pReplyBuf, int* pReplyLen) {
  Thread* self = Thread::Current();
  JNIEnv* env = self->GetJniEnv();

  uint32_t type = request->ReadUnsigned32("type");
  uint32_t length = request->ReadUnsigned32("length");

  // Create a byte[] corresponding to 'request'.
  size_t request_length = request->size();
  ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(request_length));
  if (dataArray.get() == nullptr) {
    LOG(WARNING) << "byte[] allocation failed: " << request_length;
    env->ExceptionClear();
    return false;
  }
  env->SetByteArrayRegion(dataArray.get(), 0, request_length,
                          reinterpret_cast<const jbyte*>(request->data()));
  request->Skip(request_length);

  // Run through and find all chunks.  [Currently just find the first.]
  ScopedByteArrayRO contents(env, dataArray.get());
  if (length != request_length) {
    LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%zd)", length, request_length);
    return false;
  }

  // Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)".
  ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
                                                                 WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch,
                                                                 type, dataArray.get(), 0, length));
  if (env->ExceptionCheck()) {
    LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type);
    env->ExceptionDescribe();
    env->ExceptionClear();
    return false;
  }

  if (chunk.get() == nullptr) {
    return false;
  }

  /*
   * Pull the pieces out of the chunk.  We copy the results into a
   * newly-allocated buffer that the caller can free.  We don't want to
   * continue using the Chunk object because nothing has a reference to it.
   *
   * We could avoid this by returning type/data/offset/length and having
   * the caller be aware of the object lifetime issues, but that
   * integrates the JDWP code more tightly into the rest of the runtime, and doesn't work
   * if we have responses for multiple chunks.
   *
   * So we're pretty much stuck with copying data around multiple times.
   */
  ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data)));
  jint offset = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset);
  length = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length);
  type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type);

  VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length);
  if (length == 0 || replyData.get() == nullptr) {
    return false;
  }

  const int kChunkHdrLen = 8;
  uint8_t* reply = new uint8_t[length + kChunkHdrLen];
  if (reply == nullptr) {
    LOG(WARNING) << "malloc failed: " << (length + kChunkHdrLen);
    return false;
  }
  JDWP::Set4BE(reply + 0, type);
  JDWP::Set4BE(reply + 4, length);
  env->GetByteArrayRegion(replyData.get(), offset, length, reinterpret_cast<jbyte*>(reply + kChunkHdrLen));

  *pReplyBuf = reply;
  *pReplyLen = length + kChunkHdrLen;

  VLOG(jdwp) << StringPrintf("dvmHandleDdm returning type=%.4s %p len=%d", reinterpret_cast<char*>(reply), reply, length);
  return true;
}

void Dbg::DdmBroadcast(bool connect) {
  VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "...";

  Thread* self = Thread::Current();
  if (self->GetState() != kRunnable) {
    LOG(ERROR) << "DDM broadcast in thread state " << self->GetState();
    /* try anyway? */
  }

  JNIEnv* env = self->GetJniEnv();
  jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/;
  env->CallStaticVoidMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
                            WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast,
                            event);
  if (env->ExceptionCheck()) {
    LOG(ERROR) << "DdmServer.broadcast " << event << " failed";
    env->ExceptionDescribe();
    env->ExceptionClear();
  }
}

void Dbg::DdmConnected() {
  Dbg::DdmBroadcast(true);
}

void Dbg::DdmDisconnected() {
  Dbg::DdmBroadcast(false);
  gDdmThreadNotification = false;
}

/*
 * Send a notification when a thread starts, stops, or changes its name.
 *
 * Because we broadcast the full set of threads when the notifications are
 * first enabled, it's possible for "thread" to be actively executing.
 */
void Dbg::DdmSendThreadNotification(Thread* t, uint32_t type) {
  if (!gDdmThreadNotification) {
    return;
  }

  if (type == CHUNK_TYPE("THDE")) {
    uint8_t buf[4];
    JDWP::Set4BE(&buf[0], t->GetThreadId());
    Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf);
  } else {
    CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
    ScopedObjectAccessUnchecked soa(Thread::Current());
    StackHandleScope<1> hs(soa.Self());
    Handle<mirror::String> name(hs.NewHandle(t->GetThreadName(soa)));
    size_t char_count = (name.Get() != nullptr) ? name->GetLength() : 0;
    const jchar* chars = (name.Get() != nullptr) ? name->GetValue() : nullptr;

    std::vector<uint8_t> bytes;
    JDWP::Append4BE(bytes, t->GetThreadId());
    JDWP::AppendUtf16BE(bytes, chars, char_count);
    CHECK_EQ(bytes.size(), char_count*2 + sizeof(uint32_t)*2);
    Dbg::DdmSendChunk(type, bytes);
  }
}

void Dbg::DdmSetThreadNotification(bool enable) {
  // Enable/disable thread notifications.
  gDdmThreadNotification = enable;
  if (enable) {
    // Suspend the VM then post thread start notifications for all threads. Threads attaching will
    // see a suspension in progress and block until that ends. They then post their own start
    // notification.
    SuspendVM();
    std::list<Thread*> threads;
    Thread* self = Thread::Current();
    {
      MutexLock mu(self, *Locks::thread_list_lock_);
      threads = Runtime::Current()->GetThreadList()->GetList();
    }
    {
      ScopedObjectAccess soa(self);
      for (Thread* thread : threads) {
        Dbg::DdmSendThreadNotification(thread, CHUNK_TYPE("THCR"));
      }
    }
    ResumeVM();
  }
}

void Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) {
  if (IsDebuggerActive()) {
    gJdwpState->PostThreadChange(t, type == CHUNK_TYPE("THCR"));
  }
  Dbg::DdmSendThreadNotification(t, type);
}

void Dbg::PostThreadStart(Thread* t) {
  Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THCR"));
}

void Dbg::PostThreadDeath(Thread* t) {
  Dbg::PostThreadStartOrStop(t, CHUNK_TYPE("THDE"));
}

void Dbg::DdmSendChunk(uint32_t type, size_t byte_count, const uint8_t* buf) {
  CHECK(buf != nullptr);
  iovec vec[1];
  vec[0].iov_base = reinterpret_cast<void*>(const_cast<uint8_t*>(buf));
  vec[0].iov_len = byte_count;
  Dbg::DdmSendChunkV(type, vec, 1);
}

void Dbg::DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes) {
  DdmSendChunk(type, bytes.size(), &bytes[0]);
}

void Dbg::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
  if (gJdwpState == nullptr) {
    VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type;
  } else {
    gJdwpState->DdmSendChunkV(type, iov, iov_count);
  }
}

JDWP::JdwpState* Dbg::GetJdwpState() {
  return gJdwpState;
}

int Dbg::DdmHandleHpifChunk(HpifWhen when) {
  if (when == HPIF_WHEN_NOW) {
    DdmSendHeapInfo(when);
    return true;
  }

  if (when != HPIF_WHEN_NEVER && when != HPIF_WHEN_NEXT_GC && when != HPIF_WHEN_EVERY_GC) {
    LOG(ERROR) << "invalid HpifWhen value: " << static_cast<int>(when);
    return false;
  }

  gDdmHpifWhen = when;
  return true;
}

bool Dbg::DdmHandleHpsgNhsgChunk(Dbg::HpsgWhen when, Dbg::HpsgWhat what, bool native) {
  if (when != HPSG_WHEN_NEVER && when != HPSG_WHEN_EVERY_GC) {
    LOG(ERROR) << "invalid HpsgWhen value: " << static_cast<int>(when);
    return false;
  }

  if (what != HPSG_WHAT_MERGED_OBJECTS && what != HPSG_WHAT_DISTINCT_OBJECTS) {
    LOG(ERROR) << "invalid HpsgWhat value: " << static_cast<int>(what);
    return false;
  }

  if (native) {
    gDdmNhsgWhen = when;
    gDdmNhsgWhat = what;
  } else {
    gDdmHpsgWhen = when;
    gDdmHpsgWhat = what;
  }
  return true;
}

void Dbg::DdmSendHeapInfo(HpifWhen reason) {
  // If there's a one-shot 'when', reset it.
  if (reason == gDdmHpifWhen) {
    if (gDdmHpifWhen == HPIF_WHEN_NEXT_GC) {
      gDdmHpifWhen = HPIF_WHEN_NEVER;
    }
  }

  /*
   * Chunk HPIF (client --> server)
   *
   * Heap Info. General information about the heap,
   * suitable for a summary display.
   *
   *   [u4]: number of heaps
   *
   *   For each heap:
   *     [u4]: heap ID
   *     [u8]: timestamp in ms since Unix epoch
   *     [u1]: capture reason (same as 'when' value from server)
   *     [u4]: max heap size in bytes (-Xmx)
   *     [u4]: current heap size in bytes
   *     [u4]: current number of bytes allocated
   *     [u4]: current number of objects allocated
   */
  uint8_t heap_count = 1;
  gc::Heap* heap = Runtime::Current()->GetHeap();
  std::vector<uint8_t> bytes;
  JDWP::Append4BE(bytes, heap_count);
  JDWP::Append4BE(bytes, 1);  // Heap id (bogus; we only have one heap).
  JDWP::Append8BE(bytes, MilliTime());
  JDWP::Append1BE(bytes, reason);
  JDWP::Append4BE(bytes, heap->GetMaxMemory());  // Max allowed heap size in bytes.
  JDWP::Append4BE(bytes, heap->GetTotalMemory());  // Current heap size in bytes.
  JDWP::Append4BE(bytes, heap->GetBytesAllocated());
  JDWP::Append4BE(bytes, heap->GetObjectsAllocated());
  CHECK_EQ(bytes.size(), 4U + (heap_count * (4 + 8 + 1 + 4 + 4 + 4 + 4)));
  Dbg::DdmSendChunk(CHUNK_TYPE("HPIF"), bytes);
}

enum HpsgSolidity {
  SOLIDITY_FREE = 0,
  SOLIDITY_HARD = 1,
  SOLIDITY_SOFT = 2,
  SOLIDITY_WEAK = 3,
  SOLIDITY_PHANTOM = 4,
  SOLIDITY_FINALIZABLE = 5,
  SOLIDITY_SWEEP = 6,
};

enum HpsgKind {
  KIND_OBJECT = 0,
  KIND_CLASS_OBJECT = 1,
  KIND_ARRAY_1 = 2,
  KIND_ARRAY_2 = 3,
  KIND_ARRAY_4 = 4,
  KIND_ARRAY_8 = 5,
  KIND_UNKNOWN = 6,
  KIND_NATIVE = 7,
};

#define HPSG_PARTIAL (1<<7)
#define HPSG_STATE(solidity, kind) ((uint8_t)((((kind) & 0x7) << 3) | ((solidity) & 0x7)))

class HeapChunkContext {
 public:
  // Maximum chunk size.  Obtain this from the formula:
  // (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
  HeapChunkContext(bool merge, bool native)
      : buf_(16384 - 16),
        type_(0),
        chunk_overhead_(0) {
    Reset();
    if (native) {
      type_ = CHUNK_TYPE("NHSG");
    } else {
      type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO");
    }
  }

  ~HeapChunkContext() {
    if (p_ > &buf_[0]) {
      Flush();
    }
  }

  void SetChunkOverhead(size_t chunk_overhead) {
    chunk_overhead_ = chunk_overhead;
  }

  void ResetStartOfNextChunk() {
    startOfNextMemoryChunk_ = nullptr;
  }

  void EnsureHeader(const void* chunk_ptr) {
    if (!needHeader_) {
      return;
    }

    // Start a new HPSx chunk.
    JDWP::Write4BE(&p_, 1);  // Heap id (bogus; we only have one heap).
    JDWP::Write1BE(&p_, 8);  // Size of allocation unit, in bytes.

    JDWP::Write4BE(&p_, reinterpret_cast<uintptr_t>(chunk_ptr));  // virtual address of segment start.
    JDWP::Write4BE(&p_, 0);  // offset of this piece (relative to the virtual address).
    // [u4]: length of piece, in allocation units
    // We won't know this until we're done, so save the offset and stuff in a dummy value.
    pieceLenField_ = p_;
    JDWP::Write4BE(&p_, 0x55555555);
    needHeader_ = false;
  }

  void Flush() SHARED_REQUIRES(Locks::mutator_lock_) {
    if (pieceLenField_ == nullptr) {
      // Flush immediately post Reset (maybe back-to-back Flush). Ignore.
      CHECK(needHeader_);
      return;
    }
    // Patch the "length of piece" field.
    CHECK_LE(&buf_[0], pieceLenField_);
    CHECK_LE(pieceLenField_, p_);
    JDWP::Set4BE(pieceLenField_, totalAllocationUnits_);

    Dbg::DdmSendChunk(type_, p_ - &buf_[0], &buf_[0]);
    Reset();
  }

  static void HeapChunkJavaCallback(void* start, void* end, size_t used_bytes, void* arg)
      SHARED_REQUIRES(Locks::heap_bitmap_lock_,
                            Locks::mutator_lock_) {
    reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkJavaCallback(start, end, used_bytes);
  }

  static void HeapChunkNativeCallback(void* start, void* end, size_t used_bytes, void* arg)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkNativeCallback(start, end, used_bytes);
  }

 private:
  enum { ALLOCATION_UNIT_SIZE = 8 };

  void Reset() {
    p_ = &buf_[0];
    ResetStartOfNextChunk();
    totalAllocationUnits_ = 0;
    needHeader_ = true;
    pieceLenField_ = nullptr;
  }

  bool IsNative() const {
    return type_ == CHUNK_TYPE("NHSG");
  }

  // Returns true if the object is not an empty chunk.
  bool ProcessRecord(void* start, size_t used_bytes) SHARED_REQUIRES(Locks::mutator_lock_) {
    // Note: heap call backs cannot manipulate the heap upon which they are crawling, care is taken
    // in the following code not to allocate memory, by ensuring buf_ is of the correct size
    if (used_bytes == 0) {
      if (start == nullptr) {
        // Reset for start of new heap.
        startOfNextMemoryChunk_ = nullptr;
        Flush();
      }
      // Only process in use memory so that free region information
      // also includes dlmalloc book keeping.
      return false;
    }
    if (startOfNextMemoryChunk_ != nullptr) {
      // Transmit any pending free memory. Native free memory of over kMaxFreeLen could be because
      // of the use of mmaps, so don't report. If not free memory then start a new segment.
      bool flush = true;
      if (start > startOfNextMemoryChunk_) {
        const size_t kMaxFreeLen = 2 * kPageSize;
        void* free_start = startOfNextMemoryChunk_;
        void* free_end = start;
        const size_t free_len =
            reinterpret_cast<uintptr_t>(free_end) - reinterpret_cast<uintptr_t>(free_start);
        if (!IsNative() || free_len < kMaxFreeLen) {
          AppendChunk(HPSG_STATE(SOLIDITY_FREE, 0), free_start, free_len, IsNative());
          flush = false;
        }
      }
      if (flush) {
        startOfNextMemoryChunk_ = nullptr;
        Flush();
      }
    }
    return true;
  }

  void HeapChunkNativeCallback(void* start, void* /*end*/, size_t used_bytes)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    if (ProcessRecord(start, used_bytes)) {
      uint8_t state = ExamineNativeObject(start);
      AppendChunk(state, start, used_bytes + chunk_overhead_, true /*is_native*/);
      startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
    }
  }

  void HeapChunkJavaCallback(void* start, void* /*end*/, size_t used_bytes)
      SHARED_REQUIRES(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
    if (ProcessRecord(start, used_bytes)) {
      // Determine the type of this chunk.
      // OLD-TODO: if context.merge, see if this chunk is different from the last chunk.
      // If it's the same, we should combine them.
      uint8_t state = ExamineJavaObject(reinterpret_cast<mirror::Object*>(start));
      AppendChunk(state, start, used_bytes + chunk_overhead_, false /*is_native*/);
      startOfNextMemoryChunk_ = reinterpret_cast<char*>(start) + used_bytes + chunk_overhead_;
    }
  }

  void AppendChunk(uint8_t state, void* ptr, size_t length, bool is_native)
      SHARED_REQUIRES(Locks::mutator_lock_) {
    // Make sure there's enough room left in the buffer.
    // We need to use two bytes for every fractional 256 allocation units used by the chunk plus
    // 17 bytes for any header.
    const size_t needed = ((RoundUp(length / ALLOCATION_UNIT_SIZE, 256) / 256) * 2) + 17;
    size_t byte_left = &buf_.back() - p_;
    if (byte_left < needed) {
      if (is_native) {
      // Cannot trigger memory allocation while walking native heap.
        return;
      }
      Flush();
    }

    byte_left = &buf_.back() - p_;
    if (byte_left < needed) {
      LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << length << ", "
          << needed << " bytes)";
      return;
    }
    EnsureHeader(ptr);
    // Write out the chunk description.
    length /= ALLOCATION_UNIT_SIZE;   // Convert to allocation units.
    totalAllocationUnits_ += length;
    while (length > 256) {
      *p_++ = state | HPSG_PARTIAL;
      *p_++ = 255;     // length - 1
      length -= 256;
    }
    *p_++ = state;
    *p_++ = length - 1;
  }

  uint8_t ExamineNativeObject(const void* p) SHARED_REQUIRES(Locks::mutator_lock_) {
    return p == nullptr ? HPSG_STATE(SOLIDITY_FREE, 0) : HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
  }

  uint8_t ExamineJavaObject(mirror::Object* o)
      SHARED_REQUIRES(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
    if (o == nullptr) {
      return HPSG_STATE(SOLIDITY_FREE, 0);
    }
    // It's an allocated chunk. Figure out what it is.
    gc::Heap* heap = Runtime::Current()->GetHeap();
    if (!heap->IsLiveObjectLocked(o)) {
      LOG(ERROR) << "Invalid object in managed heap: " << o;
      return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
    }
    mirror::Class* c = o->GetClass();
    if (c == nullptr) {
      // The object was probably just created but hasn't been initialized yet.
      return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
    }
    if (!heap->IsValidObjectAddress(c)) {
      LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c;
      return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
    }
    if (c->GetClass() == nullptr) {
      LOG(ERROR) << "Null class of class " << c << " for object " << o;
      return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
    }
    if (c->IsClassClass()) {
      return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
    }
    if (c->IsArrayClass()) {
      switch (c->GetComponentSize()) {
      case 1: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_1);
      case 2: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_2);
      case 4: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
      case 8: return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_8);
      }
    }
    return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
  }

  std::vector<uint8_t> buf_;
  uint8_t* p_;
  uint8_t* pieceLenField_;
  void* startOfNextMemoryChunk_;
  size_t totalAllocationUnits_;
  uint32_t type_;
  bool needHeader_;
  size_t chunk_overhead_;

  DISALLOW_COPY_AND_ASSIGN(HeapChunkContext);
};

static void BumpPointerSpaceCallback(mirror::Object* obj, void* arg)
    SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
  const size_t size = RoundUp(obj->SizeOf(), kObjectAlignment);
  HeapChunkContext::HeapChunkJavaCallback(
      obj, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(obj) + size), size, arg);
}

void Dbg::DdmSendHeapSegments(bool native) {
  Dbg::HpsgWhen when = native ? gDdmNhsgWhen : gDdmHpsgWhen;
  Dbg::HpsgWhat what = native ? gDdmNhsgWhat : gDdmHpsgWhat;
  if (when == HPSG_WHEN_NEVER) {
    return;
  }
  // Figure out what kind of chunks we'll be sending.
  CHECK(what == HPSG_WHAT_MERGED_OBJECTS || what == HPSG_WHAT_DISTINCT_OBJECTS)
      << static_cast<int>(what);

  // First, send a heap start chunk.
  uint8_t heap_id[4];
  JDWP::Set4BE(&heap_id[0], 1);  // Heap id (bogus; we only have one heap).
  Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHST") : CHUNK_TYPE("HPST"), sizeof(heap_id), heap_id);
  Thread* self = Thread::Current();
  Locks::mutator_lock_->AssertSharedHeld(self);

  // Send a series of heap segment chunks.
  HeapChunkContext context(what == HPSG_WHAT_MERGED_OBJECTS, native);
  if (native) {
#if defined(__ANDROID__) && defined(USE_DLMALLOC)
    dlmalloc_inspect_all(HeapChunkContext::HeapChunkNativeCallback, &context);
    HeapChunkContext::HeapChunkNativeCallback(nullptr, nullptr, 0, &context);  // Indicate end of a space.
#else
    UNIMPLEMENTED(WARNING) << "Native heap inspection is only supported with dlmalloc";
#endif
  } else {
    gc::Heap* heap = Runtime::Current()->GetHeap();
    for (const auto& space : heap->GetContinuousSpaces()) {
      if (space->IsDlMallocSpace()) {
        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
        // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an
        // allocation then the first sizeof(size_t) may belong to it.
        context.SetChunkOverhead(sizeof(size_t));
        space->AsDlMallocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
      } else if (space->IsRosAllocSpace()) {
        context.SetChunkOverhead(0);
        // Need to acquire the mutator lock before the heap bitmap lock with exclusive access since
        // RosAlloc's internal logic doesn't know to release and reacquire the heap bitmap lock.
        self->TransitionFromRunnableToSuspended(kSuspended);
        ThreadList* tl = Runtime::Current()->GetThreadList();
        tl->SuspendAll(__FUNCTION__);
        {
          ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
          space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
        }
        tl->ResumeAll();
        self->TransitionFromSuspendedToRunnable();
      } else if (space->IsBumpPointerSpace()) {
        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
        context.SetChunkOverhead(0);
        space->AsBumpPointerSpace()->Walk(BumpPointerSpaceCallback, &context);
        HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
      } else if (space->IsRegionSpace()) {
        heap->IncrementDisableMovingGC(self);
        self->TransitionFromRunnableToSuspended(kSuspended);
        ThreadList* tl = Runtime::Current()->GetThreadList();
        tl->SuspendAll(__FUNCTION__);
        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
        context.SetChunkOverhead(0);
        space->AsRegionSpace()->Walk(BumpPointerSpaceCallback, &context);
        HeapChunkContext::HeapChunkJavaCallback(nullptr, nullptr, 0, &context);
        tl->ResumeAll();
        self->TransitionFromSuspendedToRunnable();
        heap->DecrementDisableMovingGC(self);
      } else {
        UNIMPLEMENTED(WARNING) << "Not counting objects in space " << *space;
      }
      context.ResetStartOfNextChunk();
    }
    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
    // Walk the large objects, these are not in the AllocSpace.
    context.SetChunkOverhead(0);
    heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkJavaCallback, &context);
  }

  // Finally, send a heap end chunk.
  Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id);
}

void Dbg::SetAllocTrackingEnabled(bool enable) {
  gc::AllocRecordObjectMap::SetAllocTrackingEnabled(enable);
}

void Dbg::DumpRecentAllocations() {
  ScopedObjectAccess soa(Thread::Current());
  MutexLock mu(soa.Self(), *Locks::alloc_tracker_lock_);
  if (!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled()) {
    LOG(INFO) << "Not recording tracked allocations";
    return;
  }
  gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
  CHECK(records != nullptr);

  const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize());
  uint16_t count = capped_count;

  LOG(INFO) << "Tracked allocations, (count=" << count << ")";
  for (auto it = records->RBegin(), end = records->REnd();
      count > 0 && it != end; count--, it++) {
    const gc::AllocRecord* record = it->second;

    LOG(INFO) << StringPrintf(" Thread %-2d %6zd bytes ", record->GetTid(), record->ByteCount())
              << PrettyClass(record->GetClass());

    for (size_t stack_frame = 0, depth = record->GetDepth(); stack_frame < depth; ++stack_frame) {
      const gc::AllocRecordStackTraceElement& stack_element = record->StackElement(stack_frame);
      ArtMethod* m = stack_element.GetMethod();
      LOG(INFO) << "    " << PrettyMethod(m) << " line " << stack_element.ComputeLineNumber();
    }

    // pause periodically to help logcat catch up
    if ((count % 5) == 0) {
      usleep(40000);
    }
  }
}

class StringTable {
 public:
  StringTable() {
  }

  void Add(const std::string& str) {
    table_.insert(str);
  }

  void Add(const char* str) {
    table_.insert(str);
  }

  size_t IndexOf(const char* s) const {
    auto it = table_.find(s);
    if (it == table_.end()) {
      LOG(FATAL) << "IndexOf(\"" << s << "\") failed";
    }
    return std::distance(table_.begin(), it);
  }

  size_t Size() const {
    return table_.size();
  }

  void WriteTo(std::vector<uint8_t>& bytes) const {
    for (const std::string& str : table_) {
      const char* s = str.c_str();
      size_t s_len = CountModifiedUtf8Chars(s);
      std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]);
      ConvertModifiedUtf8ToUtf16(s_utf16.get(), s);
      JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len);
    }
  }

 private:
  std::set<std::string> table_;
  DISALLOW_COPY_AND_ASSIGN(StringTable);
};

static const char* GetMethodSourceFile(ArtMethod* method)
    SHARED_REQUIRES(Locks::mutator_lock_) {
  DCHECK(method != nullptr);
  const char* source_file = method->GetDeclaringClassSourceFile();
  return (source_file != nullptr) ? source_file : "";
}

/*
 * The data we send to DDMS contains everything we have recorded.
 *
 * Message header (all values big-endian):
 * (1b) message header len (to allow future expansion); includes itself
 * (1b) entry header len
 * (1b) stack frame len
 * (2b) number of entries
 * (4b) offset to string table from start of message
 * (2b) number of class name strings
 * (2b) number of method name strings
 * (2b) number of source file name strings
 * For each entry:
 *   (4b) total allocation size
 *   (2b) thread id
 *   (2b) allocated object's class name index
 *   (1b) stack depth
 *   For each stack frame:
 *     (2b) method's class name
 *     (2b) method name
 *     (2b) method source file
 *     (2b) line number, clipped to 32767; -2 if native; -1 if no source
 * (xb) class name strings
 * (xb) method name strings
 * (xb) source file strings
 *
 * As with other DDM traffic, strings are sent as a 4-byte length
 * followed by UTF-16 data.
 *
 * We send up 16-bit unsigned indexes into string tables.  In theory there
 * can be (kMaxAllocRecordStackDepth * alloc_record_max_) unique strings in
 * each table, but in practice there should be far fewer.
 *
 * The chief reason for using a string table here is to keep the size of
 * the DDMS message to a minimum.  This is partly to make the protocol
 * efficient, but also because we have to form the whole thing up all at
 * once in a memory buffer.
 *
 * We use separate string tables for class names, method names, and source
 * files to keep the indexes small.  There will generally be no overlap
 * between the contents of these tables.
 */
jbyteArray Dbg::GetRecentAllocations() {
  if ((false)) {
    DumpRecentAllocations();
  }

  Thread* self = Thread::Current();
  std::vector<uint8_t> bytes;
  {
    MutexLock mu(self, *Locks::alloc_tracker_lock_);
    gc::AllocRecordObjectMap* records = Runtime::Current()->GetHeap()->GetAllocationRecords();
    // In case this method is called when allocation tracker is disabled,
    // we should still send some data back.
    gc::AllocRecordObjectMap dummy;
    if (records == nullptr) {
      CHECK(!Runtime::Current()->GetHeap()->IsAllocTrackingEnabled());
      records = &dummy;
    }
    // We don't need to wait on the condition variable records->new_record_condition_, because this
    // function only reads the class objects, which are already marked so it doesn't change their
    // reachability.

    //
    // Part 1: generate string tables.
    //
    StringTable class_names;
    StringTable method_names;
    StringTable filenames;

    const uint16_t capped_count = CappedAllocRecordCount(records->GetRecentAllocationSize());
    uint16_t count = capped_count;
    for (auto it = records->RBegin(), end = records->REnd();
         count > 0 && it != end; count--, it++) {
      const gc::AllocRecord* record = it->second;
      std::string temp;
      class_names.Add(record->GetClassDescriptor(&temp));
      for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
        ArtMethod* m = record->StackElement(i).GetMethod();
        class_names.Add(m->GetDeclaringClassDescriptor());
        method_names.Add(m->GetName());
        filenames.Add(GetMethodSourceFile(m));
      }
    }

    LOG(INFO) << "recent allocation records: " << capped_count;
    LOG(INFO) << "allocation records all objects: " << records->Size();

    //
    // Part 2: Generate the output and store it in the buffer.
    //

    // (1b) message header len (to allow future expansion); includes itself
    // (1b) entry header len
    // (1b) stack frame len
    const int kMessageHeaderLen = 15;
    const int kEntryHeaderLen = 9;
    const int kStackFrameLen = 8;
    JDWP::Append1BE(bytes, kMessageHeaderLen);
    JDWP::Append1BE(bytes, kEntryHeaderLen);
    JDWP::Append1BE(bytes, kStackFrameLen);

    // (2b) number of entries
    // (4b) offset to string table from start of message
    // (2b) number of class name strings
    // (2b) number of method name strings
    // (2b) number of source file name strings
    JDWP::Append2BE(bytes, capped_count);
    size_t string_table_offset = bytes.size();
    JDWP::Append4BE(bytes, 0);  // We'll patch this later...
    JDWP::Append2BE(bytes, class_names.Size());
    JDWP::Append2BE(bytes, method_names.Size());
    JDWP::Append2BE(bytes, filenames.Size());

    std::string temp;
    count = capped_count;
    // The last "count" number of allocation records in "records" are the most recent "count" number
    // of allocations. Reverse iterate to get them. The most recent allocation is sent first.
    for (auto it = records->RBegin(), end = records->REnd();
         count > 0 && it != end; count--, it++) {
      // For each entry:
      // (4b) total allocation size
      // (2b) thread id
      // (2b) allocated object's class name index
      // (1b) stack depth
      const gc::AllocRecord* record = it->second;
      size_t stack_depth = record->GetDepth();
      size_t allocated_object_class_name_index =
          class_names.IndexOf(record->GetClassDescriptor(&temp));
      JDWP::Append4BE(bytes, record->ByteCount());
      JDWP::Append2BE(bytes, static_cast<uint16_t>(record->GetTid()));
      JDWP::Append2BE(bytes, allocated_object_class_name_index);
      JDWP::Append1BE(bytes, stack_depth);

      for (size_t stack_frame = 0; stack_frame < stack_depth; ++stack_frame) {
        // For each stack frame:
        // (2b) method's class name
        // (2b) method name
        // (2b) method source file
        // (2b) line number, clipped to 32767; -2 if native; -1 if no source
        ArtMethod* m = record->StackElement(stack_frame).GetMethod();
        size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor());
        size_t method_name_index = method_names.IndexOf(m->GetName());
        size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m));
        JDWP::Append2BE(bytes, class_name_index);
        JDWP::Append2BE(bytes, method_name_index);
        JDWP::Append2BE(bytes, file_name_index);
        JDWP::Append2BE(bytes, record->StackElement(stack_frame).ComputeLineNumber());
      }
    }

    // (xb) class name strings
    // (xb) method name strings
    // (xb) source file strings
    JDWP::Set4BE(&bytes[string_table_offset], bytes.size());
    class_names.WriteTo(bytes);
    method_names.WriteTo(bytes);
    filenames.WriteTo(bytes);
  }
  JNIEnv* env = self->GetJniEnv();
  jbyteArray result = env->NewByteArray(bytes.size());
  if (result != nullptr) {
    env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0]));
  }
  return result;
}

ArtMethod* DeoptimizationRequest::Method() const {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  return soa.DecodeMethod(method_);
}

void DeoptimizationRequest::SetMethod(ArtMethod* m) {
  ScopedObjectAccessUnchecked soa(Thread::Current());
  method_ = soa.EncodeMethod(m);
}

}  // namespace art
