ART: Add guards to the dex cache and its shortcuts

Do not return fields, methods or classes if the (declaring) class is
erroneous.

Bug: 16692788
Change-Id: If43c2414ad0eb22db5eba7cf66396c7f16c26597
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 73de683..0dd1588 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -19,6 +19,8 @@
 
 #include "art_method.h"
 
+#include "art_field.h"
+#include "class.h"
 #include "class_linker.h"
 #include "dex_cache.h"
 #include "dex_file.h"
@@ -87,11 +89,60 @@
       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
 }
 
+inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index) {
+  ArtMethod* method = GetDexCacheResolvedMethods()->Get(method_index);
+  if (method != nullptr && !method->GetDeclaringClass()->IsErroneous()) {
+    return method;
+  } else {
+    return nullptr;
+  }
+}
+
+inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
+  GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
+}
+
+inline bool ArtMethod::HasDexCacheResolvedMethods() {
+  return GetDexCacheResolvedMethods() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
+  return GetDexCacheResolvedMethods() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
+  return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
+}
+
+
 inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
   return GetFieldObject<ObjectArray<Class>>(
       OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_));
 }
 
+template <bool kWithCheck>
+inline Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
+  Class* klass;
+  if (kWithCheck) {
+    klass = GetDexCacheResolvedTypes()->Get(type_index);
+  } else {
+    klass = GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
+  }
+  return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
+}
+
+inline bool ArtMethod::HasDexCacheResolvedTypes() {
+  return GetDexCacheResolvedTypes() != nullptr;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
+  return GetDexCacheResolvedTypes() == other_cache;
+}
+
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
+  return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
+}
+
 inline uint32_t ArtMethod::GetCodeSize() {
   DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
   const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
@@ -396,7 +447,7 @@
 
 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
   mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
+  return method->GetDexCacheResolvedType(type_idx) != nullptr;
 }
 
 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 01e6149..4ebceff 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -216,13 +216,25 @@
     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
   }
 
-  ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasSameDexCacheResolvedMethods(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template <bool kWithCheck = true>
+  Class* GetDexCacheResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasSameDexCacheResolvedTypes(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Find the method that this method overrides
   ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -518,6 +530,10 @@
   static GcRoot<Class> java_lang_reflect_ArtMethod_;
 
  private:
+  ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   friend struct art::ArtMethodOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ArtMethod);
 };
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 2c5fbcd..3c947ab 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -17,7 +17,9 @@
 #ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
 #define ART_RUNTIME_MIRROR_DEX_CACHE_H_
 
+#include "art_field.h"
 #include "art_method.h"
+#include "class.h"
 #include "object.h"
 #include "object_array.h"
 
@@ -30,9 +32,6 @@
 
 namespace mirror {
 
-class ArtField;
-class ArtMethod;
-class Class;
 class String;
 
 // C++ mirror of java.lang.DexCache.
@@ -115,7 +114,12 @@
 
   ArtField* GetResolvedField(uint32_t field_idx) ALWAYS_INLINE
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetResolvedFields()->Get(field_idx);
+    ArtField* field = GetResolvedFields()->Get(field_idx);
+    if (UNLIKELY(field == nullptr || field->GetDeclaringClass()->IsErroneous())) {
+      return nullptr;
+    } else {
+      return field;
+    }
   }
 
   void SetResolvedField(uint32_t field_idx, ArtField* resolved) ALWAYS_INLINE