Avoid using dex cache array pointers in libart.

In preparation for making dex cache arrays native, avoid
using them in Java code.

This causes a performance regression for our reflection
benchmarks. Class_getDeclaredMethod and Class_getMethod
take an up to 30% hit, measured using the Quick compiler.
We accept this hit at this stage and we will tune the
performance after we're done with the larger effort.

Companion libcore/ change:
    https://android-review.googlesource.com/146069

Bug: 20134538
Change-Id: Ibbef3b50043a1311cd40723ed42e1f1c609b8fc1
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 0ccf5db..fb427dc 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -36,7 +36,7 @@
 namespace mirror {
 
 inline uint32_t ArtMethod::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 8;
+  uint32_t vtable_entries = Object::kVTableLength + 7;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
 }
 
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 22481ce..55b8068 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -183,6 +183,10 @@
     SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), new_method_index);
   }
 
+  static MemberOffset DexMethodIndexOffset() {
+    return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_);
+  }
+
   static MemberOffset MethodIndexOffset() {
     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
   }
@@ -214,6 +218,8 @@
     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
   }
 
+  ALWAYS_INLINE ObjectArray<ArtMethod>* GetDexCacheResolvedMethods()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method)
@@ -434,10 +440,6 @@
         EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
   }
 
-  static MemberOffset GetMethodIndexOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
-  }
-
   // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
   // conventions for a method of managed code. Returns false for Proxy methods.
   bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -604,9 +606,6 @@
  private:
   ALWAYS_INLINE void CheckObjectSizeEqualsMirrorSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetDexCacheResolvedMethods()
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   ALWAYS_INLINE ObjectArray<Class>* GetDexCacheResolvedTypes()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 288e88e..6758e22 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -27,7 +27,7 @@
 namespace mirror {
 
 inline uint32_t DexCache::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 1;
+  uint32_t vtable_entries = Object::kVTableLength + 5;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
 }
 
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index c893f0a..b657aec 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -91,6 +91,18 @@
   return soa.AddLocalReference<jclass>(c.Get());
 }
 
+static jobject Class_findOverriddenMethodIfProxy(JNIEnv* env, jclass, jobject art_method) {
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method);
+  mirror::Class* declaring_klass = method->GetDeclaringClass();
+  if (!declaring_klass->IsProxyClass()) {
+    return art_method;
+  }
+  uint32_t dex_method_index = method->GetDexMethodIndex();
+  mirror::ArtMethod* overriden_method = method->GetDexCacheResolvedMethods()->Get(dex_method_index);
+  return soa.AddLocalReference<jobject>(overriden_method);
+}
+
 static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
   StackHandleScope<1> hs(soa.Self());
@@ -264,6 +276,8 @@
 
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, findOverriddenMethodIfProxy,
+                "!(Ljava/lang/reflect/ArtMethod;)Ljava/lang/reflect/ArtMethod;"),
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
index 27eae46..8944270 100644
--- a/runtime/native/java_lang_DexCache.cc
+++ b/runtime/native/java_lang_DexCache.cc
@@ -48,8 +48,38 @@
                                       args);
 }
 
+static jobject DexCache_getResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index) {
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  return soa.AddLocalReference<jobject>(dex_cache->GetResolvedType(type_index));
+}
+
+static jobject DexCache_getResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index) {
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  return soa.AddLocalReference<jobject>(dex_cache->GetResolvedString(string_index));
+}
+
+static void DexCache_setResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index,
+                                     jobject type) {
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class*>(type));
+}
+
+static void DexCache_setResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index,
+                                       jobject string) {
+  ScopedFastNativeObjectAccess soa(env);
+  mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache);
+  dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String*>(string));
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(DexCache, getDexNative, "!()Lcom/android/dex/Dex;"),
+  NATIVE_METHOD(DexCache, getResolvedType, "!(I)Ljava/lang/Class;"),
+  NATIVE_METHOD(DexCache, getResolvedString, "!(I)Ljava/lang/String;"),
+  NATIVE_METHOD(DexCache, setResolvedType, "!(ILjava/lang/Class;)V"),
+  NATIVE_METHOD(DexCache, setResolvedString, "!(ILjava/lang/String;)V"),
 };
 
 void register_java_lang_DexCache(JNIEnv* env) {