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