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,