Implement ReferenceType.Instances.

Change-Id: I6a72fc4c748e7041fedcb615eca2b86b1f28bb63
diff --git a/src/debugger.cc b/src/debugger.cc
index 44785ba..f52c42a 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -759,6 +759,22 @@
   return JDWP::ERR_NONE;
 }
 
+JDWP::JdwpError Dbg::GetInstances(JDWP::RefTypeId class_id, int32_t max_count, std::vector<JDWP::ObjectId>& instances)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  JDWP::JdwpError status;
+  Class* c = DecodeClass(class_id, status);
+  if (c == NULL) {
+    return status;
+  }
+
+  std::vector<Object*> raw_instances;
+  Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances);
+  for (size_t i = 0; i < raw_instances.size(); ++i) {
+    instances.push_back(gRegistry->Add(raw_instances[i]));
+  }
+  return JDWP::ERR_NONE;
+}
+
 JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError status;
   Class* c = DecodeClass(class_id, status);
diff --git a/src/debugger.h b/src/debugger.h
index 1bad6cc..ebcff08 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -189,6 +189,9 @@
   static JDWP::JdwpError GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
                                            std::vector<uint64_t>& counts)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
+                                      std::vector<JDWP::ObjectId>& instances)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
    * Method and Field
diff --git a/src/heap.cc b/src/heap.cc
index 989a0b9..db49c61 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -879,6 +879,43 @@
   GetLiveBitmap()->Visit(counter);
 }
 
+class InstanceCollector {
+ public:
+  InstanceCollector(Class* c, int32_t max_count, std::vector<Object*>& instances)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : class_(c), max_count_(max_count), instances_(instances) {
+  }
+
+  void operator()(const Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    const Class* instance_class = o->GetClass();
+    if (instance_class == class_) {
+      if (max_count_ == 0 || instances_.size() < max_count_) {
+        instances_.push_back(const_cast<Object*>(o));
+      }
+    }
+  }
+
+ private:
+  Class* class_;
+  uint32_t max_count_;
+  std::vector<Object*>& instances_;
+
+  DISALLOW_COPY_AND_ASSIGN(InstanceCollector);
+};
+
+void Heap::GetInstances(Class* c, int32_t max_count, std::vector<Object*>& instances) {
+  // We only want reachable instances, so do a GC. This also ensures that the alloc stack
+  // is empty, so the live bitmap is the only place we need to look.
+  Thread* self = Thread::Current();
+  self->TransitionFromRunnableToSuspended(kNative);
+  CollectGarbage(false);
+  self->TransitionFromSuspendedToRunnable();
+
+  InstanceCollector collector(c, max_count, instances);
+  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  GetLiveBitmap()->Visit(collector);
+}
+
 void Heap::CollectGarbage(bool clear_soft_references) {
   // Even if we waited for a GC we still need to do another GC since weaks allocated during the
   // last GC will not have necessarily been cleared.
diff --git a/src/heap.h b/src/heap.h
index bd9945d..fd08f29 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -173,6 +173,10 @@
                       uint64_t* counts)
       LOCKS_EXCLUDED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Implements JDWP RT_Instances.
+  void GetInstances(Class* c, int32_t max_count, std::vector<Object*>& instances)
+      LOCKS_EXCLUDED(Locks::heap_bitmap_lock_)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Removes the growth limit on the alloc space so it may grow to its maximum capacity. Used to
   // implement dalvik.system.VMRuntime.clearGrowthLimit.
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index f68e560..86ecffe 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -649,6 +649,30 @@
   return Dbg::OutputDeclaredMethods(refTypeId, false, pReply);
 }
 
+static JdwpError RT_Instances(JdwpState*, const uint8_t* buf, int, ExpandBuf* reply)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  RefTypeId class_id = ReadRefTypeId(&buf);
+  int32_t max_count = Read4BE(&buf);
+  if (max_count < 0) {
+    return ERR_ILLEGAL_ARGUMENT;
+  }
+
+  std::vector<ObjectId> instances;
+  JdwpError rc = Dbg::GetInstances(class_id, max_count, instances);
+  if (rc != ERR_NONE) {
+    return rc;
+  }
+
+  expandBufAdd4BE(reply, instances.size());
+  for (size_t i = 0; i < instances.size(); ++i) {
+    rc = WriteTaggedObject(reply, instances[i]);
+    if (rc != ERR_NONE) {
+      return rc;
+    }
+  }
+  return ERR_NONE;
+}
+
 /*
  * Return the immediate superclass of a class.
  */
@@ -1616,7 +1640,7 @@
   { 2,    13, RT_SignatureWithGeneric, "ReferenceType.SignatureWithGeneric" },
   { 2,    14, RT_FieldsWithGeneric,    "ReferenceType.FieldsWithGeneric" },
   { 2,    15, RT_MethodsWithGeneric,   "ReferenceType.MethodsWithGeneric" },
-  { 2,    16, NULL,                    "ReferenceType.Instances" },
+  { 2,    16, RT_Instances,            "ReferenceType.Instances" },
   { 2,    17, NULL,                    "ReferenceType.ClassFileVersion" },
   { 2,    18, NULL,                    "ReferenceType.ConstantPool" },