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