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;