object_registry.cc revision 64f574f474aa77c72778640ab21f8cfa72546812
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 1964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes#include "scoped_thread_state_change.h" 2064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 2164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesnamespace art { 2264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 2364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesmirror::Object* const ObjectRegistry::kInvalidObject = reinterpret_cast<mirror::Object*>(1); 2464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 2564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesstd::ostream& operator<<(std::ostream& os, const ObjectRegistryEntry& rhs) { 2664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes os << "ObjectRegistryEntry[" << rhs.jni_reference_type 2764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes << ",reference=" << rhs.jni_reference 2864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes << ",count=" << rhs.reference_count 2964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes << ",id=" << rhs.id << "]"; 3064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return os; 3164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 3264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 3364f574f474aa77c72778640ab21f8cfa72546812Elliott HughesObjectRegistry::ObjectRegistry() : lock_("ObjectRegistry lock"), next_id_(1) { 3464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 3564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 3664f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::RefTypeId ObjectRegistry::AddRefType(mirror::Class* c) { 3764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return InternalAdd(c); 3864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 3964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 4064f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::ObjectId ObjectRegistry::Add(mirror::Object* o) { 4164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return InternalAdd(o); 4264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 4364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 4464f574f474aa77c72778640ab21f8cfa72546812Elliott HughesJDWP::ObjectId ObjectRegistry::InternalAdd(mirror::Object* o) { 4564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (o == NULL) { 4664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return 0; 4764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 4864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 4964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ScopedObjectAccessUnchecked soa(Thread::Current()); 5064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(soa.Self(), lock_); 5164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry dummy; 5264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes std::pair<object_iterator, bool> result = object_to_entry_.insert(std::make_pair(o, dummy)); 5364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry& entry = result.first->second; 5464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (!result.second) { 5564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // This object was already in our map. 5664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.reference_count += 1; 5764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return entry.id; 5864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 5964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 6064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // This object isn't in the registry yet, so add it. 6164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = soa.Env(); 6264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 6364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes jobject local_reference = soa.AddLocalReference<jobject>(o); 6464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 6564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference_type = JNIWeakGlobalRefType; 6664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference = env->NewWeakGlobalRef(local_reference); 6764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.reference_count = 1; 6864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.id = next_id_++; 6964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 7064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_to_entry_.Put(entry.id, &entry); 7164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 7264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteLocalRef(local_reference); 7364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 7464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return entry.id; 7564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 7664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 7764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesbool ObjectRegistry::Contains(mirror::Object* o) { 7864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 7964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 8064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return (object_to_entry_.find(o) != object_to_entry_.end()); 8164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 8264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 8364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Clear() { 8464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 8564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 8664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes VLOG(jdwp) << "Object registry contained " << object_to_entry_.size() << " entries"; 8764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 8864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // Delete all the JNI references. 8964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = self->GetJniEnv(); 9064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes for (object_iterator it = object_to_entry_.begin(); it != object_to_entry_.end(); ++it) { 9164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry& entry = (it->second); 9264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.jni_reference_type == JNIWeakGlobalRefType) { 9364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteWeakGlobalRef(entry.jni_reference); 9464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } else { 9564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteGlobalRef(entry.jni_reference); 9664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 9764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 9864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 9964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes // Clear the maps. 10064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes object_to_entry_.clear(); 10164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_to_entry_.clear(); 10264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 10364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 10464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesmirror::Object* ObjectRegistry::InternalGet(JDWP::ObjectId id) { 10564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 10664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 10764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_iterator it = id_to_entry_.find(id); 10864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (it == id_to_entry_.end()) { 10964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return kInvalidObject; 11064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 11164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry& entry = *(it->second); 11264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return self->DecodeJObject(entry.jni_reference); 11364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 11464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 11564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisableCollection(JDWP::ObjectId id) { 11664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 11764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 11864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_iterator it = id_to_entry_.find(id); 11964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (it == id_to_entry_.end()) { 12064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return; 12164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 12264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Promote(*(it->second)); 12364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 12464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 12564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::EnableCollection(JDWP::ObjectId id) { 12664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 12764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 12864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_iterator it = id_to_entry_.find(id); 12964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (it == id_to_entry_.end()) { 13064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return; 13164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 13264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Demote(*(it->second)); 13364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 13464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 13564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Demote(ObjectRegistryEntry& entry) { 13664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.jni_reference_type == JNIGlobalRefType) { 13764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 13864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = self->GetJniEnv(); 13964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes jobject global = entry.jni_reference; 14064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference = env->NewWeakGlobalRef(entry.jni_reference); 14164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference_type = JNIWeakGlobalRefType; 14264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteGlobalRef(global); 14364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 14464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 14564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 14664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::Promote(ObjectRegistryEntry& entry) { 14764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.jni_reference_type == JNIWeakGlobalRefType) { 14864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 14964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = self->GetJniEnv(); 15064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes jobject weak = entry.jni_reference; 15164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference = env->NewGlobalRef(entry.jni_reference); 15264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.jni_reference_type = JNIGlobalRefType; 15364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteWeakGlobalRef(weak); 15464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 15564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 15664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 15764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesbool ObjectRegistry::IsCollected(JDWP::ObjectId id) { 15864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 15964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 16064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_iterator it = id_to_entry_.find(id); 16164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (it == id_to_entry_.end()) { 16264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return true; // TODO: can we report that this was an invalid id? 16364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 16464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 16564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry& entry = *(it->second); 16664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.jni_reference_type == JNIWeakGlobalRefType) { 16764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = self->GetJniEnv(); 16864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return env->IsSameObject(entry.jni_reference, NULL); // Has the jweak been collected? 16964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } else { 17064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return false; // We hold a strong reference, so we know this is live. 17164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 17264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 17364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 17464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughesvoid ObjectRegistry::DisposeObject(JDWP::ObjectId id, uint32_t reference_count) { 17564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes Thread* self = Thread::Current(); 17664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes MutexLock mu(self, lock_); 17764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_iterator it = id_to_entry_.find(id); 17864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (it == id_to_entry_.end()) { 17964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes return; 18064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 18164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 18264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes ObjectRegistryEntry& entry = *(it->second); 18364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes entry.reference_count -= reference_count; 18464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.reference_count <= 0) { 18564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes JNIEnv* env = self->GetJniEnv(); 18664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes mirror::Object* object = self->DecodeJObject(entry.jni_reference); 18764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes if (entry.jni_reference_type == JNIWeakGlobalRefType) { 18864f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteWeakGlobalRef(entry.jni_reference); 18964f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } else { 19064f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes env->DeleteGlobalRef(entry.jni_reference); 19164f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 19264f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes object_to_entry_.erase(object); 19364f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes id_to_entry_.erase(id); 19464f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes } 19564f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} 19664f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes 19764f574f474aa77c72778640ab21f8cfa72546812Elliott Hughes} // namespace art 198