ART: Get rid of most of java.lang.DexCache.

All remaining functionality is moved over to native. The DexCache
object itself is allocated in the Java heap, even though there's no
longer much of a reason to do so. It can be changed in a future change
if needed.

This also renames mirror::Class:GetInterfaces to GetProxyInterfaces
since it's supposed to be called only for proxies.

Test: test-art-host, cts -m CtsLibcoreTestCases

Change-Id: Ie261f22a9f80c929f01d2b456f170c7a464ba21c
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index aa73456..aefdb54 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -976,9 +976,6 @@
         dex_cache->ClearResolvedField(pair.index, target_ptr_size_);
       }
     }
-    // Clean the dex field. It might have been populated during the initialization phase, but
-    // contains data only valid during a real run.
-    dex_cache->SetFieldObject<false>(mirror::DexCache::DexOffset(), nullptr);
   }
 
   // Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
diff --git a/runtime/Android.bp b/runtime/Android.bp
index d075c58..6c3bc04 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -149,7 +149,6 @@
         "native/dalvik_system_VMStack.cc",
         "native/dalvik_system_ZygoteHooks.cc",
         "native/java_lang_Class.cc",
-        "native/java_lang_DexCache.cc",
         "native/java_lang_Object.cc",
         "native/java_lang_String.cc",
         "native/java_lang_StringFactory.cc",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index eb7d7bd..746cace 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4409,9 +4409,9 @@
                                                decoded_name->ToModifiedUtf8().c_str()));
     CHECK_EQ(ArtField::PrettyField(klass->GetStaticField(1)), throws_field_name);
 
-    CHECK_EQ(klass.Get()->GetInterfaces(),
+    CHECK_EQ(klass.Get()->GetProxyInterfaces(),
              soa.Decode<mirror::ObjectArray<mirror::Class>>(interfaces));
-    CHECK_EQ(klass.Get()->GetThrows(),
+    CHECK_EQ(klass.Get()->GetProxyThrows(),
              soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>>(throws));
   }
   return klass.Get();
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index e5722a1..9f04e59 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -668,7 +668,6 @@
 
 struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> {
   DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") {
-    addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_resolved_call_sites_), "numResolvedCallSites");
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 6301362..9c453ec 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -138,7 +138,7 @@
             reinterpret_cast<uintptr_t>(&virtual_methods.At(0))) / method_size;
         CHECK_LT(throws_index, static_cast<int>(num_virtuals));
         mirror::ObjectArray<mirror::Class>* declared_exceptions =
-            proxy_class->GetThrows()->Get(throws_index);
+            proxy_class->GetProxyThrows()->Get(throws_index);
         mirror::Class* exception_class = exception->GetClass();
         for (int32_t i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
           mirror::Class* declared_exception = declared_exceptions->Get(i);
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index eb0a9d1..420fa85 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1131,53 +1131,6 @@
   result->SetJ(bit_cast<int64_t, double>(in));
 }
 
-static ObjPtr<mirror::Object> GetDexFromDexCache(Thread* self, mirror::DexCache* dex_cache)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  if (dex_file == nullptr) {
-    return nullptr;
-  }
-
-  // Create the direct byte buffer.
-  JNIEnv* env = self->GetJniEnv();
-  DCHECK(env != nullptr);
-  void* address = const_cast<void*>(reinterpret_cast<const void*>(dex_file->Begin()));
-  ScopedLocalRef<jobject> byte_buffer(env, env->NewDirectByteBuffer(address, dex_file->Size()));
-  if (byte_buffer.get() == nullptr) {
-    DCHECK(self->IsExceptionPending());
-    return nullptr;
-  }
-
-  jvalue args[1];
-  args[0].l = byte_buffer.get();
-
-  ScopedLocalRef<jobject> dex(env, env->CallStaticObjectMethodA(
-      WellKnownClasses::com_android_dex_Dex,
-      WellKnownClasses::com_android_dex_Dex_create,
-      args));
-
-  return self->DecodeJObject(dex.get());
-}
-
-void UnstartedRuntime::UnstartedDexCacheGetDexNative(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  // We will create the Dex object, but the image writer will release it before creating the
-  // art file.
-  mirror::Object* src = shadow_frame->GetVRegReference(arg_offset);
-  bool have_dex = false;
-  if (src != nullptr) {
-    ObjPtr<mirror::Object> dex = GetDexFromDexCache(self, src->AsDexCache());
-    if (dex != nullptr) {
-      have_dex = true;
-      result->SetL(dex);
-    }
-  }
-  if (!have_dex) {
-    self->ClearException();
-    Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Could not create Dex object");
-  }
-}
-
 static void UnstartedMemoryPeek(
     Primitive::Type type, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   int64_t address = shadow_frame->GetVRegLong(arg_offset);
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 2560a92..4791035 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -52,7 +52,6 @@
   V(MathPow, "double java.lang.Math.pow(double, double)") \
   V(ObjectHashCode, "int java.lang.Object.hashCode()") \
   V(DoubleDoubleToRawLongBits, "long java.lang.Double.doubleToRawLongBits(double)") \
-  V(DexCacheGetDexNative, "com.android.dex.Dex java.lang.DexCache.getDexNative()") \
   V(MemoryPeekByte, "byte libcore.io.Memory.peekByte(long)") \
   V(MemoryPeekShort, "short libcore.io.Memory.peekShortNative(long)") \
   V(MemoryPeekInt, "int libcore.io.Memory.peekIntNative(long)") \
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 2cff47e..f6dc551 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -841,7 +841,7 @@
   }
 }
 
-inline ObjectArray<Class>* Class::GetInterfaces() {
+inline ObjectArray<Class>* Class::GetProxyInterfaces() {
   CHECK(IsProxyClass());
   // First static field.
   auto* field = GetStaticField(0);
@@ -850,7 +850,7 @@
   return GetFieldObject<ObjectArray<Class>>(field_offset);
 }
 
-inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() {
+inline ObjectArray<ObjectArray<Class>>* Class::GetProxyThrows() {
   CHECK(IsProxyClass());
   // Second static field.
   auto* field = GetStaticField(1);
@@ -920,7 +920,7 @@
   } else if (IsArrayClass()) {
     return 2;
   } else if (IsProxyClass()) {
-    ObjectArray<Class>* interfaces = GetInterfaces();
+    ObjectArray<Class>* interfaces = GetProxyInterfaces();
     return interfaces != nullptr ? interfaces->GetLength() : 0;
   } else {
     const DexFile::TypeList* interfaces = GetInterfaceTypeList();
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index eb2ec9b..efb8710 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -946,7 +946,7 @@
     DCHECK(interface != nullptr);
     return interface;
   } else if (klass->IsProxyClass()) {
-    ObjPtr<ObjectArray<Class>> interfaces = klass->GetInterfaces();
+    ObjPtr<ObjectArray<Class>> interfaces = klass->GetProxyInterfaces();
     DCHECK(interfaces != nullptr);
     return interfaces->Get(idx);
   } else {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index c52b66a..34d5bf3 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -595,7 +595,7 @@
   // The size of java.lang.Class.class.
   static uint32_t ClassClassSize(PointerSize pointer_size) {
     // The number of vtable entries in java.lang.Class.
-    uint32_t vtable_entries = Object::kVTableLength + 70;
+    uint32_t vtable_entries = Object::kVTableLength + 67;
     return ComputeClassSize(true, vtable_entries, 0, 0, 4, 1, 0, pointer_size);
   }
 
@@ -1262,10 +1262,10 @@
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
   // For proxy class only.
-  ObjectArray<Class>* GetInterfaces() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjectArray<Class>* GetProxyInterfaces() REQUIRES_SHARED(Locks::mutator_lock_);
 
   // For proxy class only.
-  ObjectArray<ObjectArray<Class>>* GetThrows() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjectArray<ObjectArray<Class>>* GetProxyThrows() REQUIRES_SHARED(Locks::mutator_lock_);
 
   // For reference class only.
   MemberOffset GetDisableIntrinsicFlagOffset() REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 582ecb2..5d3af50 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -47,7 +47,7 @@
 }
 
 inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
-  uint32_t vtable_entries = Object::kVTableLength + 5;
+  const uint32_t vtable_entries = Object::kVTableLength;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
 }
 
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 35707ef..48a9ecd 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -212,10 +212,6 @@
     return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
   }
 
-  static MemberOffset DexOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(DexCache, dex_);
-  }
-
   static MemberOffset StringsOffset() {
     return OFFSET_OF_OBJECT_MEMBER(DexCache, strings_);
   }
@@ -516,8 +512,11 @@
   static void AtomicStoreRelease16B(std::atomic<ConversionPair64>* target, ConversionPair64 value);
 #endif
 
-  HeapReference<Object> dex_;
   HeapReference<String> location_;
+  // Number of elements in the call_sites_ array. Note that this appears here
+  // because of our packing logic for 32 bit fields.
+  uint32_t num_resolved_call_sites_;
+
   uint64_t dex_file_;               // const DexFile*
   uint64_t resolved_call_sites_;    // GcRoot<CallSite>* array with num_resolved_call_sites_
                                     // elements.
@@ -530,7 +529,6 @@
   uint64_t strings_;                // std::atomic<StringDexCachePair>*, array with num_strings_
                                     // elements.
 
-  uint32_t num_resolved_call_sites_;    // Number of elements in the call_sites_ array.
   uint32_t num_resolved_fields_;        // Number of elements in the resolved_fields_ array.
   uint32_t num_resolved_method_types_;  // Number of elements in the resolved_method_types_ array.
   uint32_t num_resolved_methods_;       // Number of elements in the resolved_methods_ array.
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index c8431c0..381dc7b 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -108,10 +108,50 @@
   return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
 }
 
-static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
+// TODO: Move this to mirror::Class ? Other mirror types that commonly appear
+// as arrays have a GetArrayClass() method.
+static ObjPtr<mirror::Class> GetClassArrayClass(Thread* self)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
+  return Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_class);
+}
+
+static jobjectArray Class_getInterfacesInternal(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::Class> c = DecodeClass(soa, javaThis);
-  return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
+  StackHandleScope<4> hs(soa.Self());
+  Handle<mirror::Class> klass = hs.NewHandle(DecodeClass(soa, javaThis));
+
+  if (klass->IsProxyClass()) {
+    return soa.AddLocalReference<jobjectArray>(klass->GetProxyInterfaces()->Clone(soa.Self()));
+  }
+
+  const DexFile::TypeList* iface_list = klass->GetInterfaceTypeList();
+  if (iface_list == nullptr) {
+    return nullptr;
+  }
+
+  const uint32_t num_ifaces = iface_list->Size();
+  Handle<mirror::Class> class_array_class = hs.NewHandle(GetClassArrayClass(soa.Self()));
+  Handle<mirror::ObjectArray<mirror::Class>> ifaces = hs.NewHandle(
+      mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class.Get(), num_ifaces));
+  if (ifaces.IsNull()) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    return nullptr;
+  }
+
+  // Check that we aren't in an active transaction, we call SetWithoutChecks
+  // with kActiveTransaction == false.
+  DCHECK(!Runtime::Current()->IsActiveTransaction());
+
+  MutableHandle<mirror::Class> interface(hs.NewHandle<mirror::Class>(nullptr));
+  for (uint32_t i = 0; i < num_ifaces; ++i) {
+    const dex::TypeIndex type_idx = iface_list->GetTypeItem(i).type_idx_;
+    interface.Assign(ClassLinker::LookupResolvedType(
+        type_idx, klass->GetDexCache(), klass->GetClassLoader()));
+    ifaces->SetWithoutChecks<false>(i, interface.Get());
+  }
+
+  return soa.AddLocalReference<jobjectArray>(ifaces.Get());
 }
 
 static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
@@ -501,9 +541,7 @@
       // Pending exception from GetDeclaredClasses.
       return nullptr;
     }
-    ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
-    ObjPtr<mirror::Class> class_array_class =
-        Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), &class_class);
+    ObjPtr<mirror::Class> class_array_class = GetClassArrayClass(soa.Self());
     if (class_array_class == nullptr) {
       return nullptr;
     }
@@ -736,8 +774,8 @@
   FAST_NATIVE_METHOD(Class, getEnclosingMethodNative, "()Ljava/lang/reflect/Method;"),
   FAST_NATIVE_METHOD(Class, getInnerClassFlags, "(I)I"),
   FAST_NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
+  FAST_NATIVE_METHOD(Class, getInterfacesInternal, "()[Ljava/lang/Class;"),
   FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
-  FAST_NATIVE_METHOD(Class, getProxyInterfaces, "()[Ljava/lang/Class;"),
   FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"),
   FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"),
   FAST_NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
deleted file mode 100644
index 8fda4df..0000000
--- a/runtime/native/java_lang_DexCache.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "java_lang_DexCache.h"
-
-#include "dex_file.h"
-#include "dex_file_types.h"
-#include "jni_internal.h"
-#include "mirror/class-inl.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/object-inl.h"
-#include "scoped_fast_native_object_access-inl.h"
-#include "well_known_classes.h"
-
-namespace art {
-
-static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) {
-  ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
-  // Should only be called while holding the lock on the dex cache.
-  DCHECK_EQ(dex_cache->GetLockOwnerThreadId(), soa.Self()->GetThreadId());
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  if (dex_file == nullptr) {
-    return nullptr;
-  }
-  void* address = const_cast<void*>(reinterpret_cast<const void*>(dex_file->Begin()));
-  jobject byte_buffer = env->NewDirectByteBuffer(address, dex_file->Size());
-  if (byte_buffer == nullptr) {
-    DCHECK(soa.Self()->IsExceptionPending());
-    return nullptr;
-  }
-
-  jvalue args[1];
-  args[0].l = byte_buffer;
-  return env->CallStaticObjectMethodA(WellKnownClasses::com_android_dex_Dex,
-                                      WellKnownClasses::com_android_dex_Dex_create,
-                                      args);
-}
-
-static jobject DexCache_getResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index) {
-  ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
-  CHECK_LT(static_cast<size_t>(type_index), dex_cache->GetDexFile()->NumTypeIds());
-  return soa.AddLocalReference<jobject>(dex_cache->GetResolvedType(dex::TypeIndex(type_index)));
-}
-
-static jobject DexCache_getResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index) {
-  ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
-  CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
-  return soa.AddLocalReference<jobject>(
-      dex_cache->GetResolvedString(dex::StringIndex(string_index)));
-}
-
-static void DexCache_setResolvedType(JNIEnv* env,
-                                     jobject javaDexCache,
-                                     jint type_index,
-                                     jobject type) {
-  ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
-  const DexFile& dex_file = *dex_cache->GetDexFile();
-  CHECK_LT(static_cast<size_t>(type_index), dex_file.NumTypeIds());
-  ObjPtr<mirror::Class> t = soa.Decode<mirror::Class>(type);
-  if (t != nullptr && t->DescriptorEquals(dex_file.StringByTypeIdx(dex::TypeIndex(type_index)))) {
-    ClassTable* table =
-        Runtime::Current()->GetClassLinker()->FindClassTable(soa.Self(), dex_cache);
-    if (table != nullptr && table->TryInsert(t) == t) {
-      dex_cache->SetResolvedType(dex::TypeIndex(type_index), t);
-    }
-  }
-}
-
-static void DexCache_setResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index,
-                                       jobject string) {
-  ScopedFastNativeObjectAccess soa(env);
-  ObjPtr<mirror::DexCache> dex_cache = soa.Decode<mirror::DexCache>(javaDexCache);
-  CHECK_LT(static_cast<size_t>(string_index), dex_cache->GetDexFile()->NumStringIds());
-  ObjPtr<mirror::String> s = soa.Decode<mirror::String>(string);
-  if (s != nullptr) {
-    dex_cache->SetResolvedString(dex::StringIndex(string_index), s);
-  }
-}
-
-static JNINativeMethod gMethods[] = {
-  FAST_NATIVE_METHOD(DexCache, getDexNative, "()Lcom/android/dex/Dex;"),
-  FAST_NATIVE_METHOD(DexCache, getResolvedType, "(I)Ljava/lang/Class;"),
-  FAST_NATIVE_METHOD(DexCache, getResolvedString, "(I)Ljava/lang/String;"),
-  FAST_NATIVE_METHOD(DexCache, setResolvedType, "(ILjava/lang/Class;)V"),
-  FAST_NATIVE_METHOD(DexCache, setResolvedString, "(ILjava/lang/String;)V"),
-};
-
-void register_java_lang_DexCache(JNIEnv* env) {
-  REGISTER_NATIVE_METHODS("java/lang/DexCache");
-}
-
-}  // namespace art
diff --git a/runtime/native/java_lang_DexCache.h b/runtime/native/java_lang_DexCache.h
deleted file mode 100644
index b1c1f5e..0000000
--- a/runtime/native/java_lang_DexCache.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_DEXCACHE_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_DEXCACHE_H_
-
-#include <jni.h>
-
-namespace art {
-
-void register_java_lang_DexCache(JNIEnv* env);
-
-}  // namespace art
-
-#endif  // ART_RUNTIME_NATIVE_JAVA_LANG_DEXCACHE_H_
diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc
index bc23bed..8f226ce 100644
--- a/runtime/native/java_lang_reflect_Executable.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -194,12 +194,146 @@
   return annotations::IsMethodAnnotationPresent(method, klass);
 }
 
+static jint Executable_compareMethodParametersInternal(JNIEnv* env,
+                                                       jobject thisMethod,
+                                                       jobject otherMethod) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtMethod* this_method = ArtMethod::FromReflectedMethod(soa, thisMethod);
+  ArtMethod* other_method = ArtMethod::FromReflectedMethod(soa, otherMethod);
+
+  this_method = this_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+  other_method = other_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+
+  const DexFile::TypeList* this_list = this_method->GetParameterTypeList();
+  const DexFile::TypeList* other_list = other_method->GetParameterTypeList();
+
+  if (this_list == other_list) {
+    return 0;
+  }
+
+  if (this_list == nullptr && other_list != nullptr) {
+    return -1;
+  }
+
+  if (other_list == nullptr && this_list != nullptr) {
+    return 1;
+  }
+
+  const int32_t this_size = this_list->Size();
+  const int32_t other_size = other_list->Size();
+
+  if (this_size != other_size) {
+    return (this_size - other_size);
+  }
+
+  for (int32_t i = 0; i < this_size; ++i) {
+    const DexFile::TypeId& lhs = this_method->GetDexFile()->GetTypeId(
+        this_list->GetTypeItem(i).type_idx_);
+    const DexFile::TypeId& rhs = other_method->GetDexFile()->GetTypeId(
+        other_list->GetTypeItem(i).type_idx_);
+
+    uint32_t lhs_len, rhs_len;
+    const char* lhs_data = this_method->GetDexFile()->StringDataAndUtf16LengthByIdx(
+        lhs.descriptor_idx_, &lhs_len);
+    const char* rhs_data = other_method->GetDexFile()->StringDataAndUtf16LengthByIdx(
+        rhs.descriptor_idx_, &rhs_len);
+
+    int cmp = strcmp(lhs_data, rhs_data);
+    if (cmp != 0) {
+      return (cmp < 0) ? -1 : 1;
+    }
+  }
+
+  return 0;
+}
+
+static jobject Executable_getMethodNameInternal(JNIEnv* env, jobject javaMethod) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+  return soa.AddLocalReference<jobject>(method->GetNameAsString(soa.Self()));
+}
+
+static jobject Executable_getMethodReturnTypeInternal(JNIEnv* env, jobject javaMethod) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+  ObjPtr<mirror::Class> return_type(method->GetReturnType(true /* resolve */));
+  if (return_type.IsNull()) {
+    CHECK(soa.Self()->IsExceptionPending());
+    return nullptr;
+  }
+
+  return soa.AddLocalReference<jobject>(return_type);
+}
+
+// TODO: Move this to mirror::Class ? Other mirror types that commonly appear
+// as arrays have a GetArrayClass() method. This is duplicated in
+// java_lang_Class.cc as well.
+static ObjPtr<mirror::Class> GetClassArrayClass(Thread* self)
+    REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> class_class = mirror::Class::GetJavaLangClass();
+  return Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_class);
+}
+
+static jobjectArray Executable_getParameterTypesInternal(JNIEnv* env, jobject javaMethod) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+
+  const DexFile::TypeList* params = method->GetParameterTypeList();
+  if (params == nullptr) {
+    return nullptr;
+  }
+
+  const uint32_t num_params = params->Size();
+
+  StackHandleScope<3> hs(soa.Self());
+  Handle<mirror::Class> class_array_class = hs.NewHandle(GetClassArrayClass(soa.Self()));
+  Handle<mirror::ObjectArray<mirror::Class>> ptypes = hs.NewHandle(
+      mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class.Get(), num_params));
+  if (ptypes.IsNull()) {
+    DCHECK(soa.Self()->IsExceptionPending());
+    return nullptr;
+  }
+
+  MutableHandle<mirror::Class> param(hs.NewHandle<mirror::Class>(nullptr));
+  for (uint32_t i = 0; i < num_params; ++i) {
+    const dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_;
+    param.Assign(Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method));
+    if (param.Get() == nullptr) {
+      DCHECK(soa.Self()->IsExceptionPending());
+      return nullptr;
+    }
+    ptypes->SetWithoutChecks<false>(i, param.Get());
+  }
+
+  return soa.AddLocalReference<jobjectArray>(ptypes.Get());
+}
+
+static jint Executable_getParameterCountInternal(JNIEnv* env, jobject javaMethod) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
+  method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+
+  const DexFile::TypeList* params = method->GetParameterTypeList();
+  return (params == nullptr) ? 0 : params->Size();
+}
+
+
 static JNINativeMethod gMethods[] = {
+  FAST_NATIVE_METHOD(Executable, compareMethodParametersInternal,
+                     "(Ljava/lang/reflect/Method;)I"),
   FAST_NATIVE_METHOD(Executable, getAnnotationNative,
-                "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
-  FAST_NATIVE_METHOD(Executable, getDeclaredAnnotationsNative, "()[Ljava/lang/annotation/Annotation;"),
+                     "(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
+  FAST_NATIVE_METHOD(Executable, getDeclaredAnnotationsNative,
+                     "()[Ljava/lang/annotation/Annotation;"),
   FAST_NATIVE_METHOD(Executable, getParameterAnnotationsNative,
-                "()[[Ljava/lang/annotation/Annotation;"),
+                     "()[[Ljava/lang/annotation/Annotation;"),
+  FAST_NATIVE_METHOD(Executable, getMethodNameInternal, "()Ljava/lang/String;"),
+  FAST_NATIVE_METHOD(Executable, getMethodReturnTypeInternal, "()Ljava/lang/Class;"),
+  FAST_NATIVE_METHOD(Executable, getParameterTypesInternal, "()[Ljava/lang/Class;"),
+  FAST_NATIVE_METHOD(Executable, getParameterCountInternal, "()I"),
   FAST_NATIVE_METHOD(Executable, getParameters0, "()[Ljava/lang/reflect/Parameter;"),
   FAST_NATIVE_METHOD(Executable, getSignatureAnnotation, "()[Ljava/lang/String;"),
   FAST_NATIVE_METHOD(Executable, isAnnotationPresentNative, "(Ljava/lang/Class;)Z"),
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 9cf80a5..9198964 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -456,6 +456,13 @@
   return reinterpret_cast<jlong>(field);
 }
 
+static jobject Field_getNameInternal(JNIEnv* env, jobject javaField) {
+  ScopedFastNativeObjectAccess soa(env);
+  ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
+  return soa.AddLocalReference<jobject>(
+      field->GetStringName(soa.Self(), true /* resolve */));
+}
+
 static jobjectArray Field_getDeclaredAnnotations(JNIEnv* env, jobject javaField) {
   ScopedFastNativeObjectAccess soa(env);
   ArtField* field = soa.Decode<mirror::Field>(javaField)->GetArtField();
@@ -506,6 +513,7 @@
   FAST_NATIVE_METHOD(Field, getFloat,   "(Ljava/lang/Object;)F"),
   FAST_NATIVE_METHOD(Field, getInt,     "(Ljava/lang/Object;)I"),
   FAST_NATIVE_METHOD(Field, getLong,    "(Ljava/lang/Object;)J"),
+  FAST_NATIVE_METHOD(Field, getNameInternal, "()Ljava/lang/String;"),
   FAST_NATIVE_METHOD(Field, getShort,   "(Ljava/lang/Object;)S"),
   FAST_NATIVE_METHOD(Field, isAnnotationPresentNative, "(Ljava/lang/Class;)Z"),
   FAST_NATIVE_METHOD(Field, set,        "(Ljava/lang/Object;Ljava/lang/Object;)V"),
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 6e5e3d9..6f0130e 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -55,7 +55,8 @@
       ++i;
     }
     CHECK_NE(throws_index, -1);
-    mirror::ObjectArray<mirror::Class>* declared_exceptions = klass->GetThrows()->Get(throws_index);
+    mirror::ObjectArray<mirror::Class>* declared_exceptions =
+        klass->GetProxyThrows()->Get(throws_index);
     return soa.AddLocalReference<jobjectArray>(declared_exceptions->Clone(soa.Self()));
   } else {
     mirror::ObjectArray<mirror::Class>* result_array =
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 9fd2c88..e4d9aa1 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -106,7 +106,6 @@
 #include "native/dalvik_system_VMStack.h"
 #include "native/dalvik_system_ZygoteHooks.h"
 #include "native/java_lang_Class.h"
-#include "native/java_lang_DexCache.h"
 #include "native/java_lang_Object.h"
 #include "native/java_lang_String.h"
 #include "native/java_lang_StringFactory.h"
@@ -1539,7 +1538,6 @@
   register_dalvik_system_VMStack(env);
   register_dalvik_system_ZygoteHooks(env);
   register_java_lang_Class(env);
-  register_java_lang_DexCache(env);
   register_java_lang_Object(env);
   register_java_lang_invoke_MethodHandleImpl(env);
   register_java_lang_ref_FinalizerReference(env);
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 2610252..54cce98 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -80,7 +80,6 @@
 jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk;
 jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer;
 
-jmethodID WellKnownClasses::com_android_dex_Dex_create;
 jmethodID WellKnownClasses::dalvik_system_VMRuntime_runFinalization;
 jmethodID WellKnownClasses::java_lang_Boolean_valueOf;
 jmethodID WellKnownClasses::java_lang_Byte_valueOf;
@@ -317,7 +316,6 @@
   org_apache_harmony_dalvik_ddmc_DdmServer = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
 
   dalvik_system_VMRuntime_runFinalization = CacheMethod(env, dalvik_system_VMRuntime, true, "runFinalization", "(J)V");
-  com_android_dex_Dex_create = CacheMethod(env, com_android_dex_Dex, true, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
   java_lang_ClassNotFoundException_init = CacheMethod(env, java_lang_ClassNotFoundException, false, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
   java_lang_ClassLoader_loadClass = CacheMethod(env, java_lang_ClassLoader, false, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
 
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index db8a53c..af4dbbf 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -90,7 +90,6 @@
   static jclass org_apache_harmony_dalvik_ddmc_Chunk;
   static jclass org_apache_harmony_dalvik_ddmc_DdmServer;
 
-  static jmethodID com_android_dex_Dex_create;
   static jmethodID dalvik_system_VMRuntime_runFinalization;
   static jmethodID java_lang_Boolean_valueOf;
   static jmethodID java_lang_Byte_valueOf;