Make debugger / jdwp compaction safe.

Fixed GetInstances, GetReferringObjects, CountInstances to use
VisitObjects instead of the live bitmap.

We now treat the object registry as system weaks and update the
objects when/if they move. Also added the recent_allocation_records_
as roots.

Bug: 12936165

Change-Id: I615c289efbf2977ceab5c4ffa73d216d799e6e33
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 99e7867..8280c7c 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -63,6 +63,9 @@
   mirror::ArtMethod* method;
   uint32_t dex_pc;
 
+  AllocRecordStackTraceElement() : method(nullptr), dex_pc(0) {
+  }
+
   int32_t LineNumber() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return MethodHelper(method).GetLineNumFromDexPC(dex_pc);
   }
@@ -81,6 +84,20 @@
     }
     return depth;
   }
+
+  void UpdateObjectPointers(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    if (type != nullptr) {
+      type = down_cast<mirror::Class*>(visitor(type, arg));
+    }
+    for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
+      mirror::ArtMethod*& m = stack[stack_frame].method;
+      if (m == nullptr) {
+        break;
+      }
+      m = down_cast<mirror::ArtMethod*>(visitor(m, arg));
+    }
+  }
 };
 
 struct Breakpoint {
@@ -775,6 +792,8 @@
 JDWP::JdwpError Dbg::GetInstanceCounts(const std::vector<JDWP::RefTypeId>& class_ids,
                                        std::vector<uint64_t>& counts)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  heap->CollectGarbage(false);
   std::vector<mirror::Class*> classes;
   counts.clear();
   for (size_t i = 0; i < class_ids.size(); ++i) {
@@ -786,19 +805,20 @@
     classes.push_back(c);
     counts.push_back(0);
   }
-
-  Runtime::Current()->GetHeap()->CountInstances(classes, false, &counts[0]);
+  heap->CountInstances(classes, false, &counts[0]);
   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_) {
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  // We only want reachable instances, so do a GC.
+  heap->CollectGarbage(false);
   JDWP::JdwpError status;
   mirror::Class* c = DecodeClass(class_id, status);
-  if (c == NULL) {
+  if (c == nullptr) {
     return status;
   }
-
   std::vector<mirror::Object*> raw_instances;
   Runtime::Current()->GetHeap()->GetInstances(c, max_count, raw_instances);
   for (size_t i = 0; i < raw_instances.size(); ++i) {
@@ -810,13 +830,14 @@
 JDWP::JdwpError Dbg::GetReferringObjects(JDWP::ObjectId object_id, int32_t max_count,
                                          std::vector<JDWP::ObjectId>& referring_objects)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  heap->CollectGarbage(false);
   mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id);
   if (o == NULL || o == ObjectRegistry::kInvalidObject) {
     return JDWP::ERR_INVALID_OBJECT;
   }
-
   std::vector<mirror::Object*> raw_instances;
-  Runtime::Current()->GetHeap()->GetReferringObjects(o, max_count, raw_instances);
+  heap->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]));
   }
@@ -3772,6 +3793,37 @@
   }
 }
 
+void Dbg::UpdateObjectPointers(RootVisitor* visitor, void* arg) {
+  {
+    MutexLock mu(Thread::Current(), gAllocTrackerLock);
+    if (recent_allocation_records_ != nullptr) {
+      size_t i = HeadIndex();
+      size_t count = gAllocRecordCount;
+      while (count--) {
+        AllocRecord* record = &recent_allocation_records_[i];
+        DCHECK(record != nullptr);
+        record->UpdateObjectPointers(visitor, arg);
+        i = (i + 1) & (gAllocRecordMax - 1);
+      }
+    }
+  }
+  if (gRegistry != nullptr) {
+    gRegistry->UpdateObjectPointers(visitor, arg);
+  }
+}
+
+void Dbg::AllowNewObjectRegistryObjects() {
+  if (gRegistry != nullptr) {
+    gRegistry->AllowNewObjects();
+  }
+}
+
+void Dbg::DisallowNewObjectRegistryObjects() {
+  if (gRegistry != nullptr) {
+    gRegistry->DisallowNewObjects();
+  }
+}
+
 class StringTable {
  public:
   StringTable() {
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 328c9cd..f1e3f45 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -452,6 +452,10 @@
   static jbyteArray GetRecentAllocations() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void DumpRecentAllocations();
 
+  // Updates the stored direct object pointers (called from SweepSystemWeaks).
+  static void UpdateObjectPointers(RootVisitor* visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   enum HpifWhen {
     HPIF_WHEN_NEVER = 0,
     HPIF_WHEN_NOW = 1,
@@ -476,6 +480,9 @@
   static void DdmSendHeapSegments(bool native)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  static void AllowNewObjectRegistryObjects() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static void DisallowNewObjectRegistryObjects() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   static void DdmBroadcast(bool connect) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void PostThreadStartOrStop(Thread*, uint32_t)
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index f438ca0..62567d7 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -1061,18 +1061,18 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : classes_(classes), use_is_assignable_from_(use_is_assignable_from), counts_(counts) {
   }
-
-  void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (size_t i = 0; i < classes_.size(); ++i) {
-      mirror::Class* instance_class = o->GetClass();
-      if (use_is_assignable_from_) {
-        if (instance_class != NULL && classes_[i]->IsAssignableFrom(instance_class)) {
-          ++counts_[i];
+  static void Callback(mirror::Object* obj, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+    InstanceCounter* instance_counter = reinterpret_cast<InstanceCounter*>(arg);
+    mirror::Class* instance_class = obj->GetClass();
+    CHECK(instance_class != nullptr);
+    for (size_t i = 0; i < instance_counter->classes_.size(); ++i) {
+      if (instance_counter->use_is_assignable_from_) {
+        if (instance_counter->classes_[i]->IsAssignableFrom(instance_class)) {
+          ++instance_counter->counts_[i];
         }
-      } else {
-        if (instance_class == classes_[i]) {
-          ++counts_[i];
-        }
+      } else if (instance_class == instance_counter->classes_[i]) {
+        ++instance_counter->counts_[i];
       }
     }
   }
@@ -1081,22 +1081,18 @@
   const std::vector<mirror::Class*>& classes_;
   bool use_is_assignable_from_;
   uint64_t* const counts_;
-
   DISALLOW_COPY_AND_ASSIGN(InstanceCounter);
 };
 
 void Heap::CountInstances(const std::vector<mirror::Class*>& classes, bool use_is_assignable_from,
                           uint64_t* counts) {
-  // 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.
+  // Can't do any GC in this function since this may move classes.
   Thread* self = Thread::Current();
-  self->TransitionFromRunnableToSuspended(kNative);
-  CollectGarbage(false);
-  self->TransitionFromSuspendedToRunnable();
-
+  auto* old_cause = self->StartAssertNoThreadSuspension("CountInstances");
   InstanceCounter counter(classes, use_is_assignable_from, counts);
-  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
-  GetLiveBitmap()->Visit(counter);
+  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  VisitObjects(InstanceCounter::Callback, &counter);
+  self->EndAssertNoThreadSuspension(old_cause);
 }
 
 class InstanceCollector {
@@ -1105,12 +1101,15 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : class_(c), max_count_(max_count), instances_(instances) {
   }
-
-  void operator()(mirror::Object* o) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::Class* instance_class = o->GetClass();
-    if (instance_class == class_) {
-      if (max_count_ == 0 || instances_.size() < max_count_) {
-        instances_.push_back(o);
+  static void Callback(mirror::Object* obj, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+    DCHECK(arg != nullptr);
+    InstanceCollector* instance_collector = reinterpret_cast<InstanceCollector*>(arg);
+    mirror::Class* instance_class = obj->GetClass();
+    if (instance_class == instance_collector->class_) {
+      if (instance_collector->max_count_ == 0 ||
+          instance_collector->instances_.size() < instance_collector->max_count_) {
+        instance_collector->instances_.push_back(obj);
       }
     }
   }
@@ -1119,22 +1118,18 @@
   mirror::Class* class_;
   uint32_t max_count_;
   std::vector<mirror::Object*>& instances_;
-
   DISALLOW_COPY_AND_ASSIGN(InstanceCollector);
 };
 
 void Heap::GetInstances(mirror::Class* c, int32_t max_count,
                         std::vector<mirror::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.
+  // Can't do any GC in this function since this may move classes.
   Thread* self = Thread::Current();
-  self->TransitionFromRunnableToSuspended(kNative);
-  CollectGarbage(false);
-  self->TransitionFromSuspendedToRunnable();
-
+  auto* old_cause = self->StartAssertNoThreadSuspension("GetInstances");
   InstanceCollector collector(c, max_count, instances);
-  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
-  GetLiveBitmap()->Visit(collector);
+  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  VisitObjects(&InstanceCollector::Callback, &collector);
+  self->EndAssertNoThreadSuspension(old_cause);
 }
 
 class ReferringObjectsFinder {
@@ -1145,6 +1140,11 @@
       : object_(object), max_count_(max_count), referring_objects_(referring_objects) {
   }
 
+  static void Callback(mirror::Object* obj, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
+    reinterpret_cast<ReferringObjectsFinder*>(arg)->operator()(obj);
+  }
+
   // For bitmap Visit.
   // TODO: Fix lock analysis to not use NO_THREAD_SAFETY_ANALYSIS, requires support for
   // annotalysis on visitors.
@@ -1164,22 +1164,18 @@
   mirror::Object* object_;
   uint32_t max_count_;
   std::vector<mirror::Object*>& referring_objects_;
-
   DISALLOW_COPY_AND_ASSIGN(ReferringObjectsFinder);
 };
 
 void Heap::GetReferringObjects(mirror::Object* o, int32_t max_count,
                                std::vector<mirror::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.
+  // Can't do any GC in this function since this may move classes.
   Thread* self = Thread::Current();
-  self->TransitionFromRunnableToSuspended(kNative);
-  CollectGarbage(false);
-  self->TransitionFromSuspendedToRunnable();
-
+  auto* old_cause = self->StartAssertNoThreadSuspension("GetReferringObjects");
   ReferringObjectsFinder finder(o, max_count, referring_objects);
-  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
-  GetLiveBitmap()->Visit(finder);
+  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  VisitObjects(&ReferringObjectsFinder::Callback, &finder);
+  self->EndAssertNoThreadSuspension(old_cause);
 }
 
 void Heap::CollectGarbage(bool clear_soft_references) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index f35ff4f..476ceee 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -249,7 +249,7 @@
   void DecrementDisableMovingGC(Thread* self);
 
   // Initiates an explicit garbage collection.
-  void CollectGarbage(bool clear_soft_references) LOCKS_EXCLUDED(Locks::mutator_lock_);
+  void CollectGarbage(bool clear_soft_references);
 
   // Does a concurrent GC, should only be called by the GC daemon thread
   // through runtime.
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index 369eddd..40ba3e3 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -31,7 +31,8 @@
 }
 
 ObjectRegistry::ObjectRegistry()
-    : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) {
+    : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), allow_new_objects_(true),
+      condition_("object registry condition", lock_), next_id_(1) {
 }
 
 JDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) {
@@ -49,58 +50,59 @@
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
   MutexLock mu(soa.Self(), lock_);
-  ObjectRegistryEntry dummy;
-  dummy.jni_reference_type = JNIWeakGlobalRefType;
-  dummy.jni_reference = NULL;
-  dummy.reference_count = 0;
-  dummy.id = 0;
-  std::pair<object_iterator, bool> result = object_to_entry_.insert(std::make_pair(o, dummy));
-  ObjectRegistryEntry& entry = result.first->second;
-  if (!result.second) {
-    // This object was already in our map.
-    entry.reference_count += 1;
-    return entry.id;
+  while (UNLIKELY(!allow_new_objects_)) {
+    condition_.WaitHoldingLocks(soa.Self());
   }
+  ObjectRegistryEntry* entry;
+  auto it = object_to_entry_.find(o);
+  if (it != object_to_entry_.end()) {
+    // This object was already in our map.
+    entry = it->second;
+    ++entry->reference_count;
+  } else {
+    entry = new ObjectRegistryEntry;
+    entry->jni_reference_type = JNIWeakGlobalRefType;
+    entry->jni_reference = nullptr;
+    entry->reference_count = 0;
+    entry->id = 0;
+    object_to_entry_.insert(std::make_pair(o, entry));
 
-  // This object isn't in the registry yet, so add it.
-  JNIEnv* env = soa.Env();
+    // This object isn't in the registry yet, so add it.
+    JNIEnv* env = soa.Env();
 
-  jobject local_reference = soa.AddLocalReference<jobject>(o);
+    jobject local_reference = soa.AddLocalReference<jobject>(o);
 
-  entry.jni_reference_type = JNIWeakGlobalRefType;
-  entry.jni_reference = env->NewWeakGlobalRef(local_reference);
-  entry.reference_count = 1;
-  entry.id = next_id_++;
+    entry->jni_reference_type = JNIWeakGlobalRefType;
+    entry->jni_reference = env->NewWeakGlobalRef(local_reference);
+    entry->reference_count = 1;
+    entry->id = next_id_++;
 
-  id_to_entry_.Put(entry.id, &entry);
+    id_to_entry_.Put(entry->id, entry);
 
-  env->DeleteLocalRef(local_reference);
-
-  return entry.id;
+    env->DeleteLocalRef(local_reference);
+  }
+  return entry->id;
 }
 
 bool ObjectRegistry::Contains(mirror::Object* o) {
-  Thread* self = Thread::Current();
-  MutexLock mu(self, lock_);
-  return (object_to_entry_.find(o) != object_to_entry_.end());
+  MutexLock mu(Thread::Current(), lock_);
+  return object_to_entry_.find(o) != object_to_entry_.end();
 }
 
 void ObjectRegistry::Clear() {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
   VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
-
   // Delete all the JNI references.
   JNIEnv* env = self->GetJniEnv();
-  for (object_iterator it = object_to_entry_.begin(); it != object_to_entry_.end(); ++it) {
-    ObjectRegistryEntry& entry = (it->second);
+  for (const auto& pair : object_to_entry_) {
+    const ObjectRegistryEntry& entry = *pair.second;
     if (entry.jni_reference_type == JNIWeakGlobalRefType) {
       env->DeleteWeakGlobalRef(entry.jni_reference);
     } else {
       env->DeleteGlobalRef(entry.jni_reference);
     }
   }
-
   // Clear the maps.
   object_to_entry_.clear();
   id_to_entry_.clear();
@@ -109,11 +111,11 @@
 mirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   if (it == id_to_entry_.end()) {
     return kInvalidObject;
   }
-  ObjectRegistryEntry& entry = *(it->second);
+  ObjectRegistryEntry& entry = *it->second;
   return self->DecodeJObject(entry.jni_reference);
 }
 
@@ -123,26 +125,26 @@
   }
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   CHECK(it != id_to_entry_.end()) << id;
-  ObjectRegistryEntry& entry = *(it->second);
+  ObjectRegistryEntry& entry = *it->second;
   return entry.jni_reference;
 }
 
 void ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   CHECK(it != id_to_entry_.end());
-  Promote(*(it->second));
+  Promote(*it->second);
 }
 
 void ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   CHECK(it != id_to_entry_.end());
-  Demote(*(it->second));
+  Demote(*it->second);
 }
 
 void ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
@@ -170,10 +172,9 @@
 bool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   CHECK(it != id_to_entry_.end());
-
-  ObjectRegistryEntry& entry = *(it->second);
+  ObjectRegistryEntry& entry = *it->second;
   if (entry.jni_reference_type == JNIWeakGlobalRefType) {
     JNIEnv* env = self->GetJniEnv();
     return env->IsSameObject(entry.jni_reference, NULL);  // Has the jweak been collected?
@@ -185,24 +186,55 @@
 void ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
   Thread* self = Thread::Current();
   MutexLock mu(self, lock_);
-  id_iterator it = id_to_entry_.find(id);
+  auto it = id_to_entry_.find(id);
   if (it == id_to_entry_.end()) {
     return;
   }
-
-  ObjectRegistryEntry& entry = *(it->second);
-  entry.reference_count -= reference_count;
-  if (entry.reference_count <= 0) {
+  ObjectRegistryEntry* entry = it->second;
+  entry->reference_count -= reference_count;
+  if (entry->reference_count <= 0) {
     JNIEnv* env = self->GetJniEnv();
-    mirror::Object* object = self->DecodeJObject(entry.jni_reference);
-    if (entry.jni_reference_type == JNIWeakGlobalRefType) {
-      env->DeleteWeakGlobalRef(entry.jni_reference);
+    mirror::Object* object = self->DecodeJObject(entry->jni_reference);
+    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
+      env->DeleteWeakGlobalRef(entry->jni_reference);
     } else {
-      env->DeleteGlobalRef(entry.jni_reference);
+      env->DeleteGlobalRef(entry->jni_reference);
     }
     object_to_entry_.erase(object);
     id_to_entry_.erase(id);
+    delete entry;
   }
 }
 
+void ObjectRegistry::UpdateObjectPointers(RootVisitor visitor, void* arg) {
+  MutexLock mu(Thread::Current(), lock_);
+  if (object_to_entry_.empty()) {
+    return;
+  }
+  std::map<mirror::Object*, ObjectRegistryEntry*> new_object_to_entry;
+  for (auto& pair : object_to_entry_) {
+    mirror::Object* new_obj;
+    if (pair.first != nullptr) {
+      new_obj = visitor(pair.first, arg);
+      if (new_obj != nullptr) {
+        new_object_to_entry.insert(std::make_pair(new_obj, pair.second));
+      }
+    }
+  }
+  object_to_entry_ = new_object_to_entry;
+}
+
+void ObjectRegistry::AllowNewObjects() {
+  Thread* self = Thread::Current();
+  MutexLock mu(self, lock_);
+  allow_new_objects_ = true;
+  condition_.Broadcast(self);
+}
+
+void ObjectRegistry::DisallowNewObjects() {
+  Thread* self = Thread::Current();
+  MutexLock mu(self, lock_);
+  allow_new_objects_ = false;
+}
+
 }  // namespace art
diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h
index 7f162ca..0190575 100644
--- a/runtime/jdwp/object_registry.h
+++ b/runtime/jdwp/object_registry.h
@@ -26,6 +26,7 @@
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
+#include "root_visitor.h"
 #include "safe_map.h"
 
 namespace art {
@@ -83,6 +84,15 @@
   // Avoid using this and use standard Get when possible.
   jobject GetJObject(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Visit, objects are treated as system weaks.
+  void UpdateObjectPointers(RootVisitor visitor, void* arg)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // We have allow / disallow functionality since we use system weak sweeping logic to update moved
+  // objects inside of the object_to_entry_ map.
+  void AllowNewObjects() LOCKS_EXCLUDED(lock_);
+  void DisallowNewObjects() LOCKS_EXCLUDED(lock_);
+
  private:
   JDWP::ObjectId InternalAdd(mirror::Object* o) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::Object* InternalGet(JDWP::ObjectId id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -90,11 +100,10 @@
   void Promote(ObjectRegistryEntry& entry) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, lock_);
 
   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  bool allow_new_objects_ GUARDED_BY(lock_);
+  ConditionVariable condition_ GUARDED_BY(lock_);
 
-  typedef std::map<mirror::Object*, ObjectRegistryEntry>::iterator object_iterator;
-  std::map<mirror::Object*, ObjectRegistryEntry> object_to_entry_ GUARDED_BY(lock_);
-
-  typedef SafeMap<JDWP::ObjectId, ObjectRegistryEntry*>::iterator id_iterator;
+  std::map<mirror::Object*, ObjectRegistryEntry*> object_to_entry_ GUARDED_BY(lock_);
   SafeMap<JDWP::ObjectId, ObjectRegistryEntry*> id_to_entry_ GUARDED_BY(lock_);
 
   size_t next_id_ GUARDED_BY(lock_);
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index dceea5c..d9baaaf 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -233,14 +233,19 @@
 static jlong VMDebug_countInstancesOfClass(JNIEnv* env, jclass, jclass javaClass,
                                            jboolean countAssignable) {
   ScopedObjectAccess soa(env);
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  // 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. Need to do GC before decoding
+  // any jobjects.
+  heap->CollectGarbage(false);
   mirror::Class* c = soa.Decode<mirror::Class*>(javaClass);
-  if (c == NULL) {
+  if (c == nullptr) {
     return 0;
   }
   std::vector<mirror::Class*> classes;
   classes.push_back(c);
   uint64_t count = 0;
-  Runtime::Current()->GetHeap()->CountInstances(classes, countAssignable, &count);
+  heap->CountInstances(classes, countAssignable, &count);
   return count;
 }
 
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 17afb43..09d05d1 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -379,6 +379,7 @@
   GetInternTable()->SweepInternTableWeaks(visitor, arg);
   GetMonitorList()->SweepMonitorList(visitor, arg);
   GetJavaVM()->SweepJniWeakGlobals(visitor, arg);
+  Dbg::UpdateObjectPointers(visitor, arg);
 }
 
 static gc::CollectorType ParseCollectorType(const std::string& option) {
@@ -1495,12 +1496,14 @@
   monitor_list_->DisallowNewMonitors();
   intern_table_->DisallowNewInterns();
   java_vm_->DisallowNewWeakGlobals();
+  Dbg::DisallowNewObjectRegistryObjects();
 }
 
 void Runtime::AllowNewSystemWeaks() {
   monitor_list_->AllowNewMonitors();
   intern_table_->AllowNewInterns();
   java_vm_->AllowNewWeakGlobals();
+  Dbg::AllowNewObjectRegistryObjects();
 }
 
 void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) {