Merge "See if running single-threaded fixes dex2oat Mac crashes." into dalvik-dev
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9ce641f..8a655bd 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -176,8 +176,9 @@
   "Ljava/lang/reflect/Method;",
   "Ljava/lang/reflect/Proxy;",
   "[Ljava/lang/String;",
-  "[Ljava/lang/reflect/Field;",
   "[Ljava/lang/reflect/AbstractMethod;",
+  "[Ljava/lang/reflect/Field;",
+  "[Ljava/lang/reflect/Method;",
   "Ljava/lang/ClassLoader;",
   "Ljava/lang/Throwable;",
   "Ljava/lang/ClassNotFoundException;",
@@ -315,13 +316,6 @@
   java_lang_DexCache->SetStatus(Class::kStatusResolved);
 
   // Constructor, Field, Method, and AbstractMethod are necessary so that FindClass can link members.
-  SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(),
-                                                                sizeof(MethodClass)));
-  CHECK(java_lang_reflect_Constructor.get() != NULL);
-  java_lang_reflect_Constructor->SetObjectSize(sizeof(Constructor));
-  SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
-  java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
-
   SirtRef<Class> java_lang_reflect_Field(self, AllocClass(self, java_lang_Class.get(),
                                                           sizeof(FieldClass)));
   CHECK(java_lang_reflect_Field.get() != NULL);
@@ -330,19 +324,29 @@
   java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
   Field::SetClass(java_lang_reflect_Field.get());
 
-  SirtRef<Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(),
-                                                           sizeof(MethodClass)));
-  CHECK(java_lang_reflect_Method.get() != NULL);
-  java_lang_reflect_Method->SetObjectSize(sizeof(Method));
-  SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
-  java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
-
   SirtRef<Class> java_lang_reflect_AbstractMethod(self, AllocClass(self, java_lang_Class.get(),
                                                                    sizeof(MethodClass)));
   CHECK(java_lang_reflect_AbstractMethod.get() != NULL);
   java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(AbstractMethod));
   SetClassRoot(kJavaLangReflectAbstractMethod, java_lang_reflect_AbstractMethod.get());
   java_lang_reflect_AbstractMethod->SetStatus(Class::kStatusResolved);
+
+  SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(),
+                                                                sizeof(MethodClass)));
+  CHECK(java_lang_reflect_Constructor.get() != NULL);
+  java_lang_reflect_Constructor->SetObjectSize(sizeof(Constructor));
+  java_lang_reflect_Constructor->SetSuperClass(java_lang_reflect_AbstractMethod.get());
+  SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get());
+  java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved);
+
+  SirtRef<Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(),
+                                                           sizeof(MethodClass)));
+  CHECK(java_lang_reflect_Method.get() != NULL);
+  java_lang_reflect_Method->SetObjectSize(sizeof(Method));
+  java_lang_reflect_Method->SetSuperClass(java_lang_reflect_AbstractMethod.get());
+  SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get());
+  java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
+
   AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get());
 
   // Set up array classes for string, field, method
@@ -350,13 +354,17 @@
   object_array_string->SetComponentType(java_lang_String.get());
   SetClassRoot(kJavaLangStringArrayClass, object_array_string.get());
 
+  SirtRef<Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class)));
+  object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
+  SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());
+
   SirtRef<Class> object_array_field(self, AllocClass(self, java_lang_Class.get(), sizeof(Class)));
   object_array_field->SetComponentType(java_lang_reflect_Field.get());
   SetClassRoot(kJavaLangReflectFieldArrayClass, object_array_field.get());
 
-  SirtRef<Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class)));
-  object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
-  SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());
+  SirtRef<Class> object_array_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class)));
+  object_array_method->SetComponentType(java_lang_reflect_Method.get());
+  SetClassRoot(kJavaLangReflectMethodArrayClass, object_array_method.get());
 
   // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
   // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
@@ -466,13 +474,17 @@
   Class* String_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangStringArrayClass]);
   CHECK_EQ(object_array_string.get(), String_array_class);
 
-  Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]);
-  CHECK_EQ(object_array_field.get(), Field_array_class);
-
   Class* Abstract_method_array_class =
       FindSystemClass(class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]);
   CHECK_EQ(object_array_abstract_method.get(), Abstract_method_array_class);
 
+  Class* Field_array_class = FindSystemClass(class_roots_descriptors_[kJavaLangReflectFieldArrayClass]);
+  CHECK_EQ(object_array_field.get(), Field_array_class);
+
+  Class* Method_array_class =
+      FindSystemClass(class_roots_descriptors_[kJavaLangReflectMethodArrayClass]);
+  CHECK_EQ(object_array_method.get(), Method_array_class);
+
   // End of special init trickery, subsequent classes may be loaded via FindSystemClass.
 
   // Create java.lang.reflect.Proxy root.
@@ -528,7 +540,7 @@
   Class* java_lang_ref_ReferenceQueue = FindSystemClass("Ljava/lang/ref/ReferenceQueue;");
   Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
 
-  const DexFile& java_lang_dex = FindDexFile(java_lang_ref_Reference->GetDexCache());
+  const DexFile& java_lang_dex = *java_lang_ref_Reference->GetDexCache()->GetDexFile();
 
   Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
   FieldHelper fh(pendingNext, this);
@@ -1136,7 +1148,7 @@
     return NULL;
   }
   SirtRef<ObjectArray<AbstractMethod> >
-      methods(self, AllocMethodArray(self, dex_file.NumMethodIds()));
+      methods(self, AllocAbstractMethodArray(self, dex_file.NumMethodIds()));
   if (methods.get() == NULL) {
     return NULL;
   }
@@ -1594,10 +1606,10 @@
   ClassDataItemIterator it(dex_file, class_data);
   Thread* self = Thread::Current();
   if (it.NumStaticFields() != 0) {
-    klass->SetSFields(AllocObjectArray<Field>(self, it.NumStaticFields()));
+    klass->SetSFields(AllocFieldArray(self, it.NumStaticFields()));
   }
   if (it.NumInstanceFields() != 0) {
-    klass->SetIFields(AllocObjectArray<Field>(self, it.NumInstanceFields()));
+    klass->SetIFields(AllocFieldArray(self, it.NumInstanceFields()));
   }
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
     SirtRef<Field> sfield(self, AllocField(self));
@@ -1618,11 +1630,11 @@
   // Load methods.
   if (it.NumDirectMethods() != 0) {
     // TODO: append direct methods to class object
-    klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(self, it.NumDirectMethods()));
+    klass->SetDirectMethods(AllocAbstractMethodArray(self, it.NumDirectMethods()));
   }
   if (it.NumVirtualMethods() != 0) {
     // TODO: append direct methods to class object
-    klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(self, it.NumVirtualMethods()));
+    klass->SetVirtualMethods(AllocMethodArray(self, it.NumVirtualMethods()));
   }
   size_t class_def_method_index = 0;
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
@@ -1778,16 +1790,6 @@
   RegisterDexFileLocked(dex_file, dex_cache);
 }
 
-// TODO: Remove.
-const DexFile& ClassLinker::FindDexFile(const DexCache* dex_cache) const {
-  CHECK(dex_cache != NULL);
-  const DexFile* dex_file = dex_cache->GetDexFile();
-  if (dex_file == NULL) {
-    LOG(FATAL) << "DexCache has no DexFile " << dex_cache->GetLocation()->ToModifiedUtf8();
-  }
-  return *dex_file;
-}
-
 DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
   MutexLock mu(Thread::Current(), dex_lock_);
   for (size_t i = 0; i != dex_caches_.size(); ++i) {
@@ -1886,10 +1888,12 @@
       new_class.reset(GetClassRoot(kObjectArrayArrayClass));
     } else if (descriptor == class_roots_descriptors_[kJavaLangStringArrayClass]) {
       new_class.reset(GetClassRoot(kJavaLangStringArrayClass));
-    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectFieldArrayClass]) {
-      new_class.reset(GetClassRoot(kJavaLangReflectFieldArrayClass));
     } else if (descriptor == class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]) {
       new_class.reset(GetClassRoot(kJavaLangReflectAbstractMethodArrayClass));
+    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectFieldArrayClass]) {
+      new_class.reset(GetClassRoot(kJavaLangReflectFieldArrayClass));
+    } else if (descriptor == class_roots_descriptors_[kJavaLangReflectMethodArrayClass]) {
+      new_class.reset(GetClassRoot(kJavaLangReflectMethodArrayClass));
     } else if (descriptor == "[C") {
       new_class.reset(GetClassRoot(kCharArrayClass));
     } else if (descriptor == "[I") {
@@ -2145,7 +2149,7 @@
   }
 
   // Try to use verification information from the oat file, otherwise do runtime verification.
-  const DexFile& dex_file = FindDexFile(klass->GetDexCache());
+  const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
   Class::Status oat_file_class_status(Class::kStatusNotReady);
   bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
   verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
@@ -2318,7 +2322,7 @@
   klass->SetDexTypeIndex(DexFile::kDexNoIndex16);
 
   // Instance fields are inherited, but we add a couple of static fields...
-  klass->SetSFields(AllocObjectArray<Field>(self, 2));
+  klass->SetSFields(AllocFieldArray(self, 2));
   // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
   // our proxy, so Class.getInterfaces doesn't return the flattened set.
   SirtRef<Field> interfaces_sfield(self, AllocField(self));
@@ -2334,12 +2338,12 @@
   throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // Proxies have 1 direct method, the constructor
-  klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(self, 1));
+  klass->SetDirectMethods(AllocAbstractMethodArray(self, 1));
   klass->SetDirectMethod(0, CreateProxyConstructor(self, klass, proxy_class));
 
   // Create virtual method using specified prototypes
   size_t num_virtual_methods = methods->GetLength();
-  klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(self, num_virtual_methods));
+  klass->SetVirtualMethods(AllocMethodArray(self, num_virtual_methods));
   for (size_t i = 0; i < num_virtual_methods; ++i) {
     SirtRef<AbstractMethod> prototype(self, methods->Get(i));
     klass->SetVirtualMethod(i, CreateProxyMethod(self, klass, prototype));
@@ -2706,7 +2710,7 @@
   if (klass1 == klass2) {
     return true;
   }
-  const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
+  const DexFile& dex_file = *method->GetDeclaringClass()->GetDexCache()->GetDexFile();
   const DexFile::ProtoId& proto_id =
       dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
   for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
@@ -3042,7 +3046,7 @@
       return false;
     }
     SirtRef<ObjectArray<AbstractMethod> >
-        vtable(self, AllocObjectArray<AbstractMethod>(self, num_virtual_methods));
+        vtable(self, AllocMethodArray(self, num_virtual_methods));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
       AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
       vtable->Set(i, virtual_method);
@@ -3145,7 +3149,7 @@
     InterfaceEntry* interface_entry = iftable->Get(i);
     Class* interface = interface_entry->GetInterface();
     ObjectArray<AbstractMethod>* method_array =
-        AllocObjectArray<AbstractMethod>(self, interface->NumVirtualMethods());
+        AllocMethodArray(self, interface->NumVirtualMethods());
     interface_entry->SetMethodArray(method_array);
     ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking();
     for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
@@ -3196,7 +3200,7 @@
     int old_method_count = klass->NumVirtualMethods();
     int new_method_count = old_method_count + miranda_list.size();
     klass->SetVirtualMethods((old_method_count == 0)
-                             ? AllocObjectArray<AbstractMethod>(self, new_method_count)
+                             ? AllocMethodArray(self, new_method_count)
                              : klass->GetVirtualMethods()->CopyOf(self, new_method_count));
 
     SirtRef<ObjectArray<AbstractMethod> > vtable(self, klass->GetVTableDuringLinking());
@@ -3729,7 +3733,7 @@
 const char* ClassLinker::MethodShorty(uint32_t method_idx, AbstractMethod* referrer, uint32_t* length) {
   Class* declaring_class = referrer->GetDeclaringClass();
   DexCache* dex_cache = declaring_class->GetDexCache();
-  const DexFile& dex_file = FindDexFile(dex_cache);
+  const DexFile& dex_file = *dex_cache->GetDexFile();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
   return dex_file.GetMethodShorty(method_id, length);
 }
diff --git a/src/class_linker.h b/src/class_linker.h
index 38b402f..fd404c1 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -104,7 +104,7 @@
     if (UNLIKELY(resolved_string == NULL)) {
       Class* declaring_class = referrer->GetDeclaringClass();
       DexCache* dex_cache = declaring_class->GetDexCache();
-      const DexFile& dex_file = FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       resolved_string = ResolveString(dex_file, string_idx, dex_cache);
     }
     return resolved_string;
@@ -136,7 +136,7 @@
       Class* declaring_class = referrer->GetDeclaringClass();
       DexCache* dex_cache = declaring_class->GetDexCache();
       ClassLoader* class_loader = declaring_class->GetClassLoader();
-      const DexFile& dex_file = FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
     }
     return resolved_type;
@@ -149,7 +149,7 @@
     Class* resolved_type = dex_cache->GetResolvedType(type_idx);
     if (UNLIKELY(resolved_type == NULL)) {
       ClassLoader* class_loader = declaring_class->GetClassLoader();
-      const DexFile& dex_file = FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader);
     }
     return resolved_type;
@@ -185,7 +185,7 @@
       Class* declaring_class = referrer->GetDeclaringClass();
       DexCache* dex_cache = declaring_class->GetDexCache();
       ClassLoader* class_loader = declaring_class->GetClassLoader();
-      const DexFile& dex_file = FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       resolved_method = ResolveMethod(dex_file, method_idx, dex_cache, class_loader, referrer, type);
     }
     return resolved_method;
@@ -199,7 +199,7 @@
       Class* declaring_class = referrer->GetDeclaringClass();
       DexCache* dex_cache = declaring_class->GetDexCache();
       ClassLoader* class_loader = declaring_class->GetClassLoader();
-      const DexFile& dex_file = FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static);
     }
     return resolved_field;
@@ -265,9 +265,6 @@
   void VisitRoots(Heap::RootVisitor* visitor, void* arg) const
       LOCKS_EXCLUDED(Locks::classlinker_classes_lock_, dex_lock_);
 
-  const DexFile& FindDexFile(const DexCache* dex_cache) const
-      LOCKS_EXCLUDED(dex_lock_)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   DexCache* FindDexCache(const DexFile& dex_file) const
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -328,12 +325,18 @@
     return ObjectArray<String>::Alloc(self, GetClassRoot(kJavaLangStringArrayClass), length);
   }
 
-  ObjectArray<AbstractMethod>* AllocMethodArray(Thread* self, size_t length)
+  ObjectArray<AbstractMethod>* AllocAbstractMethodArray(Thread* self, size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return ObjectArray<AbstractMethod>::Alloc(self,
         GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length);
   }
 
+  ObjectArray<AbstractMethod>* AllocMethodArray(Thread* self, size_t length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ObjectArray<AbstractMethod>::Alloc(self,
+        GetClassRoot(kJavaLangReflectMethodArrayClass), length);
+  }
+
   ObjectArray<InterfaceEntry>* AllocIfTable(Thread* self, size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return ObjectArray<InterfaceEntry>::Alloc(self, GetClassRoot(kObjectArrayArrayClass), length);
@@ -581,8 +584,9 @@
     kJavaLangReflectMethod,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
-    kJavaLangReflectFieldArrayClass,
     kJavaLangReflectAbstractMethodArrayClass,
+    kJavaLangReflectFieldArrayClass,
+    kJavaLangReflectMethodArrayClass,
     kJavaLangClassLoader,
     kJavaLangThrowable,
     kJavaLangClassNotFoundException,
diff --git a/src/common_test.h b/src/common_test.h
index 6994ac3..62ff907 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -229,7 +229,7 @@
 
     if (!method->IsAbstract()) {
       const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
-      const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       const CompiledMethod* compiled_method =
           compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
                                                                  method->GetDexMethodIndex()));
diff --git a/src/common_throws.cc b/src/common_throws.cc
index 7ab5614..9fb686a 100644
--- a/src/common_throws.cc
+++ b/src/common_throws.cc
@@ -61,7 +61,7 @@
 void ThrowNullPointerExceptionForMethodAccess(AbstractMethod* caller, uint32_t method_idx,
                                               InvokeType type) {
   DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache();
-  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  const DexFile& dex_file = *dex_cache->GetDexFile();
   std::ostringstream msg;
   msg << "Attempt to invoke " << type << " method '"
       << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
@@ -133,8 +133,7 @@
     default: {
       // TODO: We should have covered all the cases where we expect a NPE above, this
       //       message/logging is so we can improve any cases we've missed in the future.
-      const DexFile& dex_file = Runtime::Current()->GetClassLinker()
-          ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
+      const DexFile& dex_file = *throw_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
       std::string message("Null pointer exception during instruction '");
       message += instr->DumpString(&dex_file);
       message += "'";
@@ -243,7 +242,7 @@
 
 void ThrowNoSuchMethodError(uint32_t method_idx, const AbstractMethod* referrer) {
   DexCache* dex_cache = referrer->GetDeclaringClass()->GetDexCache();
-  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  const DexFile& dex_file = *dex_cache->GetDexFile();
   std::ostringstream msg;
   msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
   AddReferrerLocation(msg, referrer);
diff --git a/src/compiler.cc b/src/compiler.cc
index 3899ce9..8909c36 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -510,7 +510,7 @@
     class_loader = soa.Env()->NewGlobalRef(local_class_loader.get());
     // Find the dex_file
     dex_cache = method->GetDeclaringClass()->GetDexCache();
-    dex_file = &Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+    dex_file = dex_cache->GetDexFile();
   }
   self->TransitionFromRunnableToSuspended(kNative);
 
@@ -708,7 +708,7 @@
         // The referring class can't access the resolved field, this may occur as a result of a
         // protected field being made public by a sub-class. Resort to the dex file to determine
         // the correct class for the access check.
-        const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
+        const DexFile& dex_file = *referrer_class->GetDexCache()->GetDexFile();
         Class* dex_fields_class = mUnit->class_linker_->ResolveType(dex_file,
                                                          dex_file.GetFieldId(field_idx).class_idx_,
                                                          referrer_class);
@@ -764,7 +764,7 @@
           // protected field being made public by a sub-class. Resort to the dex file to determine
           // the correct class for the access check. Don't change the field's class as that is
           // used to identify the SSB.
-          const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
+          const DexFile& dex_file = *referrer_class->GetDexCache()->GetDexFile();
           Class* dex_fields_class =
               mUnit->class_linker_->ResolveType(dex_file,
                                                 dex_file.GetFieldId(field_idx).class_idx_,
@@ -878,7 +878,7 @@
         // protected method being made public by implementing an interface that re-declares the
         // method public. Resort to the dex file to determine the correct class for the access
         // check.
-        const DexFile& dex_file = mUnit->class_linker_->FindDexFile(referrer_class->GetDexCache());
+        const DexFile& dex_file = *referrer_class->GetDexCache()->GetDexFile();
         methods_class =
             mUnit->class_linker_->ResolveType(dex_file,
                                               dex_file.GetMethodId(method_idx).class_idx_,
diff --git a/src/debugger.cc b/src/debugger.cc
index c8e7381..6f0ec58 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -2167,7 +2167,7 @@
           gSingleStepControl.method = m;
           gSingleStepControl.line_number = -1;
           if (dex_cache != NULL) {
-            const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+            const DexFile& dex_file = *dex_cache->GetDexFile();
             gSingleStepControl.line_number = dex_file.GetLineNumFromPC(m, GetDexPc());
           }
         }
diff --git a/src/exception_test.cc b/src/exception_test.cc
index c35572d..58e6533 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -38,7 +38,7 @@
     ASSERT_TRUE(my_klass_ != NULL);
     class_linker_->EnsureInitialized(my_klass_, false, true);
 
-    dex_ = &Runtime::Current()->GetClassLinker()->FindDexFile(my_klass_->GetDexCache());
+    dex_ = my_klass_->GetDexCache()->GetDexFile();
 
     uint32_t code_size = 12;
     fake_code_.push_back((code_size >> 24) & 0xFF);
diff --git a/src/image_writer.cc b/src/image_writer.cc
index fe12baf..0b9c8c0 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -172,11 +172,10 @@
   String* string = obj->AsString();
   std::string utf8_string(string->ToModifiedUtf8());
   ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
   typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
   for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) {
     DexCache* dex_cache = *it;
-    const DexFile& dex_file = linker->FindDexFile(dex_cache);
+    const DexFile& dex_file = *dex_cache->GetDexFile();
     const DexFile::StringId* string_id = dex_file.FindStringId(utf8_string);
     if (string_id != NULL) {
       // This string occurs in this dex file, assign the dex cache entry.
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 488df80..59c9bef 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -88,147 +88,6 @@
   }
 }
 
-// TODO: Remove this redundant struct when GCC annotalysis works correctly on top-level functions.
-struct WorkAroundGccAnnotalysisBug {
-template<typename T>
-static jobjectArray ToArray(const ScopedObjectAccessUnchecked& soa, const char* array_class_name,
-                            const std::vector<T*>& objects)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ScopedLocalRef<jclass> array_class(soa.Env(), soa.Env()->FindClass(array_class_name));
-  jobjectArray result = soa.Env()->NewObjectArray(objects.size(), array_class.get(), NULL);
-  for (size_t i = 0; i < objects.size(); ++i) {
-    ScopedLocalRef<jobject> object(soa.Env(), soa.AddLocalReference<jobject>(objects[i]));
-    soa.Env()->SetObjectArrayElement(result, i, object.get());
-  }
-  return result;
-}
-};
-#define ToArray(a, b, c) WorkAroundGccAnnotalysisBug::ToArray(a, b, c)
-
-static bool IsVisibleConstructor(AbstractMethod* m, bool public_only) {
-  if (public_only && !m->IsPublic()) {
-    return false;
-  }
-  if (m->IsStatic()) {
-    return false;
-  }
-  return m->IsConstructor();
-}
-
-static jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, javaClass);
-  std::vector<AbstractMethod*> constructors; // TODO: Use Constructor instead of AbstractMethod
-  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    AbstractMethod* m = c->GetDirectMethod(i);
-    if (IsVisibleConstructor(m, publicOnly)) {
-      constructors.push_back(m);
-    }
-  }
-
-  return ToArray(soa, "java/lang/reflect/Constructor", constructors);
-}
-
-static bool IsVisibleField(Field* f, bool public_only) {
-  if (public_only && !f->IsPublic()) {
-    return false;
-  }
-  return true;
-}
-
-static jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, javaClass);
-  std::vector<Field*> fields;
-  FieldHelper fh;
-  for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
-    Field* f = c->GetInstanceField(i);
-    fh.ChangeField(f);
-    if (IsVisibleField(f, publicOnly)) {
-      if (fh.GetType() == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      fields.push_back(f);
-    }
-    if (env->ExceptionOccurred()) {
-      return NULL;
-    }
-  }
-  for (size_t i = 0; i < c->NumStaticFields(); ++i) {
-    Field* f = c->GetStaticField(i);
-    fh.ChangeField(f);
-    if (IsVisibleField(f, publicOnly)) {
-      if (fh.GetType() == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      fields.push_back(f);
-    }
-    if (env->ExceptionOccurred()) {
-      return NULL;
-    }
-  }
-
-  return ToArray(soa, "java/lang/reflect/Field", fields);
-}
-
-static bool IsVisibleMethod(AbstractMethod* m, bool public_only) {
-  if (public_only && !m->IsPublic()) {
-    return false;
-  }
-  if (m->IsConstructor()) {
-    return false;
-  }
-  if (m->IsMiranda()) {
-    return false;
-  }
-  return true;
-}
-
-static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, javaClass);
-  if (c == NULL) {
-    return NULL;
-  }
-
-  std::vector<AbstractMethod*> methods;
-  MethodHelper mh;
-  for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    AbstractMethod* m = c->GetVirtualMethod(i);
-    mh.ChangeMethod(m);
-    if (IsVisibleMethod(m, publicOnly)) {
-      // TODO: the use of GetParameterTypes creates an unused array here.
-      if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      methods.push_back(m);
-    }
-    if (env->ExceptionOccurred()) {
-      return NULL;
-    }
-  }
-  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    AbstractMethod* m = c->GetDirectMethod(i);
-    mh.ChangeMethod(m);
-    if (IsVisibleMethod(m, publicOnly)) {
-      // TODO: the use of GetParameterTypes creates an unused array here.
-      if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      methods.push_back(m);
-    }
-    if (env->ExceptionOccurred()) {
-      return NULL;
-    }
-  }
-
-  return ToArray(soa, "java/lang/reflect/Method", methods);
-}
-
 static jobject Class_getDex(JNIEnv* env, jobject javaClass) {
   ScopedObjectAccess soa(env);
   Class* c = DecodeClass(soa, javaClass);
@@ -237,109 +96,11 @@
   if (dex_cache == NULL) {
     return NULL;
   }
-
-  return Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache).GetDexObject(env);
-}
-
-static bool MethodMatches(MethodHelper* mh, const std::string& name, ObjectArray<Class>* arg_array)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (name != mh->GetName()) {
-    return false;
-  }
-  const DexFile::TypeList* m_type_list = mh->GetParameterTypeList();
-  uint32_t m_type_list_size = m_type_list == NULL ? 0 : m_type_list->Size();
-  uint32_t sig_length = arg_array->GetLength();
-
-  if (m_type_list_size != sig_length) {
-    return false;
-  }
-
-  for (uint32_t i = 0; i < sig_length; i++) {
-    if (mh->GetClassFromTypeIdx(m_type_list->GetTypeItem(i).type_idx_) != arg_array->Get(i)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static AbstractMethod* FindConstructorOrMethodInArray(ObjectArray<AbstractMethod>* methods,
-                                                      const std::string& name,
-                                                      ObjectArray<Class>* arg_array)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (methods == NULL) {
+  const DexFile* dex_file = dex_cache->GetDexFile();
+  if (dex_file == NULL) {
     return NULL;
   }
-  AbstractMethod* result = NULL;
-  MethodHelper mh;
-  for (int32_t i = 0; i < methods->GetLength(); ++i) {
-    AbstractMethod* method = methods->Get(i);
-    mh.ChangeMethod(method);
-    if (method->IsMiranda() || !MethodMatches(&mh, name, arg_array)) {
-      continue;
-    }
-
-    result = method;
-
-    // Covariant return types permit the class to define multiple
-    // methods with the same name and parameter types. Prefer to return
-    // a non-synthetic method in such situations. We may still return
-    // a synthetic method to handle situations like escalated visibility.
-    if (!method->IsSynthetic()) {
-        break;
-    }
-  }
-  return result;
-}
-
-static jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName,
-                                                    jobjectArray javaArgs) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, javaClass);
-  std::string name(soa.Decode<String*>(javaName)->ToModifiedUtf8());
-  ObjectArray<Class>* arg_array = soa.Decode<ObjectArray<Class>*>(javaArgs);
-
-  AbstractMethod* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
-  if (m == NULL) {
-    m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, arg_array);
-  }
-
-  if (m != NULL) {
-    return soa.AddLocalReference<jobject>(m);
-  } else {
-    return NULL;
-  }
-}
-
-static jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass java_class, jobject jname) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, java_class);
-  String* name = soa.Decode<String*>(jname);
-  DCHECK(name->GetClass()->IsStringClass());
-
-  FieldHelper fh;
-  for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
-    Field* f = c->GetInstanceField(i);
-    fh.ChangeField(f);
-    if (name->Equals(fh.GetName())) {
-      if (fh.GetType() == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      return soa.AddLocalReference<jclass>(f);
-    }
-  }
-  for (size_t i = 0; i < c->NumStaticFields(); ++i) {
-    Field* f = c->GetStaticField(i);
-    fh.ChangeField(f);
-    if (name->Equals(fh.GetName())) {
-      if (fh.GetType() == NULL) {
-        DCHECK(env->ExceptionOccurred());
-        return NULL;
-      }
-      return soa.AddLocalReference<jclass>(f);
-    }
-  }
-  return NULL;
+  return dex_file->GetDexObject(env);
 }
 
 static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
@@ -354,91 +115,12 @@
   return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
 }
 
-static jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
-  ScopedObjectAccess soa(env);
-  Class* lhs = DecodeClass(soa, javaLhs);
-  Class* rhs = soa.Decode<Class*>(javaRhs); // Can be null.
-  if (rhs == NULL) {
-    soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null");
-    return JNI_FALSE;
-  }
-  return lhs->IsAssignableFrom(rhs) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
-  ScopedObjectAccess soa(env);
-  Class* c = DecodeClass(soa, javaThis);
-  if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
-        "Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
-    return NULL;
-  }
-
-  if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
-    return NULL;
-  }
-
-  AbstractMethod* init = c->FindDeclaredDirectMethod("<init>", "()V");
-  if (init == NULL) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
-        "Class %s has no default <init>()V constructor", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
-    return NULL;
-  }
-
-  // Verify access from the call site.
-  //
-  // First, make sure the method invoking Class.newInstance() has permission
-  // to access the class.
-  //
-  // Second, make sure it has permission to invoke the constructor.  The
-  // constructor must be public or, if the caller is in the same package,
-  // have package scope.
-
-  NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetTraceStack(), 2);
-  visitor.WalkStack();
-  Class* caller_class = visitor.caller->GetDeclaringClass();
-
-  ClassHelper caller_ch(caller_class);
-  if (!caller_class->CanAccess(c)) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
-        "Class %s is not accessible from class %s",
-        PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str(),
-        PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
-    return NULL;
-  }
-  if (!caller_class->CanAccessMember(init->GetDeclaringClass(), init->GetAccessFlags())) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
-        "%s is not accessible from class %s",
-        PrettyMethod(init).c_str(),
-        PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
-    return NULL;
-  }
-
-  Object* new_obj = c->AllocObject(soa.Self());
-  if (new_obj == NULL) {
-    DCHECK(soa.Self()->IsExceptionPending());
-    return NULL;
-  }
-
-  // invoke constructor; unlike reflection calls, we don't wrap exceptions
-  jclass java_class = soa.AddLocalReference<jclass>(c);
-  jmethodID mid = soa.EncodeMethod(init);
-  return env->NewObject(java_class, mid);
-}
-
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getAnnotationDirectoryOffset, "()I"),
-  NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
-  NATIVE_METHOD(Class, getDeclaredConstructors, "(Z)[Ljava/lang/reflect/Constructor;"),
-  NATIVE_METHOD(Class, getDeclaredFieldNative, "(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
-  NATIVE_METHOD(Class, getDeclaredFields, "(Z)[Ljava/lang/reflect/Field;"),
-  NATIVE_METHOD(Class, getDeclaredMethods, "(Z)[Ljava/lang/reflect/Method;"),
   NATIVE_METHOD(Class, getDex, "()Lcom/android/dex/Dex;"),
   NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "()[Ljava/lang/Class;"),
-  NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
-  NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"),
 };
 
 void register_java_lang_Class(JNIEnv* env) {
diff --git a/src/object.h b/src/object.h
index baa7313..1af30ea 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1536,10 +1536,10 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(src != NULL);
     if (this == src) {
-      // Can always assign to things of the same type
+      // Can always assign to things of the same type.
       return true;
     } else if (IsObjectClass()) {
-      // Can assign any reference to java.lang.Object
+      // Can assign any reference to java.lang.Object.
       return !src->IsPrimitive();
     } else if (IsInterface()) {
       return src->Implements(this);
diff --git a/src/object_utils.h b/src/object_utils.h
index 297035f..1bbb7bc 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -654,8 +654,7 @@
     const DexFile* result = dex_file_;
     if (result == NULL) {
       const DexCache* dex_cache = GetDexCache();
-      result = &GetClassLinker()->FindDexFile(dex_cache);
-      dex_file_ = result;
+      result = dex_file_ = dex_cache->GetDexFile();
     }
     return *result;
   }
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 54baa42..7ee1960 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -162,7 +162,7 @@
       // The referring class can't access the resolved field, this may occur as a result of a
       // protected field being made public by a sub-class. Resort to the dex file to determine
       // the correct class for the access check.
-      const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
+      const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
       fields_class = class_linker->ResolveType(dex_file,
                                                dex_file.GetFieldId(field_idx).class_idx_,
                                                referring_class);
@@ -256,7 +256,7 @@
         // The referring class can't access the resolved method, this may occur as a result of a
         // protected method being made public by implementing an interface that re-declares the
         // method public. Resort to the dex file to determine the correct class for the access check
-        const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
+        const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
         methods_class = class_linker->ResolveType(dex_file,
                                                   dex_file.GetMethodId(method_idx).class_idx_,
                                                   referring_class);
diff --git a/src/thread.cc b/src/thread.cc
index a63a5aa..6e4a633 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -802,11 +802,10 @@
     }
     const int kMaxRepetition = 3;
     Class* c = m->GetDeclaringClass();
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     const DexCache* dex_cache = c->GetDexCache();
     int line_number = -1;
     if (dex_cache != NULL) {  // be tolerant of bad input
-      const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
+      const DexFile& dex_file = *dex_cache->GetDexFile();
       line_number = dex_file.GetLineNumFromPC(m, GetDexPc());
     }
     if (line_number == last_line_number && last_method == m) {
@@ -1701,9 +1700,7 @@
       if (catch_method == NULL) {
         LOG(INFO) << "Handler is upcall";
       } else {
-        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-        const DexFile& dex_file =
-            class_linker->FindDexFile(catch_method->GetDeclaringClass()->GetDexCache());
+        const DexFile& dex_file = *catch_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
         int line_number = dex_file.GetLineNumFromPC(catch_method, handler_dex_pc_);
         LOG(INFO) << "Handler: " << PrettyMethod(catch_method) << " (line: " << line_number << ")";
       }