object_registry.cc revision e63db27db913f1a88e2095a1ee8239b2bb9124e8
164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes/*
264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * Copyright (C) 2013 The Android Open Source Project
364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes *
464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * you may not use this file except in compliance with the License.
664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * You may obtain a copy of the License at
764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes *
864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes *
1064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * See the License for the specific language governing permissions and
1464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes * limitations under the License.
1564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes */
1664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
1764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "object_registry.h"
1864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
19e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/class.h"
2064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "scoped_thread_state_change.h"
2164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
2264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesnamespace art {
2364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
2464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesmirror::Object* const ObjectRegistry::kInvalidObject = reinterpret_cast<mirror::Object*>(1);
2564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
2664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesstd::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) {
2764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  os << "ObjectRegistryEntry[" << rhs.jni_reference_type
2864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes     << ",reference=" << rhs.jni_reference
2964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes     << ",count=" << rhs.reference_count
3064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes     << ",id=" << rhs.id << "]";
3164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return os;
3264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
3364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
340f827169742aad6209d830db773a101849c32a83Elliott HughesObjectRegistry::ObjectRegistry()
35b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    : lock_("ObjectRegistry lock", kJdwpObjectRegistryLock), next_id_(1) {
3664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
3764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
3864f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) {
3964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return InternalAdd(c);
4064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
4164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
4264f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) {
4364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return InternalAdd(o);
4464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
4564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
4664f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::ObjectId ObjectRegistry::InternalAdd(mirror::Object* o) {
47b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  if (o == nullptr) {
4864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    return 0;
4964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
5064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
51b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
52b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  int32_t identity_hash_code = o->IdentityHashCode();
5364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  ScopedObjectAccessUnchecked soa(Thread::Current());
5464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(soa.Self(), lock_);
55b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  ObjectRegistryEntry* entry = nullptr;
56b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  if (ContainsLocked(soa.Self(), o, identity_hash_code, &entry)) {
57412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    // This object was already in our map.
58412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    ++entry->reference_count;
59412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  } else {
60412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry = new ObjectRegistryEntry;
61412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference_type = JNIWeakGlobalRefType;
62412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference = nullptr;
63412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->reference_count = 0;
64412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->id = 0;
65b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    entry->identity_hash_code = identity_hash_code;
66b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    object_to_entry_.insert(std::make_pair(identity_hash_code, entry));
6764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
68412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    // This object isn't in the registry yet, so add it.
69412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    JNIEnv* env = soa.Env();
7064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
71412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    jobject local_reference = soa.AddLocalReference<jobject>(o);
7264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
73412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference_type = JNIWeakGlobalRefType;
74412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference = env->NewWeakGlobalRef(local_reference);
75412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->reference_count = 1;
76412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->id = next_id_++;
7764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
78412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    id_to_entry_.Put(entry->id, entry);
7964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
80412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    env->DeleteLocalRef(local_reference);
81412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  }
82412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  return entry->id;
8364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
8464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
85b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchibool ObjectRegistry::Contains(mirror::Object* o, ObjectRegistryEntry** out_entry) {
86b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  if (o == nullptr) {
87b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    return false;
88b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  }
89b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
90b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  int32_t identity_hash_code = o->IdentityHashCode();
91b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  Thread* self = Thread::Current();
92b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  MutexLock mu(self, lock_);
93b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  return ContainsLocked(self, o, identity_hash_code, out_entry);
94b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi}
95b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi
96b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchibool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code,
97b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi                                    ObjectRegistryEntry** out_entry) {
98b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  DCHECK(o != nullptr);
99b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end();
100b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi       it != end && it->first == identity_hash_code; ++it) {
101b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    ObjectRegistryEntry* entry = it->second;
102b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    if (o == self->DecodeJObject(entry->jni_reference)) {
103b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      if (out_entry != nullptr) {
104b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi        *out_entry = entry;
105b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      }
106b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      return true;
107b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    }
108b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  }
109b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  return false;
11064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
11164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
11264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Clear() {
11364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
11464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
11564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
11664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  // Delete all the JNI references.
11764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  JNIEnv* env = self->GetJniEnv();
118412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  for (const auto& pair : object_to_entry_) {
119a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    const ObjectRegistryEntry* entry = pair.second;
120a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
121a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz      env->DeleteWeakGlobalRef(entry->jni_reference);
12264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    } else {
123a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz      env->DeleteGlobalRef(entry->jni_reference);
12464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    }
125a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    delete entry;
12664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
12764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  // Clear the maps.
12864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  object_to_entry_.clear();
12964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  id_to_entry_.clear();
13064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
13164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
13264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesmirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) {
13364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
13464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
135412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
13664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (it == id_to_entry_.end()) {
13764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    return kInvalidObject;
13864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
139412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
14064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return self->DecodeJObject(entry.jni_reference);
14164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
14264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
143449db33fafa29578df60e8a323f78d5eb6247e76Jeff Haojobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
1440630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz  if (id == 0) {
1450630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz    return NULL;
1460630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz  }
147449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  Thread* self = Thread::Current();
148449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  MutexLock mu(self, lock_);
149412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
150449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  CHECK(it != id_to_entry_.end()) << id;
151412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
152449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  return entry.jni_reference;
153449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao}
154449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
15564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
15664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
15764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
158412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
159e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
160412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  Promote(*it->second);
16164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
16264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
16364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
16464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
16564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
166412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
167e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
168412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  Demote(*it->second);
16964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
17064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
17164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
17264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIGlobalRefType) {
17364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    Thread* self = Thread::Current();
17464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
17564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    jobject global = entry.jni_reference;
17664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference);
17764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference_type = JNIWeakGlobalRefType;
17864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    env->DeleteGlobalRef(global);
17964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
18064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
18164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
18264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Promote(ObjectRegistryEntry& entry) {
18364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
18464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    Thread* self = Thread::Current();
18564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
18664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    jobject weak = entry.jni_reference;
18764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference = env->NewGlobalRef(entry.jni_reference);
18864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference_type = JNIGlobalRefType;
18964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    env->DeleteWeakGlobalRef(weak);
19064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
19164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
19264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
19364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesbool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
19464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
19564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
196412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
197e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
198412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
19964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
20064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
2017934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return env->IsSameObject(entry.jni_reference, NULL);  // Has the jweak been collected?
20264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  } else {
2037934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return false;  // We hold a strong reference, so we know this is live.
20464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
20564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
20664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
20764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
20864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
20964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
210412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
21164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (it == id_to_entry_.end()) {
21264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    return;
21364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
214412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry* entry = it->second;
215412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  entry->reference_count -= reference_count;
216412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  if (entry->reference_count <= 0) {
21764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
218b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    // Erase the object from the maps. Note object may be null if it's
219b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    // a weak ref and the GC has cleared it.
220b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    int32_t hash_code = entry->identity_hash_code;
221b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    for (auto it = object_to_entry_.lower_bound(hash_code), end = object_to_entry_.end();
222b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi         it != end && it->first == hash_code; ++it) {
223b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      if (entry == it->second) {
224b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi        object_to_entry_.erase(it);
225b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi        break;
226b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      }
227b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    }
228412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
229412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier      env->DeleteWeakGlobalRef(entry->jni_reference);
23064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    } else {
231412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier      env->DeleteGlobalRef(entry->jni_reference);
23264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    }
23364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    id_to_entry_.erase(id);
234412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    delete entry;
23564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
23664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
23764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
23864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}  // namespace art
239