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" },