Revert^3 "ART: Use proxy ArtMethod's data_ to store the interface method.""

Still failling:

+dalvikvm64 F 08-15 18:54:16 218912 218912 art_method-inl.h:395] Check failed: !GetDeclaringClass()->IsResolved() || interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()) 


This reverts commit c42fab35f18539957debb8703195eeb76c9718f7.

Change-Id: I91b51f8c1e7f6e0ae876b751d8e9cd3b8acb62f6
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 0f5ffa0..50e9144 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -388,11 +388,17 @@
   if (LIKELY(!IsProxyMethod())) {
     return this;
   }
-  ArtMethod* interface_method = reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
-  // We can check that the proxy class implements the interface only if the proxy class
-  // is resolved, otherwise the interface table is not yet initialized.
-  DCHECK(!GetDeclaringClass()->IsResolved() ||
-         interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass()));
+  uint32_t method_index = GetDexMethodIndex();
+  uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize;
+  mirror::MethodDexCachePair pair = mirror::DexCache::GetNativePairPtrSize(
+      GetDexCacheResolvedMethods(pointer_size), slot_idx, pointer_size);
+  ArtMethod* interface_method = pair.GetObjectForIndex(method_index);
+  if (LIKELY(interface_method != nullptr)) {
+    DCHECK_EQ(interface_method, Runtime::Current()->GetClassLinker()->FindMethodForProxy(this));
+  } else {
+    interface_method = Runtime::Current()->GetClassLinker()->FindMethodForProxy(this);
+    DCHECK(interface_method != nullptr);
+  }
   return interface_method;
 }
 
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 7ffd585..cac40e0 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -458,15 +458,12 @@
     SetDataPtrSize(table, pointer_size);
   }
 
-  ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) {
+  ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) {
     // Don't do a read barrier in the DCHECK, as GetProfilingInfo is called in places
     // where the declaring class is treated as a weak reference (accessing it with
     // a read barrier would either prevent unloading the class, or crash the runtime if
     // the GC wants to unload it).
     DCHECK(!IsNative<kWithoutReadBarrier>());
-    if (UNLIKELY(IsProxyMethod())) {
-      return nullptr;
-    }
     return reinterpret_cast<ProfilingInfo*>(GetDataPtrSize(pointer_size));
   }
 
@@ -729,13 +726,9 @@
     // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
     mirror::MethodDexCacheType* dex_cache_resolved_methods_;
 
-    // Depending on the method type, the data is
-    //   - native method: pointer to the JNI function registered to this method
-    //                    or a function to resolve the JNI function,
-    //   - conflict method: ImtConflictTable,
-    //   - abstract/interface method: the single-implementation if any,
-    //   - proxy method: the original interface method or constructor,
-    //   - other methods: the profiling data.
+    // Pointer to JNI function registered to this method, or a function to resolve the JNI function,
+    // or the profiling data for non-native methods, or an ImtConflictTable, or the
+    // single-implementation of an abstract/interface method.
     void* data_;
 
     // Method dispatch from quick compiled code invokes this pointer which may cause bridging into
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0efc004..845bd6d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3552,6 +3552,7 @@
   DexCacheData data;
   data.weak_root = dex_cache_jweak;
   data.dex_file = dex_cache->GetDexFile();
+  data.resolved_methods = dex_cache->GetResolvedMethods();
   data.class_table = ClassTableForClassLoader(class_loader);
   DCHECK(data.class_table != nullptr);
   // Make sure to hold the dex cache live in the class table. This case happens for the boot class
@@ -4667,9 +4668,6 @@
                       kAccPublic |
                       kAccCompileDontBother);
   out->SetDeclaringClass(klass.Get());
-
-  // Set the original constructor method.
-  out->SetDataPtrSize(proxy_constructor, image_pointer_size_);
 }
 
 void ClassLinker::CheckProxyConstructor(ArtMethod* constructor) const {
@@ -4710,9 +4708,6 @@
   // method they copy might (if it's a default method).
   out->SetCodeItemOffset(0);
 
-  // Set the original interface method.
-  out->SetDataPtrSize(prototype, image_pointer_size_);
-
   // At runtime the method looks like a reference and argument saving method, clone the code
   // related parameters from this method.
   out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
@@ -9036,6 +9031,53 @@
                              ifcount * mirror::IfTable::kMax));
 }
 
+ArtMethod* ClassLinker::FindMethodForProxy(ArtMethod* proxy_method) {
+  DCHECK(proxy_method->IsProxyMethod());
+  {
+    uint32_t method_index = proxy_method->GetDexMethodIndex();
+    PointerSize pointer_size = image_pointer_size_;
+    Thread* const self = Thread::Current();
+    ReaderMutexLock mu(self, *Locks::dex_lock_);
+    // Locate the dex cache of the original interface/Object
+    for (const DexCacheData& data : dex_caches_) {
+      if (!self->IsJWeakCleared(data.weak_root) &&
+          proxy_method->HasSameDexCacheResolvedMethods(data.resolved_methods, pointer_size)) {
+        ObjPtr<mirror::DexCache> dex_cache =
+            ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
+        if (dex_cache != nullptr) {
+          // Lookup up the method. Instead of going through LookupResolvedMethod()
+          // and thus LookupResolvedType(), use the ClassTable from the DexCacheData.
+          ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_index, pointer_size);
+          if (resolved_method == nullptr) {
+            const DexFile::MethodId& method_id = data.dex_file->GetMethodId(method_index);
+            ObjPtr<mirror::Class> klass = dex_cache->GetResolvedType(method_id.class_idx_);
+            if (klass == nullptr) {
+              const char* descriptor = data.dex_file->StringByTypeIdx(method_id.class_idx_);
+              klass = data.class_table->Lookup(descriptor, ComputeModifiedUtf8Hash(descriptor));
+              DCHECK(klass != nullptr);
+              dex_cache->SetResolvedType(method_id.class_idx_, klass);
+            }
+            if (klass->IsInterface()) {
+              resolved_method = klass->FindInterfaceMethod(dex_cache, method_index, pointer_size);
+            } else {
+              DCHECK(
+                  klass == WellKnownClasses::ToClass(WellKnownClasses::java_lang_reflect_Proxy) ||
+                  klass == WellKnownClasses::ToClass(WellKnownClasses::java_lang_Object));
+              resolved_method = klass->FindClassMethod(dex_cache, method_index, pointer_size);
+            }
+            CHECK(resolved_method != nullptr);
+            dex_cache->SetResolvedMethod(method_index, resolved_method, pointer_size);
+          }
+          return resolved_method;
+        }
+      }
+    }
+  }
+  // Note: Do not use proxy_method->PrettyMethod() as it can call back here.
+  LOG(FATAL) << "Didn't find dex cache for " << proxy_method->GetDeclaringClass()->PrettyClass();
+  UNREACHABLE();
+}
+
 // Instantiate ResolveMethod.
 template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
     const DexFile& dex_file,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 783ec74..66bcbe0 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -479,6 +479,9 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   std::string GetDescriptorForProxy(ObjPtr<mirror::Class> proxy_class)
       REQUIRES_SHARED(Locks::mutator_lock_);
+  ArtMethod* FindMethodForProxy(ArtMethod* proxy_method)
+      REQUIRES(!Locks::dex_lock_)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Get the oat code for a method when its class isn't yet initialized.
   const void* GetQuickOatCodeFor(ArtMethod* method)
@@ -672,6 +675,7 @@
     DexCacheData()
         : weak_root(nullptr),
           dex_file(nullptr),
+          resolved_methods(nullptr),
           class_table(nullptr) { }
 
     // Check if the data is valid.
@@ -682,9 +686,11 @@
     // Weak root to the DexCache. Note: Do not decode this unnecessarily or else class unloading may
     // not work properly.
     jweak weak_root;
-    // The following field caches the DexCache's field here to avoid unnecessary jweak decode that
-    // triggers read barriers (and marks them alive unnecessarily and messes with class unloading.)
+    // The following two fields are caches to the DexCache's fields and here to avoid unnecessary
+    // jweak decode that triggers read barriers (and mark them alive unnecessarily and mess with
+    // class unloading.)
     const DexFile* dex_file;
+    mirror::MethodDexCacheType* resolved_methods;
     // Identify the associated class loader's class table. This is used to make sure that
     // the Java call to native DexCache.setResolvedType() inserts the resolved type in that
     // class table. It is also used to make sure we don't register the same dex cache with
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 40a5212..47ace7f 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -1169,6 +1169,7 @@
   RemoveUnmarkedCode(self);
 
   if (collect_profiling_info) {
+    ScopedThreadSuspension sts(self, kSuspended);
     MutexLock mu(self, lock_);
     // Free all profiling infos of methods not compiled nor being compiled.
     auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(),
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 9790e3a..daa1d61 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -323,8 +323,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   bool CheckLiveCompiledCodeHasProfilingInfo()
-      REQUIRES(lock_)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+      REQUIRES(lock_);
 
   void FreeCode(uint8_t* code) REQUIRES(lock_);
   uint8_t* AllocateCode(size_t code_size) REQUIRES(lock_);