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
19e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz#include "handle_scope-inl.h"
206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#include "jni_internal.h"
21e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/class.h"
2264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "scoped_thread_state_change.h"
2364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
2464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesnamespace art {
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) {
396650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  return Add(c);
4064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
4164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
426650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::RefTypeId ObjectRegistry::AddRefType(Handle<mirror::Class> c_h) {
436650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  return Add(c_h);
4464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
4564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
466650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) {
47b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  if (o == nullptr) {
4864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    return 0;
4964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
506650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  Thread* const self = Thread::Current();
516650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  StackHandleScope<1> hs(self);
526650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  return InternalAdd(hs.NewHandle(o));
536650075fb831379d24cfafc3d56442e742418688Sebastien Hertz}
546650075fb831379d24cfafc3d56442e742418688Sebastien Hertz
556650075fb831379d24cfafc3d56442e742418688Sebastien Hertz// Template instantiations must be declared below.
566650075fb831379d24cfafc3d56442e742418688Sebastien Hertztemplate<class T>
576650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::ObjectId ObjectRegistry::Add(Handle<T> obj_h) {
586650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  if (obj_h.Get() == nullptr) {
596650075fb831379d24cfafc3d56442e742418688Sebastien Hertz    return 0;
606650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  }
616650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  return InternalAdd(obj_h);
626650075fb831379d24cfafc3d56442e742418688Sebastien Hertz}
636650075fb831379d24cfafc3d56442e742418688Sebastien Hertz
646650075fb831379d24cfafc3d56442e742418688Sebastien Hertz// Explicit template instantiation.
656650075fb831379d24cfafc3d56442e742418688Sebastien Hertztemplate
666650075fb831379d24cfafc3d56442e742418688Sebastien HertzSHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
676650075fb831379d24cfafc3d56442e742418688Sebastien HertzLOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_)
686650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Object> obj_h);
696650075fb831379d24cfafc3d56442e742418688Sebastien Hertz
706650075fb831379d24cfafc3d56442e742418688Sebastien Hertztemplate
716650075fb831379d24cfafc3d56442e742418688Sebastien HertzSHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
726650075fb831379d24cfafc3d56442e742418688Sebastien HertzLOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_)
736650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::ObjectId ObjectRegistry::Add(Handle<mirror::Throwable> obj_h);
746650075fb831379d24cfafc3d56442e742418688Sebastien Hertz
756650075fb831379d24cfafc3d56442e742418688Sebastien Hertztemplate<class T>
766650075fb831379d24cfafc3d56442e742418688Sebastien HertzJDWP::ObjectId ObjectRegistry::InternalAdd(Handle<T> obj_h) {
776650075fb831379d24cfafc3d56442e742418688Sebastien Hertz  CHECK(obj_h.Get() != nullptr);
7864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
79e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz  Thread* const self = Thread::Current();
80e4266c511ffe6a1ed472292bea06881dcbf06f7aSebastien Hertz  self->AssertNoPendingException();
81692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  // Object::IdentityHashCode may cause these locks to be held so check we do not already
82692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  // hold them.
83692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Locks::thread_list_lock_->AssertNotHeld(self);
84692063955ae845d8bd9fa2d22a50a1e06513bdcfSebastien Hertz  Locks::thread_suspend_count_lock_->AssertNotHeld(self);
85e4266c511ffe6a1ed472292bea06881dcbf06f7aSebastien Hertz
86b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  // Call IdentityHashCode here to avoid a lock level violation between lock_ and monitor_lock.
87e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz  int32_t identity_hash_code = obj_h->IdentityHashCode();
88e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz
89e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz  ScopedObjectAccessUnchecked soa(self);
9064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(soa.Self(), lock_);
91b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  ObjectRegistryEntry* entry = nullptr;
92e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz  if (ContainsLocked(soa.Self(), obj_h.Get(), identity_hash_code, &entry)) {
93412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    // This object was already in our map.
94412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    ++entry->reference_count;
95412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  } else {
96412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry = new ObjectRegistryEntry;
97412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference_type = JNIWeakGlobalRefType;
98412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference = nullptr;
99412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->reference_count = 0;
100412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->id = 0;
101b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    entry->identity_hash_code = identity_hash_code;
102b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    object_to_entry_.insert(std::make_pair(identity_hash_code, entry));
10364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
104412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    // This object isn't in the registry yet, so add it.
105412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    JNIEnv* env = soa.Env();
10664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
107e2d628b5b0a1b9c29c173f3cbad3ef6cb6c24d2dSebastien Hertz    jobject local_reference = soa.AddLocalReference<jobject>(obj_h.Get());
10864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
109412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference_type = JNIWeakGlobalRefType;
110412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->jni_reference = env->NewWeakGlobalRef(local_reference);
111412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->reference_count = 1;
112412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    entry->id = next_id_++;
11364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
114412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    id_to_entry_.Put(entry->id, entry);
11564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
116412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    env->DeleteLocalRef(local_reference);
117412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  }
118412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  return entry->id;
11964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
12064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
121b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchibool ObjectRegistry::ContainsLocked(Thread* self, mirror::Object* o, int32_t identity_hash_code,
122b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi                                    ObjectRegistryEntry** out_entry) {
123b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  DCHECK(o != nullptr);
124b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  for (auto it = object_to_entry_.lower_bound(identity_hash_code), end = object_to_entry_.end();
125b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi       it != end && it->first == identity_hash_code; ++it) {
126b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    ObjectRegistryEntry* entry = it->second;
127b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    if (o == self->DecodeJObject(entry->jni_reference)) {
128b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      if (out_entry != nullptr) {
129b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi        *out_entry = entry;
130b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      }
131b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      return true;
132b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    }
133b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  }
134b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi  return false;
13564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
13664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
13764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Clear() {
13855f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  Thread* const self = Thread::Current();
13955f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz
14055f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // We must not hold the mutator lock exclusively if we want to delete weak global
14155f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // references. Otherwise this can lead to a deadlock with a running GC:
14255f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // 1. GC thread disables access to weak global references, then releases
14355f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  //    mutator lock.
14455f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // 2. JDWP thread takes mutator lock exclusively after suspending all
14555f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  //    threads.
14655f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // 3. GC thread waits for shared mutator lock which is held by JDWP
14755f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  //    thread.
14855f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  // 4. JDWP thread clears weak global references but need to wait for GC
14955f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  //    thread to re-enable access to them.
15055f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz  Locks::mutator_lock_->AssertNotExclusiveHeld(self);
15155f6534f260ec82ef2d69a0667b1883f13d11399Sebastien Hertz
15264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
15364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries";
15464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  // Delete all the JNI references.
15564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  JNIEnv* env = self->GetJniEnv();
156412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  for (const auto& pair : object_to_entry_) {
157a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    const ObjectRegistryEntry* entry = pair.second;
158a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
159a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz      env->DeleteWeakGlobalRef(entry->jni_reference);
16064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    } else {
161a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz      env->DeleteGlobalRef(entry->jni_reference);
16264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    }
163a032870e19e4a6c8d62b7dab806261006fa711eeSebastien Hertz    delete entry;
16464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
16564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  // Clear the maps.
16664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  object_to_entry_.clear();
16764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  id_to_entry_.clear();
16864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
16964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
170c0542af3e2170143ba40d89136e284997e16bf64Ian Rogersmirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error) {
17164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
17264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
173412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
17464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (it == id_to_entry_.end()) {
175c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    *error = JDWP::ERR_INVALID_OBJECT;
176c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers    return nullptr;
17764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
178412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
179c0542af3e2170143ba40d89136e284997e16bf64Ian Rogers  *error = JDWP::ERR_NONE;
18064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  return self->DecodeJObject(entry.jni_reference);
18164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
18264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
183449db33fafa29578df60e8a323f78d5eb6247e76Jeff Haojobject ObjectRegistry::GetJObject(JDWP::ObjectId id) {
1840630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz  if (id == 0) {
1857d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    return nullptr;
1860630ab5239a7d7be24dedbc3f66c822332446fc3Sebastien Hertz  }
187449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  Thread* self = Thread::Current();
188449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  MutexLock mu(self, lock_);
189412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
190449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  CHECK(it != id_to_entry_.end()) << id;
191412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
192449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao  return entry.jni_reference;
193449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao}
194449db33fafa29578df60e8a323f78d5eb6247e76Jeff Hao
19564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisableCollection(JDWP::ObjectId id) {
19664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
19764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
198412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
199e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
200412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  Promote(*it->second);
20164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
20264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
20364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::EnableCollection(JDWP::ObjectId id) {
20464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
20564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
206412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
207e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
208412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  Demote(*it->second);
20964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
21064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
21164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Demote(ObjectRegistryEntry& entry) {
21264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIGlobalRefType) {
21364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    Thread* self = Thread::Current();
21464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
21564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    jobject global = entry.jni_reference;
21664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference);
21764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference_type = JNIWeakGlobalRefType;
21864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    env->DeleteGlobalRef(global);
21964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
22064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
22164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
22264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Promote(ObjectRegistryEntry& entry) {
22364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
22464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    Thread* self = Thread::Current();
22564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
22664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    jobject weak = entry.jni_reference;
22764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference = env->NewGlobalRef(entry.jni_reference);
22864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    entry.jni_reference_type = JNIGlobalRefType;
22964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    env->DeleteWeakGlobalRef(weak);
23064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
23164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
23264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
23364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesbool ObjectRegistry::IsCollected(JDWP::ObjectId id) {
23464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
23564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
236412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
237e96060aa2483529d087031f7cdcc0405f1ef9218Sebastien Hertz  CHECK(it != id_to_entry_.end());
238412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry& entry = *it->second;
23964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (entry.jni_reference_type == JNIWeakGlobalRefType) {
24064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
2417d95565c84d91ae5dcec4b89728ada208633de0cSebastien Hertz    return env->IsSameObject(entry.jni_reference, nullptr);  // Has the jweak been collected?
24264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  } else {
2437934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    return false;  // We hold a strong reference, so we know this is live.
24464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
24564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
24664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
24764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) {
24864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  Thread* self = Thread::Current();
24964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  MutexLock mu(self, lock_);
250412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  auto it = id_to_entry_.find(id);
25164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  if (it == id_to_entry_.end()) {
25264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    return;
25364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
254412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  ObjectRegistryEntry* entry = it->second;
255412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  entry->reference_count -= reference_count;
256412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier  if (entry->reference_count <= 0) {
25764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    JNIEnv* env = self->GetJniEnv();
258b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    // Erase the object from the maps. Note object may be null if it's
259b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    // a weak ref and the GC has cleared it.
260b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    int32_t hash_code = entry->identity_hash_code;
261277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe    for (auto inner_it = object_to_entry_.lower_bound(hash_code), end = object_to_entry_.end();
262277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe         inner_it != end && inner_it->first == hash_code; ++inner_it) {
263277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe      if (entry == inner_it->second) {
264277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe        object_to_entry_.erase(inner_it);
265b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi        break;
266b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi      }
267b5a9e3d1cc1fd66683e43e365afc8c900e2800c4Hiroshi Yamauchi    }
268412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    if (entry->jni_reference_type == JNIWeakGlobalRefType) {
269412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier      env->DeleteWeakGlobalRef(entry->jni_reference);
27064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    } else {
271412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier      env->DeleteGlobalRef(entry->jni_reference);
27264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    }
27364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes    id_to_entry_.erase(id);
274412c7fced915fc8d4d5e4166e977d55c809168a6Mathieu Chartier    delete entry;
27564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes  }
27664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}
27764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes
27864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes}  // namespace art
279