Optimizing compiler support for directly calling interface methods

This teaches the optimizing compiler how to perform invoke-super on
interfaces. This should make the invokes generally faster.

Bug: 24618811

Change-Id: I7f9b0fb1209775c1c8837ab5d21f8acba3cc72a5
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index ea1afa8..7e8a4a4 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -116,6 +116,30 @@
   return resolved_method;
 }
 
+inline mirror::Class* ClassLinker::ResolveReferencedClassOfMethod(Thread* self,
+                                                                  uint32_t method_idx,
+                                                                  ArtMethod* referrer) {
+  // NB: We cannot simply use `GetResolvedMethod(method_idx, ...)->GetDeclaringClass()`. This is
+  // because if we did so than an invoke-super could be incorrectly dispatched in cases where
+  // GetMethodId(method_idx).class_idx_ refers to a non-interface, non-direct-superclass
+  // (super*-class?) of the referrer and the direct superclass of the referrer contains a concrete
+  // implementation of the method. If this class's implementation of the method is copied from an
+  // interface (either miranda, default or conflict) we would incorrectly assume that is what we
+  // want to invoke on, instead of the 'concrete' implementation that the direct superclass
+  // contains.
+  mirror::Class* declaring_class = referrer->GetDeclaringClass();
+  StackHandleScope<2> hs(self);
+  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
+  const DexFile* dex_file = h_dex_cache->GetDexFile();
+  const DexFile::MethodId& method = dex_file->GetMethodId(method_idx);
+  mirror::Class* resolved_type = h_dex_cache->GetResolvedType(method.class_idx_);
+  if (UNLIKELY(resolved_type == nullptr)) {
+    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
+    resolved_type = ResolveType(*dex_file, method.class_idx_, h_dex_cache, class_loader);
+  }
+  return resolved_type;
+}
+
 template <ClassLinker::ResolveMode kResolveMode>
 inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
                                              uint32_t method_idx,