Handle more cases of super calls in the compiler.

Add support for calling super methods that are not referenced within the
compiling dex file.

Test: 808-checker-invoke-super
Test: 809-checker-invoke-super-bss
Change-Id: Ib103f818ac8b612a79b6b18cc8eda81131bb3149
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 3401e65..9fb9c4e 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -957,18 +957,6 @@
       actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
           vtable_index, class_linker->GetImagePointerSize());
     }
-    if (actual_method != resolved_method &&
-        !IsSameDexFile(*actual_method->GetDexFile(), *dex_compilation_unit.GetDexFile())) {
-      // The back-end code generator relies on this check in order to ensure that it will not
-      // attempt to read the dex_cache with a dex_method_index that is not from the correct
-      // dex_file. If we didn't do this check then the dex_method_index will not be updated in the
-      // builder, which means that the code-generator (and sharpening and inliner, maybe)
-      // might invoke an incorrect method.
-      // TODO: The actual method could still be referenced in the current dex file, so we
-      //       could try locating it.
-      // TODO: Remove the dex_file restriction.
-      return nullptr;
-    }
     if (!actual_method->IsInvokable()) {
       // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
       // could resolve the callee to the wrong method.
@@ -1092,15 +1080,31 @@
 
   HInvoke* invoke = nullptr;
   if (invoke_type == kDirect || invoke_type == kStatic || invoke_type == kSuper) {
+    // For sharpening, we create another MethodReference, to account for the
+    // kSuper case below where we cannot find a dex method index.
+    bool has_method_id = true;
     if (invoke_type == kSuper) {
+      uint32_t dex_method_index = method_reference.index;
       if (IsSameDexFile(*method_info.dex_file, *dex_compilation_unit_->GetDexFile())) {
         // Update the method index to the one resolved. Note that this may be a no-op if
         // we resolved to the method referenced by the instruction.
-        method_reference.index = method_info.index;
+        dex_method_index = method_info.index;
+      } else {
+        // Try to find a dex method index in this caller's dex file.
+        ScopedObjectAccess soa(Thread::Current());
+        dex_method_index = resolved_method->FindDexMethodIndexInOtherDexFile(
+            *dex_compilation_unit_->GetDexFile(), method_idx);
+      }
+      if (dex_method_index == dex::kDexNoIndex) {
+        has_method_id = false;
+      } else {
+        method_reference.index = dex_method_index;
       }
     }
     HInvokeStaticOrDirect::DispatchInfo dispatch_info =
-        HSharpening::SharpenInvokeStaticOrDirect(resolved_method, code_generator_);
+        HSharpening::SharpenInvokeStaticOrDirect(resolved_method,
+                                                 has_method_id,
+                                                 code_generator_);
     if (dispatch_info.code_ptr_location ==
             HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative) {
       graph_->SetHasDirectCriticalNativeCall(true);
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index d586306..d616912 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2310,7 +2310,8 @@
       // the invoke, as we would need to look it up in the current dex file, and it
       // is unlikely that it exists. The most usual situation for such typed
       // arraycopy methods is a direct pointer to the boot image.
-      invoke->SetDispatchInfo(HSharpening::SharpenInvokeStaticOrDirect(method, codegen_));
+      invoke->SetDispatchInfo(
+          HSharpening::SharpenInvokeStaticOrDirect(method, /* has_method_id= */ true, codegen_));
     }
   }
 }
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 04a8eab..f658f8a 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -58,7 +58,7 @@
 }
 
 HInvokeStaticOrDirect::DispatchInfo HSharpening::SharpenInvokeStaticOrDirect(
-    ArtMethod* callee, CodeGenerator* codegen) {
+    ArtMethod* callee, bool has_method_id, CodeGenerator* codegen) {
   if (kIsDebugBuild) {
     ScopedObjectAccess soa(Thread::Current());  // Required for GetDeclaringClass below.
     DCHECK(callee != nullptr);
@@ -96,6 +96,8 @@
       method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
     } else if (BootImageAOTCanEmbedMethod(callee, compiler_options)) {
       method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative;
+    } else if (!has_method_id) {
+      method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
     } else {
       // Use PC-relative access to the .bss methods array.
       method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
@@ -118,6 +120,9 @@
     // Use PC-relative access to the .data.bimg.rel.ro methods array.
     method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo;
     code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
+  } else if (!has_method_id) {
+    method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall;
+    code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
   } else {
     // Use PC-relative access to the .bss methods array.
     method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h
index b818672..b48cd4b 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -31,7 +31,7 @@
  public:
   // Used by the builder and InstructionSimplifier.
   static HInvokeStaticOrDirect::DispatchInfo SharpenInvokeStaticOrDirect(
-      ArtMethod* callee, CodeGenerator* codegen);
+      ArtMethod* callee, bool has_method_id, CodeGenerator* codegen);
 
   // Used by the builder and the inliner.
   static HLoadClass::LoadKind ComputeLoadClassKind(HLoadClass* load_class,