/*
 * 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 "class_linker.h"
#include "class_loader.h"
#include "dex_verifier.h" // For Instruction.
#include "context.h"
#include "object_utils.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "space.h"
#include "stack_indirect_reference_table.h"
#include "thread_list.h"

extern "C" void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*), void*);
#ifndef HAVE_ANDROID_OS
void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*), void*) {
  // No-op for glibc.
}
#endif

namespace art {

static const size_t kMaxAllocRecordStackDepth = 16; // Max 255.
static const size_t kNumAllocRecords = 512; // Must be power of 2.

static const uintptr_t kInvalidId = 1;
static const Object* kInvalidObject = reinterpret_cast<Object*>(kInvalidId);

class ObjectRegistry {
 public:
  ObjectRegistry() : lock_("ObjectRegistry lock") {
  }

  JDWP::ObjectId Add(Object* o) {
    if (o == NULL) {
      return 0;
    }
    JDWP::ObjectId id = static_cast<JDWP::ObjectId>(reinterpret_cast<uintptr_t>(o));
    MutexLock mu(lock_);
    map_[id] = o;
    return id;
  }

  void Clear() {
    MutexLock mu(lock_);
    LOG(DEBUG) << "Debugger has detached; object registry had " << map_.size() << " entries";
    map_.clear();
  }

  bool Contains(JDWP::ObjectId id) {
    MutexLock mu(lock_);
    return map_.find(id) != map_.end();
  }

  template<typename T> T Get(JDWP::ObjectId id) {
    if (id == 0) {
      return NULL;
    }

    MutexLock mu(lock_);
    typedef std::map<JDWP::ObjectId, Object*>::iterator It; // C++0x auto
    It it = map_.find(id);
    return (it != map_.end()) ? reinterpret_cast<T>(it->second) : reinterpret_cast<T>(kInvalidId);
  }

  void VisitRoots(Heap::RootVisitor* visitor, void* arg) {
    MutexLock mu(lock_);
    typedef std::map<JDWP::ObjectId, Object*>::iterator It; // C++0x auto
    for (It it = map_.begin(); it != map_.end(); ++it) {
      visitor(it->second, arg);
    }
  }

 private:
  Mutex lock_;
  std::map<JDWP::ObjectId, Object*> map_;
};

struct AllocRecordStackTraceElement {
  Method* method;
  uintptr_t raw_pc;

  int32_t LineNumber() const {
    return MethodHelper(method).GetLineNumFromNativePC(raw_pc);
  }
};

struct AllocRecord {
  Class* type;
  size_t byte_count;
  uint16_t thin_lock_id;
  AllocRecordStackTraceElement stack[kMaxAllocRecordStackDepth]; // Unused entries have NULL method.

  size_t GetDepth() {
    size_t depth = 0;
    while (depth < kMaxAllocRecordStackDepth && stack[depth].method != NULL) {
      ++depth;
    }
    return depth;
  }
};

struct Breakpoint {
  Method* method;
  uint32_t pc;
  Breakpoint(Method* method, uint32_t pc) : method(method), pc(pc) {}
};

static std::ostream& operator<<(std::ostream& os, const Breakpoint& rhs) {
  os << "Breakpoint[" << PrettyMethod(rhs.method) << " @" << rhs.pc << "]";
  return os;
}

struct SingleStepControl {
  // Are we single-stepping right now?
  bool is_active;
  Thread* thread;

  JDWP::JdwpStepSize step_size;
  JDWP::JdwpStepDepth step_depth;

  const Method* method;
  int32_t line_number; // Or -1 for native methods.
  std::set<uint32_t> dex_pcs;
  int stack_depth;
};

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

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

// Broken-down JDWP options. (Only valid if gJdwpConfigured is true.)
static JDWP::JdwpOptions gJdwpOptions;

// Runtime JDWP state.
static JDWP::JdwpState* gJdwpState = NULL;
static bool gDebuggerConnected;  // debugger or DDMS is connected.
static bool gDebuggerActive;     // debugger is making requests.
static bool gDisposed;           // debugger called VirtualMachine.Dispose, so we should drop the connection.

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;

static ObjectRegistry* gRegistry = NULL;

// Recent allocation tracking.
static Mutex gAllocTrackerLock("AllocTracker lock");
AllocRecord* Dbg::recent_allocation_records_ = NULL; // TODO: CircularBuffer<AllocRecord>
static size_t gAllocRecordHead = 0;
static size_t gAllocRecordCount = 0;

// Breakpoints and single-stepping.
static Mutex gBreakpointsLock("breakpoints lock");
static std::vector<Breakpoint> gBreakpoints;
static SingleStepControl gSingleStepControl;

static bool IsBreakpoint(Method* m, uint32_t dex_pc) {
  MutexLock mu(gBreakpointsLock);
  uint32_t pc = dex_pc / 2; // dex bytecodes are twice the size JDWP expects.
  for (size_t i = 0; i < gBreakpoints.size(); ++i) {
    if (gBreakpoints[i].method == m && gBreakpoints[i].pc == pc) {
      VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i];
      return true;
    }
  }
  return false;
}

static Array* DecodeArray(JDWP::RefTypeId id, JDWP::JdwpError& status) {
  Object* o = gRegistry->Get<Object*>(id);
  if (o == NULL || o == kInvalidObject) {
    status = JDWP::ERR_INVALID_OBJECT;
    return NULL;
  }
  if (!o->IsArrayInstance()) {
    status = JDWP::ERR_INVALID_ARRAY;
    return NULL;
  }
  status = JDWP::ERR_NONE;
  return o->AsArray();
}

static Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError& status) {
  Object* o = gRegistry->Get<Object*>(id);
  if (o == NULL || o == kInvalidObject) {
    status = JDWP::ERR_INVALID_OBJECT;
    return NULL;
  }
  if (!o->IsClass()) {
    status = JDWP::ERR_INVALID_CLASS;
    return NULL;
  }
  status = JDWP::ERR_NONE;
  return o->AsClass();
}

static Thread* DecodeThread(JDWP::ObjectId threadId) {
  Object* thread_peer = gRegistry->Get<Object*>(threadId);
  if (thread_peer == NULL || thread_peer == kInvalidObject) {
    return NULL;
  }
  return Thread::FromManagedThread(thread_peer);
}

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 TagFromClass(Class* c) {
  CHECK(c != NULL);
  if (c->IsArrayClass()) {
    return JDWP::JT_ARRAY;
  }

  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  if (c->IsStringClass()) {
    return JDWP::JT_STRING;
  } else if (c->IsClassClass()) {
    return JDWP::JT_CLASS_OBJECT;
  } else if (class_linker->FindSystemClass("Ljava/lang/Thread;")->IsAssignableFrom(c)) {
    return JDWP::JT_THREAD;
  } else if (class_linker->FindSystemClass("Ljava/lang/ThreadGroup;")->IsAssignableFrom(c)) {
    return JDWP::JT_THREAD_GROUP;
  } else if (class_linker->FindSystemClass("Ljava/lang/ClassLoader;")->IsAssignableFrom(c)) {
    return JDWP::JT_CLASS_LOADER;
  } else {
    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.
 */
static JDWP::JdwpTag TagFromObject(const Object* o) {
  return (o == NULL) ? JDWP::JT_OBJECT : TagFromClass(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;
  }
}

/*
 * Handle one of the JDWP name/value pairs.
 *
 * JDWP options are:
 *  help: if specified, show help message and bail
 *  transport: may be dt_socket or dt_shmem
 *  address: for dt_socket, "host:port", or just "port" when listening
 *  server: if "y", wait for debugger to attach; if "n", attach to debugger
 *  timeout: how long to wait for debugger to connect / listen
 *
 * Useful with server=n (these aren't supported yet):
 *  onthrow=<exception-name>: connect to debugger when exception thrown
 *  onuncaught=y|n: connect to debugger when uncaught exception thrown
 *  launch=<command-line>: launch the debugger itself
 *
 * The "transport" option is required, as is "address" if server=n.
 */
static bool ParseJdwpOption(const std::string& name, const std::string& value) {
  if (name == "transport") {
    if (value == "dt_socket") {
      gJdwpOptions.transport = JDWP::kJdwpTransportSocket;
    } else if (value == "dt_android_adb") {
      gJdwpOptions.transport = JDWP::kJdwpTransportAndroidAdb;
    } else {
      LOG(ERROR) << "JDWP transport not supported: " << value;
      return false;
    }
  } else if (name == "server") {
    if (value == "n") {
      gJdwpOptions.server = false;
    } else if (value == "y") {
      gJdwpOptions.server = true;
    } else {
      LOG(ERROR) << "JDWP option 'server' must be 'y' or 'n'";
      return false;
    }
  } else if (name == "suspend") {
    if (value == "n") {
      gJdwpOptions.suspend = false;
    } else if (value == "y") {
      gJdwpOptions.suspend = true;
    } else {
      LOG(ERROR) << "JDWP option 'suspend' must be 'y' or 'n'";
      return false;
    }
  } else if (name == "address") {
    /* this is either <port> or <host>:<port> */
    std::string port_string;
    gJdwpOptions.host.clear();
    std::string::size_type colon = value.find(':');
    if (colon != std::string::npos) {
      gJdwpOptions.host = value.substr(0, colon);
      port_string = value.substr(colon + 1);
    } else {
      port_string = value;
    }
    if (port_string.empty()) {
      LOG(ERROR) << "JDWP address missing port: " << value;
      return false;
    }
    char* end;
    uint64_t port = strtoul(port_string.c_str(), &end, 10);
    if (*end != '\0' || port > 0xffff) {
      LOG(ERROR) << "JDWP address has junk in port field: " << value;
      return false;
    }
    gJdwpOptions.port = port;
  } else if (name == "launch" || name == "onthrow" || name == "oncaught" || name == "timeout") {
    /* valid but unsupported */
    LOG(INFO) << "Ignoring JDWP option '" << name << "'='" << value << "'";
  } else {
    LOG(INFO) << "Ignoring unrecognized JDWP option '" << name << "'='" << value << "'";
  }

  return true;
}

/*
 * Parse the latter half of a -Xrunjdwp/-agentlib:jdwp= string, e.g.:
 * "transport=dt_socket,address=8000,server=y,suspend=n"
 */
bool Dbg::ParseJdwpOptions(const std::string& options) {
  VLOG(jdwp) << "ParseJdwpOptions: " << options;

  std::vector<std::string> pairs;
  Split(options, ',', pairs);

  for (size_t i = 0; i < pairs.size(); ++i) {
    std::string::size_type equals = pairs[i].find('=');
    if (equals == std::string::npos) {
      LOG(ERROR) << "Can't parse JDWP option '" << pairs[i] << "' in '" << options << "'";
      return false;
    }
    ParseJdwpOption(pairs[i].substr(0, equals), pairs[i].substr(equals + 1));
  }

  if (gJdwpOptions.transport == JDWP::kJdwpTransportUnknown) {
    LOG(ERROR) << "Must specify JDWP transport: " << options;
  }
  if (!gJdwpOptions.server && (gJdwpOptions.host.empty() || gJdwpOptions.port == 0)) {
    LOG(ERROR) << "Must specify JDWP host and port when server=n: " << options;
    return false;
  }

  gJdwpConfigured = true;
  return true;
}

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

  CHECK(gRegistry == NULL);
  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 == NULL) {
    // 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()) {
    //ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
    if (!gJdwpState->PostVMStart()) {
      LOG(WARNING) << "Failed to post 'start' message to debugger";
    }
  }
}

void Dbg::StopJdwp() {
  delete gJdwpState;
  delete gRegistry;
  gRegistry = NULL;
}

void Dbg::GcDidFinish() {
  if (gDdmHpifWhen != HPIF_WHEN_NEVER) {
    LOG(DEBUG) << "Sending VM heap info to DDM";
    DdmSendHeapInfo(gDdmHpifWhen);
  }
  if (gDdmHpsgWhen != HPSG_WHEN_NEVER) {
    LOG(DEBUG) << "Dumping VM heap to DDM";
    DdmSendHeapSegments(false);
  }
  if (gDdmNhsgWhen != HPSG_WHEN_NEVER) {
    LOG(DEBUG) << "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 != NULL) ? gJdwpState->GetDebugThread() : NULL;
}

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

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

void Dbg::Disposed() {
  gDisposed = true;
}

bool Dbg::IsDisposed() {
  return gDisposed;
}

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 (gDebuggerActive) {
    return;
  }

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

  // TODO: CHECK we don't have any outstanding breakpoints.

  gDebuggerActive = true;

  //dvmEnableAllSubMode(kSubModeDebuggerActive);
}

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

  gDebuggerActive = false;

  //dvmDisableAllSubMode(kSubModeDebuggerActive);

  gRegistry->Clear();
  gDebuggerConnected = false;
}

bool Dbg::IsDebuggerConnected() {
  return gDebuggerActive;
}

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

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

int Dbg::ThreadRunning() {
  return static_cast<int>(Thread::Current()->SetState(Thread::kRunnable));
}

int Dbg::ThreadWaiting() {
  return static_cast<int>(Thread::Current()->SetState(Thread::kVmWait));
}

int Dbg::ThreadContinuing(int new_state) {
  return static_cast<int>(Thread::Current()->SetState(static_cast<Thread::State>(new_state)));
}

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

void Dbg::Exit(int status) {
  exit(status); // This is all dalvik did.
}

void Dbg::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
  if (gRegistry != NULL) {
    gRegistry->VisitRoots(visitor, arg);
  }
}

std::string Dbg::GetClassName(JDWP::RefTypeId classId) {
  Object* o = gRegistry->Get<Object*>(classId);
  if (o == NULL) {
    return "NULL";
  }
  if (o == kInvalidObject) {
    return StringPrintf("invalid object %p", reinterpret_cast<void*>(classId));
  }
  if (!o->IsClass()) {
    return StringPrintf("non-class %p", o); // This is only used for debugging output anyway.
  }
  return DescriptorToName(ClassHelper(o->AsClass()).GetDescriptor());
}

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

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

JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
  Object* o = gRegistry->Get<Object*>(id);
  if (o == NULL || o == kInvalidObject) {
    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 status;
  Class* c = DecodeClass(id, status);
  if (c == NULL) {
    return status;
  }

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

  // Set ACC_SUPER; dex files don't contain this flag, but all classes are supposed to have it set.
  // Class.getModifiers doesn't return it, but JDWP does, so we set it here.
  access_flags |= kAccSuper;

  expandBufAdd4BE(pReply, access_flags);

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId classId, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }

  expandBufAdd1(pReply, c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS);
  expandBufAddRefTypeId(pReply, classId);
  return JDWP::ERR_NONE;
}

void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) {
  // Get the complete list of reference classes (i.e. all classes except
  // the primitive types).
  // Returns a newly-allocated buffer full of RefTypeId values.
  struct ClassListCreator {
    explicit ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) {
    }

    static bool Visit(Class* c, void* arg) {
      return reinterpret_cast<ClassListCreator*>(arg)->Visit(c);
    }

    bool Visit(Class* c) {
      if (!c->IsPrimitive()) {
        classes.push_back(static_cast<JDWP::RefTypeId>(gRegistry->Add(c)));
      }
      return true;
    }

    std::vector<JDWP::RefTypeId>& classes;
  };

  ClassListCreator clc(classes);
  Runtime::Current()->GetClassLinker()->VisitClasses(ClassListCreator::Visit, &clc);
}

JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }

  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 != NULL) {
    *pDescriptor = ClassHelper(c).GetDescriptor();
  }
  return JDWP::ERR_NONE;
}

void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) {
  std::vector<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 objectId, JDWP::ExpandBuf* pReply) {
  Object* o = gRegistry->Get<Object*>(objectId);
  if (o == NULL || o == kInvalidObject) {
    return JDWP::ERR_INVALID_OBJECT;
  }

  JDWP::JdwpTypeTag type_tag;
  if (o->GetClass()->IsArrayClass()) {
    type_tag = JDWP::TT_ARRAY;
  } else if (o->GetClass()->IsInterface()) {
    type_tag = JDWP::TT_INTERFACE;
  } else {
    type_tag = JDWP::TT_CLASS;
  }
  JDWP::RefTypeId type_id = gRegistry->Add(o->GetClass());

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

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId classId, std::string& signature) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }
  signature = ClassHelper(c).GetDescriptor();
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId classId, std::string& result) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }
  result = ClassHelper(c).GetSourceFile();
  return JDWP::ERR_NONE;
}

uint8_t Dbg::GetObjectTag(JDWP::ObjectId objectId) {
  Object* o = gRegistry->Get<Object*>(objectId);
  return TagFromObject(o);
}

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 arrayId, int& length) {
  JDWP::JdwpError status;
  Array* a = DecodeArray(arrayId, status);
  if (a == NULL) {
    return status;
  }
  length = a->GetLength();
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId arrayId, int offset, int count, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError status;
  Array* a = DecodeArray(arrayId, status);
  if (a == NULL) {
    return status;
  }

  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;
  }
  std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
  JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);

  expandBufAdd1(pReply, tag);
  expandBufAdd4BE(pReply, count);

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

  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId arrayId, int offset, int count, const uint8_t* src) {
  JDWP::JdwpError status;
  Array* a = DecodeArray(arrayId, status);
  if (a == NULL) {
    return status;
  }

  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;
  }
  std::string descriptor(ClassHelper(a->GetClass()).GetDescriptor());
  JDWP::JdwpTag tag = BasicTagFromDescriptor(descriptor.c_str() + 1);

  if (IsPrimitiveTag(tag)) {
    size_t width = GetTagWidth(tag);
    uint8_t* dst = &(reinterpret_cast<uint8_t*>(a->GetRawData())[offset * width]);
    if (width == 8) {
      for (int i = 0; i < count; ++i) {
        // Handle potentially non-aligned memory access one byte at a time for ARM's benefit.
        uint64_t value;
        for (size_t j = 0; j < sizeof(uint64_t); ++j) reinterpret_cast<uint8_t*>(&value)[j] = src[j];
        src += sizeof(uint64_t);
        JDWP::Write8BE(&dst, value);
      }
    } else if (width == 4) {
      const uint32_t* src4 = reinterpret_cast<const uint32_t*>(src);
      for (int i = 0; i < count; ++i) JDWP::Write4BE(&dst, src4[i]);
    } else if (width == 2) {
      const uint16_t* src2 = reinterpret_cast<const uint16_t*>(src);
      for (int i = 0; i < count; ++i) JDWP::Write2BE(&dst, src2[i]);
    } else {
      memcpy(&dst[offset * width], src, count * width);
    }
  } else {
    ObjectArray<Object>* oa = a->AsObjectArray<Object>();
    for (int i = 0; i < count; ++i) {
      JDWP::ObjectId id = JDWP::ReadObjectId(&src);
      Object* o = gRegistry->Get<Object*>(id);
      if (o == kInvalidObject) {
        return JDWP::ERR_INVALID_OBJECT;
      }
      oa->Set(offset + i, o);
    }
  }

  return JDWP::ERR_NONE;
}

JDWP::ObjectId Dbg::CreateString(const std::string& str) {
  return gRegistry->Add(String::AllocFromModifiedUtf8(str.c_str()));
}

JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }
  new_object = gRegistry->Add(c->AllocObject());
  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 arrayClassId, uint32_t length, JDWP::ObjectId& new_array) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(arrayClassId, status);
  if (c == NULL) {
    return status;
  }
  new_array = gRegistry->Add(Array::Alloc(c, length));
  return JDWP::ERR_NONE;
}

bool Dbg::MatchType(JDWP::RefTypeId instClassId, JDWP::RefTypeId classId) {
  JDWP::JdwpError status;
  Class* c1 = DecodeClass(instClassId, status);
  Class* c2 = DecodeClass(classId, status);
  if (c1 == NULL || c2 == NULL) {
    // TODO: it doesn't seem like we can do any better here?
    return false;
  }
  return c1->InstanceOf(c2);
}

static JDWP::FieldId ToFieldId(const Field* f) {
#ifdef MOVING_GARBAGE_COLLECTOR
  UNIMPLEMENTED(FATAL);
#else
  return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f));
#endif
}

static JDWP::MethodId ToMethodId(const Method* m) {
#ifdef MOVING_GARBAGE_COLLECTOR
  UNIMPLEMENTED(FATAL);
#else
  return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m));
#endif
}

static Field* FromFieldId(JDWP::FieldId fid) {
#ifdef MOVING_GARBAGE_COLLECTOR
  UNIMPLEMENTED(FATAL);
#else
  return reinterpret_cast<Field*>(static_cast<uintptr_t>(fid));
#endif
}

static Method* FromMethodId(JDWP::MethodId mid) {
#ifdef MOVING_GARBAGE_COLLECTOR
  UNIMPLEMENTED(FATAL);
#else
  return reinterpret_cast<Method*>(static_cast<uintptr_t>(mid));
#endif
}

static void SetLocation(JDWP::JdwpLocation& location, Method* m, uintptr_t native_pc) {
  if (m == NULL) {
    memset(&location, 0, sizeof(location));
  } else {
    Class* c = m->GetDeclaringClass();
    location.typeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
    location.classId = gRegistry->Add(c);
    location.methodId = ToMethodId(m);
    location.idx = m->IsNative() ? -1 : m->ToDexPC(native_pc) / 2;
  }
}

std::string Dbg::GetMethodName(JDWP::RefTypeId, JDWP::MethodId methodId) {
  Method* m = FromMethodId(methodId);
  return MethodHelper(m).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;
}

static const uint16_t kEclipseWorkaroundSlot = 1000;

/*
 * Eclipse appears to expect that the "this" reference is in slot zero.
 * If it's not, the "variables" display will show two copies of "this",
 * possibly because it gets "this" from SF.ThisObject and then displays
 * all locals with nonzero slot numbers.
 *
 * So, we remap the item in slot 0 to 1000, and remap "this" to zero.  On
 * SF.GetValues / SF.SetValues we map them back.
 *
 * TODO: jdb uses the value to determine whether a variable is a local or an argument,
 * by checking whether it's less than the number of arguments. To make that work, we'd
 * have to "mangle" all the arguments to come first, not just the implicit argument 'this'.
 */
static uint16_t MangleSlot(uint16_t slot, const char* name) {
  uint16_t newSlot = slot;
  if (strcmp(name, "this") == 0) {
    newSlot = 0;
  } else if (slot == 0) {
    newSlot = kEclipseWorkaroundSlot;
  }
  return newSlot;
}

static uint16_t DemangleSlot(uint16_t slot, Method* m) {
  if (slot == kEclipseWorkaroundSlot) {
    return 0;
  } else if (slot == 0) {
    const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
    CHECK(code_item != NULL);
    return code_item->registers_size_ - code_item->ins_size_;
  }
  return slot;
}

JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId classId, bool with_generic, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }

  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) {
    Field* f = (i < instance_field_count) ? c->GetInstanceField(i) : c->GetStaticField(i - instance_field_count);
    FieldHelper fh(f);
    expandBufAddFieldId(pReply, ToFieldId(f));
    expandBufAddUtf8String(pReply, fh.GetName());
    expandBufAddUtf8String(pReply, fh.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 classId, bool with_generic, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }

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

  expandBufAdd4BE(pReply, direct_method_count + virtual_method_count);

  for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) {
    Method* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count);
    MethodHelper mh(m);
    expandBufAddMethodId(pReply, ToMethodId(m));
    expandBufAddUtf8String(pReply, mh.GetName());
    expandBufAddUtf8String(pReply, mh.GetSignature());
    if (with_generic) {
      static const char genericSignature[1] = "";
      expandBufAddUtf8String(pReply, genericSignature);
    }
    expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags()));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId classId, JDWP::ExpandBuf* pReply) {
  JDWP::JdwpError status;
  Class* c = DecodeClass(classId, status);
  if (c == NULL) {
    return status;
  }

  ClassHelper kh(c);
  size_t interface_count = kh.NumInterfaces();
  expandBufAdd4BE(pReply, interface_count);
  for (size_t i = 0; i < interface_count; ++i) {
    expandBufAddRefTypeId(pReply, gRegistry->Add(kh.GetInterface(i)));
  }
  return JDWP::ERR_NONE;
}

void Dbg::OutputLineTable(JDWP::RefTypeId, JDWP::MethodId methodId, 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 true;
    }
  };

  Method* m = FromMethodId(methodId);
  MethodHelper mh(m);
  uint64_t start, end;
  if (m->IsNative()) {
    start = -1;
    end = -1;
  } else {
    start = 0;
    // TODO: what are the units supposed to be? *2?
    end = mh.GetCodeItem()->insns_size_in_code_units_;
  }

  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;

  mh.GetDexFile().DecodeDebugInfo(mh.GetCodeItem(), m->IsStatic(), m->GetDexMethodIndex(),
                                  DebugCallbackContext::Callback, NULL, &context);

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

void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId methodId, bool with_generic, JDWP::ExpandBuf* pReply) {
  struct DebugCallbackContext {
    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) {
      DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);

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

      slot = MangleSlot(slot, name);

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

  Method* m = FromMethodId(methodId);
  MethodHelper mh(m);
  const DexFile::CodeItem* code_item = mh.GetCodeItem();

  // arg_count considers doubles and longs to take 2 units.
  // variable_count considers everything to take 1 unit.
  std::string shorty(mh.GetShorty());
  expandBufAdd4BE(pReply, m->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.pReply = pReply;
  context.variable_count = 0;
  context.with_generic = with_generic;

  mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), NULL,
                                  DebugCallbackContext::Callback, &context);

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

JDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId fieldId) {
  return BasicTagFromDescriptor(FieldHelper(FromFieldId(fieldId)).GetTypeDescriptor());
}

JDWP::JdwpTag Dbg::GetStaticFieldBasicTag(JDWP::FieldId fieldId) {
  return BasicTagFromDescriptor(FieldHelper(FromFieldId(fieldId)).GetTypeDescriptor());
}

static JDWP::JdwpError GetFieldValueImpl(JDWP::ObjectId objectId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply, bool is_static) {
  Object* o = gRegistry->Get<Object*>(objectId);
  if ((!is_static && o == NULL) || o == kInvalidObject) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  Field* f = FromFieldId(fieldId);
  if (f->IsStatic() != is_static) {
    return JDWP::ERR_INVALID_FIELDID;
  }

  JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());

  if (IsPrimitiveTag(tag)) {
    expandBufAdd1(pReply, tag);
    if (tag == JDWP::JT_BOOLEAN || tag == JDWP::JT_BYTE) {
      expandBufAdd1(pReply, f->Get32(o));
    } else if (tag == JDWP::JT_CHAR || tag == JDWP::JT_SHORT) {
      expandBufAdd2BE(pReply, f->Get32(o));
    } else if (tag == JDWP::JT_FLOAT || tag == JDWP::JT_INT) {
      expandBufAdd4BE(pReply, f->Get32(o));
    } else if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
      expandBufAdd8BE(pReply, f->Get64(o));
    } else {
      LOG(FATAL) << "Unknown tag: " << tag;
    }
  } else {
    Object* value = f->GetObject(o);
    expandBufAdd1(pReply, TagFromObject(value));
    expandBufAddObjectId(pReply, gRegistry->Add(value));
  }
  return JDWP::ERR_NONE;
}

JDWP::JdwpError Dbg::GetFieldValue(JDWP::ObjectId objectId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply) {
  return GetFieldValueImpl(objectId, fieldId, pReply, false);
}

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

static JDWP::JdwpError SetFieldValueImpl(JDWP::ObjectId objectId, JDWP::FieldId fieldId, uint64_t value, int width, bool is_static) {
  Object* o = gRegistry->Get<Object*>(objectId);
  if ((!is_static && o == NULL) || o == kInvalidObject) {
    return JDWP::ERR_INVALID_OBJECT;
  }
  Field* f = FromFieldId(fieldId);
  if (f->IsStatic() != is_static) {
    return JDWP::ERR_INVALID_FIELDID;
  }

  JDWP::JdwpTag tag = BasicTagFromDescriptor(FieldHelper(f).GetTypeDescriptor());

  if (IsPrimitiveTag(tag)) {
    if (tag == JDWP::JT_DOUBLE || tag == JDWP::JT_LONG) {
      f->Set64(o, value);
    } else {
      f->Set32(o, value);
    }
  } else {
    Object* v = gRegistry->Get<Object*>(value);
    if (v == kInvalidObject) {
      return JDWP::ERR_INVALID_OBJECT;
    }
    if (v != NULL) {
      Class* field_type = FieldHelper(f).GetType();
      if (!field_type->IsAssignableFrom(v->GetClass())) {
        return JDWP::ERR_INVALID_OBJECT;
      }
    }
    f->SetObject(o, v);
  }

  return JDWP::ERR_NONE;
}

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

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

std::string Dbg::StringToUtf8(JDWP::ObjectId strId) {
  String* s = gRegistry->Get<String*>(strId);
  return s->ToModifiedUtf8();
}

bool Dbg::GetThreadName(JDWP::ObjectId threadId, std::string& name) {
  ScopedThreadListLock thread_list_lock;
  Thread* thread = DecodeThread(threadId);
  if (thread == NULL) {
    return false;
  }
  name = thread->GetThreadName()->ToModifiedUtf8();
  return true;
}

JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId threadId, JDWP::ExpandBuf* pReply) {
  Object* thread = gRegistry->Get<Object*>(threadId);
  if (thread == kInvalidObject) {
    return JDWP::ERR_INVALID_OBJECT;
  }

  // Okay, so it's an object, but is it actually a thread?
  if (DecodeThread(threadId) == NULL) {
    return JDWP::ERR_INVALID_THREAD;
  }

  Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/Thread;");
  CHECK(c != NULL);
  Field* f = c->FindInstanceField("group", "Ljava/lang/ThreadGroup;");
  CHECK(f != NULL);
  Object* group = f->GetObject(thread);
  CHECK(group != NULL);
  JDWP::ObjectId thread_group_id = gRegistry->Add(group);

  expandBufAddObjectId(pReply, thread_group_id);
  return JDWP::ERR_NONE;
}

std::string Dbg::GetThreadGroupName(JDWP::ObjectId threadGroupId) {
  Object* thread_group = gRegistry->Get<Object*>(threadGroupId);
  CHECK(thread_group != NULL);

  Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;");
  CHECK(c != NULL);
  Field* f = c->FindInstanceField("name", "Ljava/lang/String;");
  CHECK(f != NULL);
  String* s = reinterpret_cast<String*>(f->GetObject(thread_group));
  return s->ToModifiedUtf8();
}

JDWP::ObjectId Dbg::GetThreadGroupParent(JDWP::ObjectId threadGroupId) {
  Object* thread_group = gRegistry->Get<Object*>(threadGroupId);
  CHECK(thread_group != NULL);

  Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;");
  CHECK(c != NULL);
  Field* f = c->FindInstanceField("parent", "Ljava/lang/ThreadGroup;");
  CHECK(f != NULL);
  Object* parent = f->GetObject(thread_group);
  return gRegistry->Add(parent);
}

static Object* GetStaticThreadGroup(const char* field_name) {
  Class* c = Runtime::Current()->GetClassLinker()->FindSystemClass("Ljava/lang/ThreadGroup;");
  CHECK(c != NULL);
  Field* f = c->FindStaticField(field_name, "Ljava/lang/ThreadGroup;");
  CHECK(f != NULL);
  Object* group = f->GetObject(NULL);
  CHECK(group != NULL);
  return group;
}

JDWP::ObjectId Dbg::GetSystemThreadGroupId() {
  return gRegistry->Add(GetStaticThreadGroup("mSystem"));
}

JDWP::ObjectId Dbg::GetMainThreadGroupId() {
  return gRegistry->Add(GetStaticThreadGroup("mMain"));
}

bool Dbg::GetThreadStatus(JDWP::ObjectId threadId, JDWP::JdwpThreadStatus* pThreadStatus, JDWP::JdwpSuspendStatus* pSuspendStatus) {
  ScopedThreadListLock thread_list_lock;

  Thread* thread = DecodeThread(threadId);
  if (thread == NULL) {
    return false;
  }

  switch (thread->GetState()) {
  case Thread::kTerminated:   *pThreadStatus = JDWP::TS_ZOMBIE;   break;
  case Thread::kRunnable:     *pThreadStatus = JDWP::TS_RUNNING;  break;
  case Thread::kTimedWaiting: *pThreadStatus = JDWP::TS_SLEEPING; break;
  case Thread::kBlocked:      *pThreadStatus = JDWP::TS_MONITOR;  break;
  case Thread::kWaiting:      *pThreadStatus = JDWP::TS_WAIT;     break;
  case Thread::kInitializing: *pThreadStatus = JDWP::TS_ZOMBIE;   break;
  case Thread::kStarting:     *pThreadStatus = JDWP::TS_ZOMBIE;   break;
  case Thread::kNative:       *pThreadStatus = JDWP::TS_RUNNING;  break;
  case Thread::kVmWait:       *pThreadStatus = JDWP::TS_WAIT;     break;
  case Thread::kSuspended:    *pThreadStatus = JDWP::TS_RUNNING;  break;
  default:
    LOG(FATAL) << "Unknown thread state " << thread->GetState();
  }

  *pSuspendStatus = (thread->IsSuspended() ? JDWP::SUSPEND_STATUS_SUSPENDED : JDWP::SUSPEND_STATUS_NOT_SUSPENDED);

  return true;
}

JDWP::JdwpError Dbg::GetThreadSuspendCount(JDWP::ObjectId threadId, JDWP::ExpandBuf* pReply) {
  Thread* thread = DecodeThread(threadId);
  if (thread == NULL) {
    return JDWP::ERR_INVALID_THREAD;
  }
  expandBufAdd4BE(pReply, thread->GetSuspendCount());
  return JDWP::ERR_NONE;
}

bool Dbg::ThreadExists(JDWP::ObjectId threadId) {
  return DecodeThread(threadId) != NULL;
}

bool Dbg::IsSuspended(JDWP::ObjectId threadId) {
  return DecodeThread(threadId)->IsSuspended();
}

void Dbg::GetThreadGroupThreadsImpl(Object* thread_group, JDWP::ObjectId** ppThreadIds, uint32_t* pThreadCount) {
  struct ThreadListVisitor {
    static void Visit(Thread* t, void* arg) {
      reinterpret_cast<ThreadListVisitor*>(arg)->Visit(t);
    }

    void Visit(Thread* t) {
      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.
        return;
      }
      if (thread_group == NULL || t->GetThreadGroup() == thread_group) {
        threads.push_back(gRegistry->Add(t->GetPeer()));
      }
    }

    Object* thread_group;
    std::vector<JDWP::ObjectId> threads;
  };

  ThreadListVisitor tlv;
  tlv.thread_group = thread_group;

  {
    ScopedThreadListLock thread_list_lock;
    Runtime::Current()->GetThreadList()->ForEach(ThreadListVisitor::Visit, &tlv);
  }

  *pThreadCount = tlv.threads.size();
  if (*pThreadCount == 0) {
    *ppThreadIds = NULL;
  } else {
    *ppThreadIds = new JDWP::ObjectId[*pThreadCount];
    for (size_t i = 0; i < *pThreadCount; ++i) {
      (*ppThreadIds)[i] = tlv.threads[i];
    }
  }
}

void Dbg::GetThreadGroupThreads(JDWP::ObjectId threadGroupId, JDWP::ObjectId** ppThreadIds, uint32_t* pThreadCount) {
  GetThreadGroupThreadsImpl(gRegistry->Get<Object*>(threadGroupId), ppThreadIds, pThreadCount);
}

void Dbg::GetAllThreads(JDWP::ObjectId** ppThreadIds, uint32_t* pThreadCount) {
  GetThreadGroupThreadsImpl(NULL, ppThreadIds, pThreadCount);
}

static int GetStackDepth(Thread* thread) {
  struct CountStackDepthVisitor : public Thread::StackVisitor {
    CountStackDepthVisitor() : depth(0) {}
    virtual void VisitFrame(const Frame& f, uintptr_t) {
      // TODO: we'll need to skip callee-save frames too.
      if (f.HasMethod()) {
        ++depth;
      }
    }
    size_t depth;
  };
  CountStackDepthVisitor visitor;
  thread->WalkStack(&visitor);
  return visitor.depth;
}

int Dbg::GetThreadFrameCount(JDWP::ObjectId threadId) {
  ScopedThreadListLock thread_list_lock;
  return GetStackDepth(DecodeThread(threadId));
}

bool Dbg::GetThreadFrame(JDWP::ObjectId threadId, int desired_frame_number, JDWP::FrameId* pFrameId, JDWP::JdwpLocation* pLoc) {
  ScopedThreadListLock thread_list_lock;
  struct GetFrameVisitor : public Thread::StackVisitor {
    GetFrameVisitor(int desired_frame_number, JDWP::FrameId* pFrameId, JDWP::JdwpLocation* pLoc)
        : found(false), depth(0), desired_frame_number(desired_frame_number), pFrameId(pFrameId), pLoc(pLoc) {
    }
    virtual void VisitFrame(const Frame& f, uintptr_t pc) {
      // TODO: we'll need to skip callee-save frames too.
      if (!f.HasMethod()) {
        return; // The debugger can't do anything useful with a frame that has no Method*.
      }

      if (depth == desired_frame_number) {
        *pFrameId = reinterpret_cast<JDWP::FrameId>(f.GetSP());
        SetLocation(*pLoc, f.GetMethod(), pc);
        found = true;
      }
      ++depth;
    }
    bool found;
    int depth;
    int desired_frame_number;
    JDWP::FrameId* pFrameId;
    JDWP::JdwpLocation* pLoc;
  };
  GetFrameVisitor visitor(desired_frame_number, pFrameId, pLoc);
  visitor.desired_frame_number = desired_frame_number;
  DecodeThread(threadId)->WalkStack(&visitor);
  return visitor.found;
}

JDWP::ObjectId Dbg::GetThreadSelfId() {
  return gRegistry->Add(Thread::Current()->GetPeer());
}

void Dbg::SuspendVM() {
  ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable); // TODO: do we really want to change back? should the JDWP thread be Runnable usually?
  Runtime::Current()->GetThreadList()->SuspendAll(true);
}

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

void Dbg::SuspendThread(JDWP::ObjectId threadId) {
  Object* peer = gRegistry->Get<Object*>(threadId);
  ScopedThreadListLock thread_list_lock;
  Thread* thread = Thread::FromManagedThread(peer);
  if (thread == NULL) {
    LOG(WARNING) << "No such thread for suspend: " << peer;
    return;
  }
  Runtime::Current()->GetThreadList()->Suspend(thread, true);
}

void Dbg::ResumeThread(JDWP::ObjectId threadId) {
  Object* peer = gRegistry->Get<Object*>(threadId);
  ScopedThreadListLock thread_list_lock;
  Thread* thread = Thread::FromManagedThread(peer);
  if (thread == NULL) {
    LOG(WARNING) << "No such thread for resume: " << peer;
    return;
  }
  Runtime::Current()->GetThreadList()->Resume(thread, true);
}

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

static Object* GetThis(Frame& f) {
  Method* m = f.GetMethod();
  Object* o = NULL;
  if (!m->IsNative() && !m->IsStatic()) {
    uint16_t reg = DemangleSlot(0, m);
    o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
  }
  return o;
}

void Dbg::GetThisObject(JDWP::FrameId frameId, JDWP::ObjectId* pThisId) {
  Method** sp = reinterpret_cast<Method**>(frameId);
  Frame f(sp);
  Object* o = GetThis(f);
  *pThisId = gRegistry->Add(o);
}

void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
  Method** sp = reinterpret_cast<Method**>(frameId);
  Frame f(sp);
  Method* m = f.GetMethod();
  uint16_t reg = DemangleSlot(slot, m);

  const VmapTable vmap_table(m->GetVmapTableRaw());
  uint32_t vmap_offset;
  if (vmap_table.IsInContext(reg, vmap_offset)) {
    UNIMPLEMENTED(FATAL) << "Don't know how to pull locals from callee save frames: " << vmap_offset;
  }

  switch (tag) {
  case JDWP::JT_BOOLEAN:
    {
      CHECK_EQ(width, 1U);
      uint32_t intVal = f.GetVReg(m, reg);
      VLOG(jdwp) << "get boolean local " << reg << " = " << intVal;
      JDWP::Set1(buf+1, intVal != 0);
    }
    break;
  case JDWP::JT_BYTE:
    {
      CHECK_EQ(width, 1U);
      uint32_t intVal = f.GetVReg(m, reg);
      VLOG(jdwp) << "get byte local " << reg << " = " << intVal;
      JDWP::Set1(buf+1, intVal);
    }
    break;
  case JDWP::JT_SHORT:
  case JDWP::JT_CHAR:
    {
      CHECK_EQ(width, 2U);
      uint32_t intVal = f.GetVReg(m, reg);
      VLOG(jdwp) << "get short/char local " << reg << " = " << intVal;
      JDWP::Set2BE(buf+1, intVal);
    }
    break;
  case JDWP::JT_INT:
  case JDWP::JT_FLOAT:
    {
      CHECK_EQ(width, 4U);
      uint32_t intVal = f.GetVReg(m, reg);
      VLOG(jdwp) << "get int/float local " << reg << " = " << intVal;
      JDWP::Set4BE(buf+1, intVal);
    }
    break;
  case JDWP::JT_ARRAY:
    {
      CHECK_EQ(width, sizeof(JDWP::ObjectId));
      Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
      VLOG(jdwp) << "get array local " << reg << " = " << o;
      if (o != NULL && !Heap::IsHeapAddress(o)) {
        LOG(FATAL) << "Register " << reg << " expected to hold array: " << o;
      }
      JDWP::SetObjectId(buf+1, gRegistry->Add(o));
    }
    break;
  case JDWP::JT_OBJECT:
    {
      CHECK_EQ(width, sizeof(JDWP::ObjectId));
      Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
      VLOG(jdwp) << "get object local " << reg << " = " << o;
      if (o != NULL && !Heap::IsHeapAddress(o)) {
        LOG(FATAL) << "Register " << reg << " expected to hold object: " << o;
      }
      tag = TagFromObject(o);
      JDWP::SetObjectId(buf+1, gRegistry->Add(o));
    }
    break;
  case JDWP::JT_DOUBLE:
  case JDWP::JT_LONG:
    {
      CHECK_EQ(width, 8U);
      uint32_t lo = f.GetVReg(m, reg);
      uint64_t hi = f.GetVReg(m, reg + 1);
      uint64_t longVal = (hi << 32) | lo;
      VLOG(jdwp) << "get double/long local " << hi << ":" << lo << " = " << longVal;
      JDWP::Set8BE(buf+1, longVal);
    }
    break;
  default:
    LOG(FATAL) << "Unknown tag " << tag;
    break;
  }

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

void Dbg::SetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint64_t value, size_t width) {
  Method** sp = reinterpret_cast<Method**>(frameId);
  Frame f(sp);
  Method* m = f.GetMethod();
  uint16_t reg = DemangleSlot(slot, m);

  const VmapTable vmap_table(m->GetVmapTableRaw());
  uint32_t vmap_offset;
  if (vmap_table.IsInContext(reg, vmap_offset)) {
    UNIMPLEMENTED(FATAL) << "Don't know how to pull locals from callee save frames: " << vmap_offset;
  }

  switch (tag) {
  case JDWP::JT_BOOLEAN:
  case JDWP::JT_BYTE:
    CHECK_EQ(width, 1U);
    f.SetVReg(m, reg, static_cast<uint32_t>(value));
    break;
  case JDWP::JT_SHORT:
  case JDWP::JT_CHAR:
    CHECK_EQ(width, 2U);
    f.SetVReg(m, reg, static_cast<uint32_t>(value));
    break;
  case JDWP::JT_INT:
  case JDWP::JT_FLOAT:
    CHECK_EQ(width, 4U);
    f.SetVReg(m, reg, static_cast<uint32_t>(value));
    break;
  case JDWP::JT_ARRAY:
  case JDWP::JT_OBJECT:
  case JDWP::JT_STRING:
    {
      CHECK_EQ(width, sizeof(JDWP::ObjectId));
      Object* o = gRegistry->Get<Object*>(static_cast<JDWP::ObjectId>(value));
      f.SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)));
    }
    break;
  case JDWP::JT_DOUBLE:
  case JDWP::JT_LONG:
    CHECK_EQ(width, 8U);
    f.SetVReg(m, reg, static_cast<uint32_t>(value));
    f.SetVReg(m, reg + 1, static_cast<uint32_t>(value >> 32));
    break;
  default:
    LOG(FATAL) << "Unknown tag " << tag;
    break;
  }
}

void Dbg::PostLocationEvent(const Method* m, int dex_pc, Object* this_object, int event_flags) {
  Class* c = m->GetDeclaringClass();

  JDWP::JdwpLocation location;
  location.typeTag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
  location.classId = gRegistry->Add(c);
  location.methodId = ToMethodId(m);
  location.idx = m->IsNative() ? -1 : dex_pc / 2;

  // Note we use "NoReg" so we don't keep track of references that are
  // never actually sent to the debugger. 'this_id' is only used to
  // compare against registered events...
  JDWP::ObjectId this_id = static_cast<JDWP::ObjectId>(reinterpret_cast<uintptr_t>(this_object));
  if (gJdwpState->PostLocationEvent(&location, this_id, event_flags)) {
    // ...unless there's a registered event, in which case we
    // need to really track the class and 'this'.
    gRegistry->Add(c);
    gRegistry->Add(this_object);
  }
}

void Dbg::PostException(Method** sp, Method* throwMethod, uintptr_t throwNativePc, Method* catchMethod, uintptr_t catchNativePc, Object* exception) {
  if (!gDebuggerActive) {
    return;
  }

  JDWP::JdwpLocation throw_location;
  SetLocation(throw_location, throwMethod, throwNativePc);
  JDWP::JdwpLocation catch_location;
  SetLocation(catch_location, catchMethod, catchNativePc);

  // We need 'this' for InstanceOnly filters.
  JDWP::ObjectId this_id;
  GetThisObject(reinterpret_cast<JDWP::FrameId>(sp), &this_id);

  /*
   * Hand the event to the JDWP exception handler.  Note we're using the
   * "NoReg" objectID on the exception, which is not strictly correct --
   * the exception object WILL be passed up to the debugger if the
   * debugger is interested in the event.  We do this because the current
   * implementation of the debugger object registry never throws anything
   * away, and some people were experiencing a fatal build up of exception
   * objects when dealing with certain libraries.
   */
  JDWP::ObjectId exception_id = static_cast<JDWP::ObjectId>(reinterpret_cast<uintptr_t>(exception));
  JDWP::RefTypeId exception_class_id = gRegistry->Add(exception->GetClass());

  gJdwpState->PostException(&throw_location, exception_id, exception_class_id, &catch_location, this_id);
}

void Dbg::PostClassPrepare(Class* c) {
  if (!gDebuggerActive) {
    return;
  }

  // OLD-TODO - we currently always send both "verified" and "prepared" since
  // debuggers seem to like that.  There might be some advantage to honesty,
  // since the class may not yet be verified.
  int state = JDWP::CS_VERIFIED | JDWP::CS_PREPARED;
  JDWP::JdwpTypeTag tag = c->IsInterface() ? JDWP::TT_INTERFACE : JDWP::TT_CLASS;
  gJdwpState->PostClassPrepare(tag, gRegistry->Add(c), ClassHelper(c).GetDescriptor(), state);
}

void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self, Method** sp) {
  if (!gDebuggerActive || dex_pc == -2 /* fake method exit */) {
    return;
  }

  Frame f(sp);
  f.Next(); // Skip callee save frame.
  Method* m = f.GetMethod();

  if (dex_pc == -1) {
    // We use a pc of -1 to represent method entry, since we might branch back to pc 0 later.
    // This means that for this special notification, there can't be anything else interesting
    // going on, so we're done already.
    Dbg::PostLocationEvent(m, 0, GetThis(f), kMethodEntry);
    return;
  }

  int event_flags = 0;

  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.
  if (gSingleStepControl.is_active && gSingleStepControl.thread == self) {
    CHECK(!m->IsNative());
    if (gSingleStepControl.step_depth == 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 (gSingleStepControl.method != m) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new method";
      } else if (gSingleStepControl.step_size == JDWP::SS_MIN) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new instruction";
      } else if (gSingleStepControl.dex_pcs.find(dex_pc) == gSingleStepControl.dex_pcs.end()) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS new line";
      }
    } else if (gSingleStepControl.step_depth == 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.)

      // TODO: can we just use the value of 'sp'?
      int stack_depth = GetStackDepth(self);

      if (stack_depth < gSingleStepControl.stack_depth) {
        // popped up one or more frames, always trigger
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS method pop";
      } else if (stack_depth == gSingleStepControl.stack_depth) {
        // same depth, see if we moved
        if (gSingleStepControl.step_size == JDWP::SS_MIN) {
          event_flags |= kSingleStep;
          VLOG(jdwp) << "SS new instruction";
        } else if (gSingleStepControl.dex_pcs.find(dex_pc) == gSingleStepControl.dex_pcs.end()) {
          event_flags |= kSingleStep;
          VLOG(jdwp) << "SS new line";
        }
      }
    } else {
      CHECK_EQ(gSingleStepControl.step_depth, 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.

      // TODO: can we just use the value of 'sp'?
      int stack_depth = GetStackDepth(self);
      if (stack_depth < gSingleStepControl.stack_depth) {
        event_flags |= kSingleStep;
        VLOG(jdwp) << "SS method pop";
      }
    }
  }

  // Check to see if this is a "return" instruction.  JDWP says we should
  // send the event *after* the code has been executed, but it also says
  // the location we provide is the last instruction.  Since the "return"
  // instruction has no interesting side effects, we should be safe.
  // (We can't just move this down to the returnFromMethod label because
  // we potentially need to combine it with other events.)
  // We're also not supposed to generate a method exit event if the method
  // terminates "with a thrown exception".
  if (dex_pc >= 0) {
    const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
    CHECK(code_item != NULL);
    CHECK_LT(dex_pc, static_cast<int32_t>(code_item->insns_size_in_code_units_));
    if (Instruction::At(&code_item->insns_[dex_pc])->IsReturn()) {
      event_flags |= kMethodExit;
    }
  }

  // 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, GetThis(f), event_flags);
  }
}

void Dbg::WatchLocation(const JDWP::JdwpLocation* location) {
  MutexLock mu(gBreakpointsLock);
  Method* m = FromMethodId(location->methodId);
  gBreakpoints.push_back(Breakpoint(m, location->idx));
  VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1];
}

void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) {
  MutexLock mu(gBreakpointsLock);
  Method* m = FromMethodId(location->methodId);
  for (size_t i = 0; i < gBreakpoints.size(); ++i) {
    if (gBreakpoints[i].method == m && gBreakpoints[i].pc == location->idx) {
      VLOG(jdwp) << "Removed breakpoint #" << i << ": " << gBreakpoints[i];
      gBreakpoints.erase(gBreakpoints.begin() + i);
      return;
    }
  }
}

JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize step_size, JDWP::JdwpStepDepth step_depth) {
  Thread* thread = DecodeThread(threadId);
  if (thread == NULL) {
    return JDWP::ERR_INVALID_THREAD;
  }

  // TODO: there's no theoretical reason why we couldn't support single-stepping
  // of multiple threads at once, but we never did so historically.
  if (gSingleStepControl.thread != NULL && thread != gSingleStepControl.thread) {
    LOG(WARNING) << "single-step already active for " << *gSingleStepControl.thread
                 << "; switching to " << *thread;
  }

  //
  // Work out what Method* we're in, the current line number, and how deep the stack currently
  // is for step-out.
  //

  struct SingleStepStackVisitor : public Thread::StackVisitor {
    SingleStepStackVisitor() {
      gSingleStepControl.method = NULL;
      gSingleStepControl.stack_depth = 0;
    }
    virtual void VisitFrame(const Frame& f, uintptr_t pc) {
      // TODO: we'll need to skip callee-save frames too.
      if (f.HasMethod()) {
        ++gSingleStepControl.stack_depth;
        if (gSingleStepControl.method == NULL) {
          const Method* m = f.GetMethod();
          const DexCache* dex_cache = m->GetDeclaringClass()->GetDexCache();
          gSingleStepControl.method = m;
          gSingleStepControl.line_number = -1;
          if (dex_cache != NULL) {
            const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
            gSingleStepControl.line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc));
          }
        }
      }
    }
  };
  SingleStepStackVisitor visitor;
  thread->WalkStack(&visitor);

  //
  // Find the dex_pc values that correspond to the current line, for line-based single-stepping.
  //

  struct DebugCallbackContext {
    DebugCallbackContext() {
      last_pc_valid = false;
      last_pc = 0;
      gSingleStepControl.dex_pcs.clear();
    }

    static bool Callback(void* raw_context, uint32_t address, uint32_t line_number) {
      DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context);
      if (static_cast<int32_t>(line_number) == gSingleStepControl.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) {
          gSingleStepControl.dex_pcs.insert(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 = MethodHelper(gSingleStepControl.method).GetCodeItem()->insns_size_in_code_units_;
        for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) {
          gSingleStepControl.dex_pcs.insert(dex_pc);
        }
      }
    }

    bool last_pc_valid;
    uint32_t last_pc;
  };
  DebugCallbackContext context;
  const Method* m = gSingleStepControl.method;
  MethodHelper mh(m);
  mh.GetDexFile().DecodeDebugInfo(mh.GetCodeItem(), m->IsStatic(), m->GetDexMethodIndex(),
                                  DebugCallbackContext::Callback, NULL, &context);

  //
  // Everything else...
  //

  gSingleStepControl.thread = thread;
  gSingleStepControl.step_size = step_size;
  gSingleStepControl.step_depth = step_depth;
  gSingleStepControl.is_active = true;

  if (VLOG_IS_ON(jdwp)) {
    VLOG(jdwp) << "Single-step thread: " << *gSingleStepControl.thread;
    VLOG(jdwp) << "Single-step step size: " << gSingleStepControl.step_size;
    VLOG(jdwp) << "Single-step step depth: " << gSingleStepControl.step_depth;
    VLOG(jdwp) << "Single-step current method: " << PrettyMethod(gSingleStepControl.method);
    VLOG(jdwp) << "Single-step current line: " << gSingleStepControl.line_number;
    VLOG(jdwp) << "Single-step current stack depth: " << gSingleStepControl.stack_depth;
    VLOG(jdwp) << "Single-step dex_pc values:";
    for (std::set<uint32_t>::iterator it = gSingleStepControl.dex_pcs.begin() ; it != gSingleStepControl.dex_pcs.end(); ++it) {
      VLOG(jdwp) << " " << *it;
    }
  }

  return JDWP::ERR_NONE;
}

void Dbg::UnconfigureStep(JDWP::ObjectId threadId) {
  gSingleStepControl.is_active = false;
  gSingleStepControl.thread = NULL;
  gSingleStepControl.dex_pcs.clear();
}

JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId objectId, JDWP::RefTypeId classId, JDWP::MethodId methodId, uint32_t numArgs, uint64_t* argArray, uint32_t options, JDWP::JdwpTag* pResultTag, uint64_t* pResultValue, JDWP::ObjectId* pExceptionId) {
  ThreadList* thread_list = Runtime::Current()->GetThreadList();

  Thread* targetThread = NULL;
  DebugInvokeReq* req = NULL;
  {
    ScopedThreadListLock thread_list_lock;
    targetThread = DecodeThread(threadId);
    if (targetThread == NULL) {
      LOG(ERROR) << "InvokeMethod request for non-existent thread " << threadId;
      return JDWP::ERR_INVALID_THREAD;
    }
    req = targetThread->GetInvokeReq();
    if (!req->ready) {
      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 = 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.
    }

    JDWP::JdwpError status;
    req->receiver_ = gRegistry->Get<Object*>(objectId);
    if (req->receiver_ == kInvalidObject) {
      return JDWP::ERR_INVALID_OBJECT;
    }
    req->thread_ = gRegistry->Get<Object*>(threadId); // TODO: check that this is actually a thread!
    if (req->thread_ == kInvalidObject) {
      return JDWP::ERR_INVALID_OBJECT;
    }
    req->class_ = DecodeClass(classId, status);
    if (req->class_ == NULL) {
      return status;
    }
    req->method_ = FromMethodId(methodId);
    req->num_args_ = numArgs;
    // TODO: check that the argument list is valid.
    req->arg_array_ = argArray;
    req->options_ = options;
    req->invoke_needed_ = true;
  }

  // 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 ResumeAllThreads
  // call, and it's unwise to hold it during WaitForSuspend.

  {
    /*
     * We change our (JDWP thread) status, which should be THREAD_RUNNING,
     * so the VM can suspend for a GC if the invoke request causes us to
     * run out of memory.  It's also a good idea to change it before locking
     * the invokeReq mutex, although that should never be held for long.
     */
    ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);

    VLOG(jdwp) << "    Transferring control to event thread";
    {
      MutexLock mu(req->lock_);

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

      // Wait for the request to finish executing.
      while (req->invoke_needed_) {
        req->cond_.Wait(req->lock_);
      }
    }
    VLOG(jdwp) << "    Control has returned from event thread";

    /* wait for thread to re-suspend itself */
    targetThread->WaitUntilSuspended();
    //dvmWaitForSuspend(targetThread);
  }

  /*
   * Suspend the threads.  We waited for the target thread to suspend
   * itself, so all we need to do is suspend the others.
   *
   * The suspendAllThreads() call will double-suspend the event thread,
   * so we want to resume the target thread once to keep the books straight.
   */
  if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) {
    VLOG(jdwp) << "      Suspending all threads";
    thread_list->SuspendAll(true);
    VLOG(jdwp) << "      Resuming event thread to balance the count";
    thread_list->Resume(targetThread, true);
  }

  // Copy the result.
  *pResultTag = req->result_tag;
  if (IsPrimitiveTag(req->result_tag)) {
    *pResultValue = req->result_value.j;
  } else {
    *pResultValue = gRegistry->Add(req->result_value.l);
  }
  *pExceptionId = req->exception;
  return req->error;
}

void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
  Thread* self = Thread::Current();

  // We can be called while an exception is pending in the VM.  We need
  // to preserve that across the method invocation.
  SirtRef<Throwable> old_exception(self->GetException());
  self->ClearException();

  ScopedThreadStateChange tsc(self, Thread::kRunnable);

  // Translate the method through the vtable, unless the debugger wants to suppress it.
  Method* m = pReq->method_;
  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m);
  if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) {
    m = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_);
    VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m);
  }
  CHECK(m != NULL);

  CHECK_EQ(sizeof(jvalue), sizeof(uint64_t));

  pReq->result_value = InvokeWithJValues(self, pReq->receiver_, m, reinterpret_cast<JValue*>(pReq->arg_array_));

  pReq->exception = gRegistry->Add(self->GetException());
  pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty());
  if (pReq->exception != 0) {
    Object* exc = self->GetException();
    VLOG(jdwp) << "  JDWP invocation returning with exception=" << exc << " " << PrettyTypeOf(exc);
    self->ClearException();
    pReq->result_value.j = 0;
  } else if (pReq->result_tag == JDWP::JT_OBJECT) {
    /* if no exception thrown, examine object result more closely */
    JDWP::JdwpTag new_tag = TagFromObject(pReq->result_value.l);
    if (new_tag != pReq->result_tag) {
      VLOG(jdwp) << "  JDWP promoted result from " << pReq->result_tag << " to " << new_tag;
      pReq->result_tag = new_tag;
    }

    /*
     * Register the object.  We don't actually need an ObjectId yet,
     * but we do need to be sure that the GC won't move or discard the
     * object when we switch out of RUNNING.  The ObjectId conversion
     * will add the object to the "do not touch" list.
     *
     * We can't use the "tracked allocation" mechanism here because
     * the object is going to be handed off to a different thread.
     */
    gRegistry->Add(pReq->result_value.l);
  }

  if (old_exception.get() != NULL) {
    self->SetException(old_exception.get());
  }
}

/*
 * Register an object ID that might not have been registered previously.
 *
 * Normally this wouldn't happen -- the conversion to an ObjectId would
 * have added the object to the registry -- but in some cases (e.g.
 * throwing exceptions) we really want to do the registration late.
 */
void Dbg::RegisterObjectId(JDWP::ObjectId id) {
  gRegistry->Add(reinterpret_cast<Object*>(id));
}

/*
 * "buf" 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(const uint8_t* buf, int dataLen, uint8_t** pReplyBuf, int* pReplyLen) {
  CHECK_GE(dataLen, 0);

  Thread* self = Thread::Current();
  JNIEnv* env = self->GetJniEnv();

  static jclass Chunk_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/Chunk");
  static jclass DdmServer_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
  static jmethodID dispatch_mid = env->GetStaticMethodID(DdmServer_class, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;");
  static jfieldID data_fid = env->GetFieldID(Chunk_class, "data", "[B");
  static jfieldID length_fid = env->GetFieldID(Chunk_class, "length", "I");
  static jfieldID offset_fid = env->GetFieldID(Chunk_class, "offset", "I");
  static jfieldID type_fid = env->GetFieldID(Chunk_class, "type", "I");

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

  const int kChunkHdrLen = 8;

  // Run through and find all chunks.  [Currently just find the first.]
  ScopedByteArrayRO contents(env, dataArray.get());
  jint type = JDWP::Get4BE(reinterpret_cast<const uint8_t*>(&contents[0]));
  jint length = JDWP::Get4BE(reinterpret_cast<const uint8_t*>(&contents[4]));
  jint offset = kChunkHdrLen;
  if (offset + length > dataLen) {
    LOG(WARNING) << StringPrintf("bad chunk found (len=%u pktLen=%d)", length, dataLen);
    return false;
  }

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

  if (chunk.get() == NULL) {
    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 VM, 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(), data_fid)));
  length = env->GetIntField(chunk.get(), length_fid);
  offset = env->GetIntField(chunk.get(), offset_fid);
  type = env->GetIntField(chunk.get(), type_fid);

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

  jsize replyLength = env->GetArrayLength(replyData.get());
  if (offset + length > replyLength) {
    LOG(WARNING) << StringPrintf("chunk off=%d len=%d exceeds reply array len %d", offset, length, replyLength);
    return false;
  }

  uint8_t* reply = new uint8_t[length + kChunkHdrLen];
  if (reply == NULL) {
    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 buf=%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() != Thread::kRunnable) {
    LOG(ERROR) << "DDM broadcast in thread state " << self->GetState();
    /* try anyway? */
  }

  JNIEnv* env = self->GetJniEnv();
  static jclass DdmServer_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
  static jmethodID broadcast_mid = env->GetStaticMethodID(DdmServer_class, "broadcast", "(I)V");
  jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/;
  env->CallStaticVoidMethod(DdmServer_class, broadcast_mid, 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->GetThinLockId());
    Dbg::DdmSendChunk(CHUNK_TYPE("THDE"), 4, buf);
  } else {
    CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
    SirtRef<String> name(t->GetThreadName());
    size_t char_count = (name.get() != NULL) ? name->GetLength() : 0;
    const jchar* chars = name->GetCharArray()->GetData();

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

static void DdmSendThreadStartCallback(Thread* t, void*) {
  Dbg::DdmSendThreadNotification(t, CHUNK_TYPE("THCR"));
}

void Dbg::DdmSetThreadNotification(bool enable) {
  // We lock the thread list to avoid sending duplicate events or missing
  // a thread change. We should be okay holding this lock while sending
  // the messages out. (We have to hold it while accessing a live thread.)
  ScopedThreadListLock thread_list_lock;

  gDdmThreadNotification = enable;
  if (enable) {
    Runtime::Current()->GetThreadList()->ForEach(DdmSendThreadStartCallback, NULL);
  }
}

void Dbg::PostThreadStartOrStop(Thread* t, uint32_t type) {
  if (gDebuggerActive) {
    JDWP::ObjectId id = gRegistry->Add(t->GetPeer());
    gJdwpState->PostThreadChange(id, 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 != NULL);
  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 struct iovec* iov, int iov_count) {
  if (gJdwpState == NULL) {
    VLOG(jdwp) << "Debugger thread not active, ignoring DDM send: " << type;
  } else {
    gJdwpState->DdmSendChunkV(type, iov, iov_count);
  }
}

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;
  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),
        merge_(merge) {
    Reset();
    if (native) {
      type_ = CHUNK_TYPE("NHSG");
    } else {
      type_ = merge ? CHUNK_TYPE("HPSG") : CHUNK_TYPE("HPSO");
    }
  }

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

  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() {
    // 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 HeapChunkCallback(void* start, void* end, size_t used_bytes, void* arg) {
    reinterpret_cast<HeapChunkContext*>(arg)->HeapChunkCallback(start, end, used_bytes);
  }

 private:
  enum { ALLOCATION_UNIT_SIZE = 8 };

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

  void HeapChunkCallback(void* start, void* end, size_t used_bytes) {
    // 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

    const void* user_ptr = used_bytes > 0 ? const_cast<void*>(start) : NULL;
    // from malloc.c mem2chunk(mem)
    const void* chunk_ptr =
        reinterpret_cast<const void*>(reinterpret_cast<const char*>(const_cast<void*>(start)) -
            (2 * sizeof(size_t)));
    // from malloc.c chunksize
    size_t chunk_len = (*reinterpret_cast<size_t* const*>(chunk_ptr))[1] & ~7;


    //size_t chunk_len = malloc_usable_size(user_ptr);
    CHECK_EQ((chunk_len & (ALLOCATION_UNIT_SIZE-1)), 0U);

    /* 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.
     */
    {
      size_t needed = (((chunk_len/ALLOCATION_UNIT_SIZE + 255) / 256) * 2);
      size_t bytesLeft = buf_.size() - (size_t)(p_ - &buf_[0]);
      if (bytesLeft < needed) {
        Flush();
      }

      bytesLeft = buf_.size() - (size_t)(p_ - &buf_[0]);
      if (bytesLeft < needed) {
        LOG(WARNING) << "Chunk is too big to transmit (chunk_len=" << chunk_len << ", " << needed << " bytes)";
        return;
      }
    }

    // OLD-TODO: notice when there's a gap and start a new heap, or at least a new range.
    EnsureHeader(chunk_ptr);

    // 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 = ExamineObject(reinterpret_cast<const Object*>(user_ptr), (type_ == CHUNK_TYPE("NHSG")));

    // Write out the chunk description.
    chunk_len /= ALLOCATION_UNIT_SIZE;   // convert to allocation units
    totalAllocationUnits_ += chunk_len;
    while (chunk_len > 256) {
      *p_++ = state | HPSG_PARTIAL;
      *p_++ = 255;     // length - 1
      chunk_len -= 256;
    }
    *p_++ = state;
    *p_++ = chunk_len - 1;
  }

  uint8_t ExamineObject(const Object* o, bool is_native_heap) {
    if (o == NULL) {
      return HPSG_STATE(SOLIDITY_FREE, 0);
    }

    // It's an allocated chunk. Figure out what it is.

    // If we're looking at the native heap, we'll just return
    // (SOLIDITY_HARD, KIND_NATIVE) for all allocated chunks.
    if (is_native_heap || !Heap::IsLiveObjectLocked(o)) {
      return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
    }

    Class* c = o->GetClass();
    if (c == NULL) {
      // The object was probably just created but hasn't been initialized yet.
      return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
    }

    if (!Heap::IsHeapAddress(c)) {
      LOG(WARNING) << "Invalid class for managed heap object: " << o << " " << c;
      return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
    }

    if (c->IsClassClass()) {
      return HPSG_STATE(SOLIDITY_HARD, KIND_CLASS_OBJECT);
    }

    if (c->IsArrayClass()) {
      if (o->IsObjectArray()) {
        return HPSG_STATE(SOLIDITY_HARD, KIND_ARRAY_4);
      }
      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_;
  size_t totalAllocationUnits_;
  uint32_t type_;
  bool merge_;
  bool needHeader_;

  DISALLOW_COPY_AND_ASSIGN(HeapChunkContext);
};

void Dbg::DdmSendHeapSegments(bool native) {
  Dbg::HpsgWhen when;
  Dbg::HpsgWhat what;
  if (!native) {
    when = gDdmHpsgWhen;
    what = gDdmHpsgWhat;
  } else {
    when = gDdmNhsgWhen;
    what = gDdmNhsgWhat;
  }
  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);

  // Send a series of heap segment chunks.
  HeapChunkContext context((what == HPSG_WHAT_MERGED_OBJECTS), native);
  if (native) {
    // TODO: enable when bionic has moved to dlmalloc 2.8.5
    // dlmalloc_inspect_all(HeapChunkContext::HeapChunkCallback, &context);
    UNIMPLEMENTED(WARNING) << "Native heap send heap segments";
  } else {
    Heap::GetAllocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &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 enabled) {
  MutexLock mu(gAllocTrackerLock);
  if (enabled) {
    if (recent_allocation_records_ == NULL) {
      LOG(INFO) << "Enabling alloc tracker (" << kNumAllocRecords << " entries, "
                << kMaxAllocRecordStackDepth << " frames --> "
                << (sizeof(AllocRecord) * kNumAllocRecords) << " bytes)";
      gAllocRecordHead = gAllocRecordCount = 0;
      recent_allocation_records_ = new AllocRecord[kNumAllocRecords];
      CHECK(recent_allocation_records_ != NULL);
    }
  } else {
    delete[] recent_allocation_records_;
    recent_allocation_records_ = NULL;
  }
}

struct AllocRecordStackVisitor : public Thread::StackVisitor {
  explicit AllocRecordStackVisitor(AllocRecord* record) : record(record), depth(0) {
  }

  virtual void VisitFrame(const Frame& f, uintptr_t pc) {
    if (depth >= kMaxAllocRecordStackDepth) {
      return;
    }
    Method* m = f.GetMethod();
    if (m == NULL || m->IsCalleeSaveMethod()) {
      return;
    }
    record->stack[depth].method = m;
    record->stack[depth].raw_pc = pc;
    ++depth;
  }

  ~AllocRecordStackVisitor() {
    // Clear out any unused stack trace elements.
    for (; depth < kMaxAllocRecordStackDepth; ++depth) {
      record->stack[depth].method = NULL;
      record->stack[depth].raw_pc = 0;
    }
  }

  AllocRecord* record;
  size_t depth;
};

void Dbg::RecordAllocation(Class* type, size_t byte_count) {
  Thread* self = Thread::Current();
  CHECK(self != NULL);

  MutexLock mu(gAllocTrackerLock);
  if (recent_allocation_records_ == NULL) {
    return;
  }

  // Advance and clip.
  if (++gAllocRecordHead == kNumAllocRecords) {
    gAllocRecordHead = 0;
  }

  // Fill in the basics.
  AllocRecord* record = &recent_allocation_records_[gAllocRecordHead];
  record->type = type;
  record->byte_count = byte_count;
  record->thin_lock_id = self->GetThinLockId();

  // Fill in the stack trace.
  AllocRecordStackVisitor visitor(record);
  self->WalkStack(&visitor);

  if (gAllocRecordCount < kNumAllocRecords) {
    ++gAllocRecordCount;
  }
}

/*
 * Return the index of the head element.
 *
 * We point at the most-recently-written record, so if allocRecordCount is 1
 * we want to use the current element.  Take "head+1" and subtract count
 * from it.
 *
 * We need to handle underflow in our circular buffer, so we add
 * kNumAllocRecords and then mask it back down.
 */
inline static int headIndex() {
  return (gAllocRecordHead+1 + kNumAllocRecords - gAllocRecordCount) & (kNumAllocRecords-1);
}

void Dbg::DumpRecentAllocations() {
  MutexLock mu(gAllocTrackerLock);
  if (recent_allocation_records_ == NULL) {
    LOG(INFO) << "Not recording tracked allocations";
    return;
  }

  // "i" is the head of the list.  We want to start at the end of the
  // list and move forward to the tail.
  size_t i = headIndex();
  size_t count = gAllocRecordCount;

  LOG(INFO) << "Tracked allocations, (head=" << gAllocRecordHead << " count=" << count << ")";
  while (count--) {
    AllocRecord* record = &recent_allocation_records_[i];

    LOG(INFO) << StringPrintf(" T=%-2d %6zd ", record->thin_lock_id, record->byte_count)
              << PrettyClass(record->type);

    for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
      const Method* m = record->stack[stack_frame].method;
      if (m == NULL) {
        break;
      }
      LOG(INFO) << "    " << PrettyMethod(m) << " line " << record->stack[stack_frame].LineNumber();
    }

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

    i = (i + 1) & (kNumAllocRecords-1);
  }
}

class StringTable {
 public:
  StringTable() {
  }

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

  size_t IndexOf(const char* s) {
    return std::distance(table_.begin(), table_.find(s));
  }

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

  void WriteTo(std::vector<uint8_t>& bytes) {
    typedef std::set<const char*>::const_iterator It; // TODO: C++0x auto
    for (It it = table_.begin(); it != table_.end(); ++it) {
      const char* s = *it;
      size_t s_len = CountModifiedUtf8Chars(s);
      UniquePtr<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<const char*> table_;
  DISALLOW_COPY_AND_ASSIGN(StringTable);
};

/*
 * 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) threadId
 *   (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 * kNumAllocRecords) 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();
  }

  MutexLock mu(gAllocTrackerLock);

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

  int count = gAllocRecordCount;
  int idx = headIndex();
  while (count--) {
    AllocRecord* record = &recent_allocation_records_[idx];

    class_names.Add(ClassHelper(record->type).GetDescriptor());

    MethodHelper mh;
    for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
      Method* m = record->stack[i].method;
      mh.ChangeMethod(m);
      if (m != NULL) {
        class_names.Add(mh.GetDeclaringClassDescriptor());
        method_names.Add(mh.GetName());
        filenames.Add(mh.GetDeclaringClassSourceFile());
      }
    }

    idx = (idx + 1) & (kNumAllocRecords-1);
  }

  LOG(INFO) << "allocation records: " << gAllocRecordCount;

  /*
   * Part 2: allocate a buffer and generate the output.
   */
  std::vector<uint8_t> bytes;

  // (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, gAllocRecordCount);
  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());

  count = gAllocRecordCount;
  idx = headIndex();
  ClassHelper kh;
  while (count--) {
    // For each entry:
    // (4b) total allocation size
    // (2b) thread id
    // (2b) allocated object's class name index
    // (1b) stack depth
    AllocRecord* record = &recent_allocation_records_[idx];
    size_t stack_depth = record->GetDepth();
    JDWP::Append4BE(bytes, record->byte_count);
    JDWP::Append2BE(bytes, record->thin_lock_id);
    kh.ChangeClass(record->type);
    JDWP::Append2BE(bytes, class_names.IndexOf(kh.GetDescriptor()));
    JDWP::Append1BE(bytes, stack_depth);

    MethodHelper mh;
    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
      mh.ChangeMethod(record->stack[stack_frame].method);
      JDWP::Append2BE(bytes, class_names.IndexOf(mh.GetDeclaringClassDescriptor()));
      JDWP::Append2BE(bytes, method_names.IndexOf(mh.GetName()));
      JDWP::Append2BE(bytes, filenames.IndexOf(mh.GetDeclaringClassSourceFile()));
      JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber());
    }

    idx = (idx + 1) & (kNumAllocRecords-1);
  }

  // (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 = Thread::Current()->GetJniEnv();
  jbyteArray result = env->NewByteArray(bytes.size());
  if (result != NULL) {
    env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0]));
  }
  return result;
}

}  // namespace art
