Implement ObjectReference.ReferringObjects.

Bug: 4159882
Change-Id: Iac145715bec80b5900256d3f6bdb18e283eb9a12
diff --git a/src/debugger.cc b/src/debugger.cc
index f52c42a..1df7fe9 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -775,6 +775,22 @@
   return JDWP::ERR_NONE;
 }
 
+JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
+                                         std::vector<JDWP::ObjectId>& referring_objects)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Object* o = gRegistry->Get<Object*>(object_id);
+  if (o == NULL || o == kInvalidObject) {
+    return JDWP::ERR_INVALID_OBJECT;
+  }
+
+  std::vector<Object*> raw_instances;
+  Runtime::Current()->GetHeap()->GetReferringObjects(o, max_count, raw_instances);
+  for (size_t i = 0; i < raw_instances.size(); ++i) {
+    referring_objects.push_back(gRegistry->Add(raw_instances[i]));
+  }
+  return JDWP::ERR_NONE;
+}
+
 JDWP::JdwpError Dbg::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 ebcff08..c03adea 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -192,6 +192,9 @@
   static JDWP::JdwpError GetInstances(JDWP::RefTypeId class_id, int32_t max_count,
                                       std::vector<JDWP::ObjectId>& instances)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static JDWP::JdwpError GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
+                                             std::vector<JDWP::ObjectId>& referring_objects)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
    * Method and Field
diff --git a/src/heap.cc b/src/heap.cc
index db49c61..656aae7 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -916,6 +916,49 @@
   GetLiveBitmap()->Visit(collector);
 }
 
+class ReferringObjectsFinder {
+ public:
+  ReferringObjectsFinder(Object* object, int32_t max_count, std::vector<Object*>& referring_objects)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : object_(object), max_count_(max_count), referring_objects_(referring_objects) {
+  }
+
+  // For bitmap Visit.
+  // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
+  // annotalysis on visitors.
+  void operator()(const Object* o) const NO_THREAD_SAFETY_ANALYSIS {
+    MarkSweep::VisitObjectReferences(o, *this);
+  }
+
+  // For MarkSweep::VisitObjectReferences.
+  void operator ()(const Object* referrer, const Object* object, const MemberOffset&, bool) const {
+    if (object == object_ && (max_count_ == 0 || referring_objects_.size() < max_count_)) {
+      referring_objects_.push_back(const_cast<Object*>(referrer));
+    }
+  }
+
+ private:
+  Object* object_;
+  uint32_t max_count_;
+  std::vector<Object*>& referring_objects_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReferringObjectsFinder);
+};
+
+void Heap::GetReferringObjects(Object* o, int32_t max_count,
+                               std::vector<Object*>& referring_objects) {
+  // 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();
+
+  ReferringObjectsFinder finder(o, max_count, referring_objects);
+  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  GetLiveBitmap()->Visit(finder);
+}
+
 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 fd08f29..78cbe99 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -177,6 +177,10 @@
   void GetInstances(Class* c, int32_t max_count, std::vector<Object*>& instances)
       LOCKS_EXCLUDED(Locks::heap_bitmap_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Implements JDWP OR_ReferringObjects.
+  void GetReferringObjects(Object* o, int32_t max_count, std::vector<Object*>& referring_objects)
+      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 86ecffe..23a3130 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -95,6 +95,18 @@
   return rc;
 }
 
+static JdwpError WriteTaggedObjectList(ExpandBuf* reply, const std::vector<ObjectId>& objects)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  expandBufAdd4BE(reply, objects.size());
+  for (size_t i = 0; i < objects.size(); ++i) {
+    JdwpError rc = WriteTaggedObject(reply, objects[i]);
+    if (rc != ERR_NONE) {
+      return rc;
+    }
+  }
+  return ERR_NONE;
+}
+
 /*
  * Common code for *_InvokeMethod requests.
  *
@@ -663,14 +675,7 @@
     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 WriteTaggedObjectList(reply, instances);
 }
 
 /*
@@ -949,6 +954,23 @@
   return ERR_NONE;
 }
 
+static JdwpError OR_ReferringObjects(JdwpState*, const uint8_t* buf, int, ExpandBuf* reply)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ObjectId object_id = ReadObjectId(&buf);
+  int32_t max_count = Read4BE(&buf);
+  if (max_count < 0) {
+    return ERR_ILLEGAL_ARGUMENT;
+  }
+
+  std::vector<ObjectId> referring_objects;
+  JdwpError rc = Dbg::GetReferringObjects(object_id, max_count, referring_objects);
+  if (rc != ERR_NONE) {
+    return rc;
+  }
+
+  return WriteTaggedObjectList(reply, referring_objects);
+}
+
 /*
  * Return the string value in a string object.
  */
@@ -1674,7 +1696,7 @@
   { 9,    7,  OR_DisableCollection, "ObjectReference.DisableCollection" },
   { 9,    8,  OR_EnableCollection,  "ObjectReference.EnableCollection" },
   { 9,    9,  OR_IsCollected,       "ObjectReference.IsCollected" },
-  { 9,    10, NULL,                 "ObjectReference.ReferringObjects" },
+  { 9,    10, OR_ReferringObjects,  "ObjectReference.ReferringObjects" },
 
   /* StringReference command set (10) */
   { 10,   1,  SR_Value,         "StringReference.Value" },