Clean up class resolution and lookup.
Simplify the code and avoid read barriers when appropriate.
Relax class status check in ArtField::GetDeclaringClass()
because we can see ClassStatus::kIdx from the from-space
class object for kReadBarrierOption=kWithoutReadBarrier.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: I83886a64fe5a99a1c3c30eab3b35dae449e6b4bc
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 384581f..baa5102 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -34,12 +34,16 @@
namespace art {
+inline bool ArtField::IsProxyField() {
+ return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass<kVerifyNone>();
+}
+
template<ReadBarrierOption kReadBarrierOption>
inline ObjPtr<mirror::Class> ArtField::GetDeclaringClass() {
GcRootSource gc_root_source(this);
ObjPtr<mirror::Class> result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
DCHECK(result != nullptr);
- DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus();
+ DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << result->GetStatus();
return result;
}
@@ -302,25 +306,21 @@
inline ObjPtr<mirror::Class> ArtField::LookupResolvedType() {
ScopedAssertNoThreadSuspension ants(__FUNCTION__);
- const uint32_t field_index = GetDexFieldIndex();
- ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
- if (UNLIKELY(declaring_class->IsProxyClass())) {
+ if (UNLIKELY(IsProxyField())) {
return ProxyFindSystemClass(GetTypeDescriptor());
}
ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->LookupResolvedType(
- declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class);
+ GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this);
DCHECK(!Thread::Current()->IsExceptionPending());
return type;
}
inline ObjPtr<mirror::Class> ArtField::ResolveType() {
- const uint32_t field_index = GetDexFieldIndex();
- ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
- if (UNLIKELY(declaring_class->IsProxyClass())) {
+ if (UNLIKELY(IsProxyField())) {
return ProxyFindSystemClass(GetTypeDescriptor());
}
ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType(
- declaring_class->GetDexFile().GetFieldId(field_index).type_idx_, declaring_class);
+ GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this);
DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending());
return type;
}
@@ -329,12 +329,14 @@
return Primitive::ComponentSize(GetTypeAsPrimitiveType());
}
+template <ReadBarrierOption kReadBarrierOption>
inline ObjPtr<mirror::DexCache> ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetDeclaringClass()->GetDexCache();
+ ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
+ return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
}
inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_) {
- return GetDexCache()->GetDexFile();
+ return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
}
inline ObjPtr<mirror::String> ArtField::GetStringName(Thread* self, bool resolve) {
diff --git a/runtime/art_field.h b/runtime/art_field.h
index f39af39..784a862 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -215,6 +215,7 @@
size_t FieldSize() REQUIRES_SHARED(Locks::mutator_lock_);
+ template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ObjPtr<mirror::DexCache> GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_);
const DexFile* GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -236,6 +237,8 @@
REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ bool IsProxyField() REQUIRES_SHARED(Locks::mutator_lock_);
+
ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::String> ResolveGetStringName(Thread* self,
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index c1fac36..ec66966 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -324,7 +324,7 @@
template <ReadBarrierOption kReadBarrierOption>
inline mirror::DexCache* ArtMethod::GetDexCache() {
if (LIKELY(!IsObsolete<kReadBarrierOption>())) {
- mirror::Class* klass = GetDeclaringClass<kReadBarrierOption>();
+ ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>();
return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>();
} else {
DCHECK(!IsProxyMethod());
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 25eb85d..888f713 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -17,7 +17,10 @@
#ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
#define ART_RUNTIME_CLASS_LINKER_INL_H_
-#include "art_field.h"
+#include <atomic>
+
+#include "art_field-inl.h"
+#include "art_method-inl.h"
#include "class_linker.h"
#include "gc/heap-inl.h"
#include "gc_root-inl.h"
@@ -29,8 +32,6 @@
#include "obj_ptr-inl.h"
#include "scoped_thread_state_change-inl.h"
-#include <atomic>
-
namespace art {
inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
@@ -68,18 +69,27 @@
HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
Thread::Current()->PoisonObjectPointers();
}
- if (kIsDebugBuild) {
- Thread::Current()->AssertNoPendingException();
- }
+ DCHECK(!Thread::Current()->IsExceptionPending());
// We do not need the read barrier for getting the DexCache for the initial resolved type
// lookup as both from-space and to-space copies point to the same native resolved types array.
ObjPtr<mirror::Class> resolved_type =
referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (resolved_type == nullptr) {
- StackHandleScope<2> hs(Thread::Current());
- Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
- resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader);
+ resolved_type = DoResolveType(type_idx, referrer);
+ }
+ return resolved_type;
+}
+
+inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
+ ArtField* referrer) {
+ Thread::PoisonObjectPointersIfDebug();
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::Class> resolved_type =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
+ if (UNLIKELY(resolved_type == nullptr)) {
+ resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
}
return resolved_type;
}
@@ -87,19 +97,13 @@
inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
ArtMethod* referrer) {
Thread::PoisonObjectPointersIfDebug();
- if (kIsDebugBuild) {
- Thread::Current()->AssertNoPendingException();
- }
+ DCHECK(!Thread::Current()->IsExceptionPending());
// We do not need the read barrier for getting the DexCache for the initial resolved type
// lookup as both from-space and to-space copies point to the same native resolved types array.
ObjPtr<mirror::Class> resolved_type =
referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (UNLIKELY(resolved_type == nullptr)) {
- StackHandleScope<2> hs(Thread::Current());
- ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
- resolved_type = DoResolveType(type_idx, dex_cache, class_loader);
+ resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
}
return resolved_type;
}
@@ -123,7 +127,19 @@
ObjPtr<mirror::Class> type =
referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (type == nullptr) {
- type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+ type = DoLookupResolvedType(type_idx, referrer);
+ }
+ return type;
+}
+
+inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
+ ArtField* referrer) {
+ // We do not need the read barrier for getting the DexCache for the initial resolved type
+ // lookup as both from-space and to-space copies point to the same native resolved types array.
+ ObjPtr<mirror::Class> type =
+ referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
+ if (type == nullptr) {
+ type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
}
return type;
}
@@ -135,7 +151,7 @@
ObjPtr<mirror::Class> type =
referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
if (type == nullptr) {
- type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+ type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
}
return type;
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e46b980..dccdff0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7701,6 +7701,11 @@
}
ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ return DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoLookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader) {
const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -7729,6 +7734,14 @@
}
ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer) {
+ StackHandleScope<2> hs(Thread::Current());
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
+ return DoResolveType(type_idx, dex_cache, class_loader);
+}
+
+ObjPtr<mirror::Class> ClassLinker::DoResolveType(dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader) {
Thread* self = Thread::Current();
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index b38f01d..32016fa 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -67,6 +67,8 @@
using MethodDexCacheType = std::atomic<MethodDexCachePair>;
} // namespace mirror
+class ArtField;
+class ArtMethod;
class ClassHierarchyAnalysis;
enum class ClassRoot : uint32_t;
class ClassTable;
@@ -219,10 +221,9 @@
ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ObjPtr<mirror::Class> referrer)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
-
- // Resolve a type with the given index from the DexFile associated with the given `referrer`,
- // storing the result in the DexCache. The `referrer` is used to identify the target DexCache
- // and ClassLoader to use for resolution.
+ ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
ObjPtr<mirror::Class> ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
@@ -242,10 +243,8 @@
ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::Class> referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Look up a resolved type with the given index from the DexFile associated with the given
- // `referrer`, storing the result in the DexCache. The `referrer` is used to identify the
- // target DexCache and ClassLoader to use for lookup.
+ ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtField* referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<mirror::Class> LookupResolvedType(dex::TypeIndex type_idx, ArtMethod* referrer)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -878,12 +877,19 @@
// Implementation of LookupResolvedType() called when the type was not found in the dex cache.
ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ ObjPtr<mirror::Class> DoLookupResolvedType(dex::TypeIndex type_idx,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
// Implementation of ResolveType() called when the type was not found in the dex cache.
ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
+ ObjPtr<mirror::Class> referrer)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
+ ObjPtr<mirror::Class> DoResolveType(dex::TypeIndex type_idx,
Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_)
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 56658c3..90e89cf 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -958,12 +958,9 @@
return true;
}
case EncodedArrayValueIterator::ValueType::kType: {
- StackHandleScope<2> hs(self);
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
dex::TypeIndex index(static_cast<uint32_t>(encoded_value->GetI()));
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- ObjPtr<mirror::Class> o = cl->ResolveType(index, dex_cache, class_loader);
+ ObjPtr<mirror::Class> o = cl->ResolveType(index, referrer);
if (UNLIKELY(o.IsNull())) {
DCHECK(self->IsExceptionPending());
return false;