Manage JDWP errors related to garbage collection.

Returns INVALID_OBJECT error in case of invalid object ID or null object ID in
commands ObjectReference.DisableCollection, ObjectReference.EnableCollection
and ObjectReference.IsCollected.

Note: JDWP specs do not state ObjectReference.EnableCollection must return any
error code. We choose to be more strict so these three commands all behave the
same.

Change-Id: I06fb75b75f7d33cf4d23e121d9541bfd70b778bb
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 52a2141..edfd21f 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -795,18 +795,37 @@
 
 JDWP::JdwpError Dbg::DisableCollection(JDWP::ObjectId object_id)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id);
+  if (o == NULL || o == ObjectRegistry::kInvalidObject) {
+    return JDWP::ERR_INVALID_OBJECT;
+  }
   gRegistry->DisableCollection(object_id);
   return JDWP::ERR_NONE;
 }
 
 JDWP::JdwpError Dbg::EnableCollection(JDWP::ObjectId object_id)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id);
+  // Unlike DisableCollection, JDWP specs do not state an invalid object causes an error. The RI
+  // also ignores these cases and never return an error. However it's not obvious why this command
+  // should behave differently from DisableCollection and IsCollected commands. So let's be more
+  // strict and return an error if this happens.
+  if (o == NULL || o == ObjectRegistry::kInvalidObject) {
+    return JDWP::ERR_INVALID_OBJECT;
+  }
   gRegistry->EnableCollection(object_id);
   return JDWP::ERR_NONE;
 }
 
 JDWP::JdwpError Dbg::IsCollected(JDWP::ObjectId object_id, bool& is_collected)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id);
+  // JDWP specs state an INVALID_OBJECT error is returned if the object ID is not valid. However
+  // the RI seems to ignore this and does not return any error in this case. Let's comply with
+  // JDWP specs here.
+  if (o == NULL || o == ObjectRegistry::kInvalidObject) {
+    return JDWP::ERR_INVALID_OBJECT;
+  }
   is_collected = gRegistry->IsCollected(object_id);
   return JDWP::ERR_NONE;
 }
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index be2219c..b2371e8 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -130,9 +130,7 @@
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
   id_iterator it = id_to_entry_.find(id);
-  if (it == id_to_entry_.end()) {
-    return;
-  }
+  CHECK(it != id_to_entry_.end());
   Promote(*(it->second));
 }
 
@@ -140,9 +138,7 @@
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
   id_iterator it = id_to_entry_.find(id);
-  if (it == id_to_entry_.end()) {
-    return;
-  }
+  CHECK(it != id_to_entry_.end());
   Demote(*(it->second));
 }
 
@@ -172,9 +168,7 @@
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
   id_iterator it = id_to_entry_.find(id);
-  if (it == id_to_entry_.end()) {
-    return true;  // TODO: can we report that this was an invalid id?
-  }
+  CHECK(it != id_to_entry_.end());
 
   ObjectRegistryEntry& entry = *(it->second);
   if (entry.jni_reference_type == JNIWeakGlobalRefType) {