Remove dexCacheResolvedMethods, address Proxy issue

Change-Id: Iab8c7edb954d241bd5a92260db07696b9559155f
diff --git a/src/class_linker.cc b/src/class_linker.cc
index bc8e333..60bd614 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1515,7 +1515,6 @@
 
   dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
   dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
-  dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
   dst->SetDexCacheCodeAndDirectMethods(klass->GetDexCache()->GetCodeAndDirectMethods());
   dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
 }
@@ -2140,6 +2139,28 @@
   return DotToDescriptor(name->ToModifiedUtf8().c_str());
 }
 
+Method* ClassLinker::FindMethodForProxy(const Class* proxy_class, const Method* proxy_method) {
+  DCHECK(proxy_class->IsProxyClass());
+  DCHECK(proxy_method->IsProxyMethod());
+  // Locate the dex cache of the original interface/Object
+  DexCache* dex_cache = NULL;
+  {
+    ObjectArray<Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes();
+    MutexLock mu(dex_lock_);
+    for (size_t i = 0; i != dex_caches_.size(); ++i) {
+      if (dex_caches_[i]->GetResolvedTypes() == resolved_types) {
+        dex_cache = dex_caches_[i];
+        break;
+      }
+    }
+  }
+  CHECK(dex_cache != NULL);
+  uint32_t method_idx = proxy_method->GetDexMethodIndex();
+  Method* resolved_method = dex_cache->GetResolvedMethod(method_idx);
+  CHECK(resolved_method != NULL);
+  return resolved_method;
+}
+
 
 Method* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) {
   // Create constructor for Proxy that must initialize h
@@ -2166,7 +2187,8 @@
 Method* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<Method>& prototype) {
   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
   // prototype method
-  prototype->GetDexCacheResolvedMethods()->Set(prototype->GetDexMethodIndex(), prototype.get());
+  prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
+                                                                   prototype.get());
   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
   // as necessary
   Method* method = down_cast<Method*>(prototype->Clone());
@@ -2183,6 +2205,7 @@
   method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
   method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
   method->SetCode(reinterpret_cast<void*>(art_proxy_invoke_handler));
+
   return method;
 }
 
diff --git a/src/class_linker.h b/src/class_linker.h
index 0b165334..f6b7c15 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -158,10 +158,10 @@
                         bool is_direct);
 
   Method* ResolveMethod(uint32_t method_idx, const Method* referrer, bool is_direct) {
-    Method* resolved_method = referrer->GetDexCacheResolvedMethods()->Get(method_idx);
+    Class* declaring_class = referrer->GetDeclaringClass();
+    DexCache* dex_cache = declaring_class->GetDexCache();
+    Method* resolved_method = dex_cache->GetResolvedMethod(method_idx);
     if (UNLIKELY(resolved_method == NULL)) {
-      Class* declaring_class = referrer->GetDeclaringClass();
-      DexCache* dex_cache = declaring_class->GetDexCache();
       const ClassLoader* class_loader = declaring_class->GetClassLoader();
       const DexFile& dex_file = FindDexFile(dex_cache);
       resolved_method = ResolveMethod(dex_file, method_idx, dex_cache, class_loader, is_direct);
@@ -282,6 +282,7 @@
   Class* CreateProxyClass(String* name, ObjectArray<Class>* interfaces, ClassLoader* loader,
                           ObjectArray<Method>* methods, ObjectArray<ObjectArray<Class> >* throws);
   std::string GetDescriptorForProxy(const Class* proxy_class);
+  Method* FindMethodForProxy(const Class* proxy_class, const Method* proxy_method);
 
   pid_t GetClassesLockOwner(); // For SignalCatcher.
   pid_t GetDexLockOwner(); // For SignalCatcher.
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index e9a94a9..9f63c5e 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -139,15 +139,12 @@
 
     EXPECT_TRUE(method->GetDexCacheStrings() != NULL);
     EXPECT_TRUE(method->GetDexCacheResolvedTypes() != NULL);
-    EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL);
     EXPECT_TRUE(method->GetDexCacheCodeAndDirectMethods() != NULL);
     EXPECT_TRUE(method->GetDexCacheInitializedStaticStorage() != NULL);
     EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetStrings(),
               method->GetDexCacheStrings());
     EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes(),
               method->GetDexCacheResolvedTypes());
-    EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods(),
-              method->GetDexCacheResolvedMethods());
     EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetCodeAndDirectMethods(),
               method->GetDexCacheCodeAndDirectMethods());
     EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetInitializedStaticStorage(),
@@ -446,7 +443,6 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, declaring_class_),                      "declaringClass"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_code_and_direct_methods_),    "dexCacheCodeAndDirectMethods"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_initialized_static_storage_), "dexCacheInitializedStaticStorage"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_methods_),           "dexCacheResolvedMethods"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_types_),             "dexCacheResolvedTypes"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_),                    "dexCacheStrings"));
 
diff --git a/src/java_lang_reflect_Method.cc b/src/java_lang_reflect_Method.cc
index 3be13ca..b32f815 100644
--- a/src/java_lang_reflect_Method.cc
+++ b/src/java_lang_reflect_Method.cc
@@ -50,9 +50,15 @@
   return AddLocalReference<jobject>(env, declared_exceptions->Clone());
 }
 
+jobject Method_findOverriddenMethod(JNIEnv* env, jobject javaMethod) {
+  Method* method = Decode<Object*>(env, javaMethod)->AsMethod();
+  return AddLocalReference<jobject>(env, method->FindOverriddenMethod());
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Method, invoke, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
   NATIVE_METHOD(Method, getExceptionTypesNative, "()[Ljava/lang/Class;"),
+  NATIVE_METHOD(Method, findOverriddenMethod, "()Ljava/lang/reflect/Method;"),
 };
 
 }  // namespace
diff --git a/src/object.cc b/src/object.cc
index bb87698..22ee742 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -355,16 +355,6 @@
                  new_dex_cache_classes, false);
 }
 
-ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
-  return GetFieldObject<ObjectArray<Method>*>(
-      OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
-}
-
-void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
-  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
-                 new_dex_cache_methods, false);
-}
-
 CodeAndDirectMethods* Method::GetDexCacheCodeAndDirectMethods() const {
   return GetFieldPtr<CodeAndDirectMethods*>(
       OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
@@ -421,18 +411,22 @@
     result = super_class_vtable->Get(method_index);
   } else {
     // Method didn't override superclass method so search interfaces
-    MethodHelper mh(this);
-    MethodHelper interface_mh;
-    ObjectArray<InterfaceEntry>* iftable = GetDeclaringClass()->GetIfTable();
-    for (int32_t i = 0; i < iftable->GetLength() && result == NULL; i++) {
-      InterfaceEntry* entry = iftable->Get(i);
-      Class* interface = entry->GetInterface();
-      for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-        Method* interface_method = interface->GetVirtualMethod(j);
-        interface_mh.ChangeMethod(interface_method);
-        if (mh.HasSameNameAndSignature(&interface_mh)) {
-          result = interface_method;
-          break;
+    if (IsProxyMethod()) {
+      result = Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this);
+    } else {
+      MethodHelper mh(this);
+      MethodHelper interface_mh;
+      ObjectArray<InterfaceEntry>* iftable = GetDeclaringClass()->GetIfTable();
+      for (int32_t i = 0; i < iftable->GetLength() && result == NULL; i++) {
+        InterfaceEntry* entry = iftable->Get(i);
+        Class* interface = entry->GetInterface();
+        for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
+          Method* interface_method = interface->GetVirtualMethod(j);
+          interface_mh.ChangeMethod(interface_method);
+          if (mh.HasSameNameAndSignature(&interface_mh)) {
+            result = interface_method;
+            break;
+          }
         }
       }
     }
diff --git a/src/object.h b/src/object.h
index 738d2b0..6092ce4 100644
--- a/src/object.h
+++ b/src/object.h
@@ -604,9 +604,6 @@
   ObjectArray<Class>* GetDexCacheResolvedTypes() const;
   void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types);
 
-  ObjectArray<Method>* GetDexCacheResolvedMethods() const;
-  void SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods);
-
   CodeAndDirectMethods* GetDexCacheCodeAndDirectMethods() const;
   void SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value);
 
@@ -792,10 +789,6 @@
     return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_);
   }
 
-  static MemberOffset GetDexCacheResolvedMethodsOffset() {
-    return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_);
-  }
-
   static MemberOffset GetMethodIndexOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
   }
@@ -868,9 +861,6 @@
   ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
 
   // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
-  ObjectArray<Method>* dex_cache_resolved_methods_;
-
-  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
   ObjectArray<Class>* dex_cache_resolved_types_;
 
   // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
diff --git a/src/object_utils.h b/src/object_utils.h
index e2d9b88..28b5ef6 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -561,7 +561,7 @@
     if (method != NULL) {
       Class* klass = method->GetDeclaringClass();
       if (klass->IsProxyClass()) {
-        method = method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
+        method = GetClassLinker()->FindMethodForProxy(klass, method);
         CHECK(method != NULL);
       }
     }
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 14b14e0..eb06df5 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1037,7 +1037,6 @@
     FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     Method* method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
-    referrer->GetDexCacheResolvedMethods()->Set(method_idx, method);
     return method;
 }