Revert "Devirtualize to HInvokeStaticOrDirect."
This reverts commit 5024ddfd125b5c3b59d7f359ae33cf7f0255b048.
Bug: 187408838
Reason for revert: b/187408838
Change-Id: If74f5ddbacc73296f66c55762e2a8d1ec2cd1f19
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index f251817..611c691 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1240,22 +1240,32 @@
bool HInliner::TryDevirtualize(HInvoke* invoke_instruction,
ArtMethod* method,
HInvoke** replacement) {
+ DCHECK(!method->IsProxyMethod());
DCHECK(invoke_instruction != *replacement);
- if (!invoke_instruction->IsInvokeInterface() && !invoke_instruction->IsInvokeVirtual()) {
+ if (!invoke_instruction->IsInvokeInterface()) {
+ // TODO: Consider sharpening an invoke virtual once it is not dependent on the
+ // compiler driver.
return false;
}
+ // Devirtualization by exact type uses a method in the vtable, so we should
+ // not see a default non-copied method.
+ DCHECK(!method->IsDefault() || method->IsCopied());
+ // Turn an invoke-interface into an invoke-virtual. An invoke-virtual is always
+ // better than an invoke-interface because:
+ // 1) In the best case, the interface call has one more indirection (to fetch the IMT).
+ // 2) We will not go to the conflict trampoline with an invoke-virtual.
+ // TODO: Consider sharpening once it is not dependent on the compiler driver.
+
+ if (kIsDebugBuild && method->IsDefaultConflicting()) {
+ ReferenceTypeInfo receiver_type = invoke_instruction->InputAt(0)->GetReferenceTypeInfo();
+ // Devirtualization by exact type uses a method in the vtable,
+ // so it's OK to change this invoke into a HInvokeVirtual.
+ ObjPtr<mirror::Class> receiver_class = receiver_type.GetTypeHandle().Get();
+ CHECK(!receiver_class->IsInterface());
+ PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ CHECK(method == receiver_class->GetVTableEntry(method->GetMethodIndex(), pointer_size));
+ }
- // Don't bother trying to call directly a default conflict method. It
- // doesn't have a proper MethodReference, but also `GetCanonicalMethod`
- // will return an actual default implementation.
- if (method->IsDefaultConflicting()) {
- return false;
- }
- DCHECK(!method->IsProxyMethod());
- ClassLinker* cl = Runtime::Current()->GetClassLinker();
- PointerSize pointer_size = cl->GetImagePointerSize();
- // The sharpening logic assumes the caller isn't passing a copied method.
- method = method->GetCanonicalMethod(pointer_size);
uint32_t dex_method_index = FindMethodIndexIn(
method,
*invoke_instruction->GetMethodReference().dex_file,
@@ -1263,32 +1273,19 @@
if (dex_method_index == dex::kDexNoIndex) {
return false;
}
- HInvokeStaticOrDirect::DispatchInfo dispatch_info =
- HSharpening::SharpenLoadMethod(method,
- /* has_method_id= */ true,
- /* for_interface_call= */ false,
- codegen_);
- DCHECK_NE(dispatch_info.code_ptr_location, CodePtrLocation::kCallCriticalNative);
- HInvokeStaticOrDirect* new_invoke = new (graph_->GetAllocator()) HInvokeStaticOrDirect(
+ HInvokeVirtual* new_invoke = new (graph_->GetAllocator()) HInvokeVirtual(
graph_->GetAllocator(),
invoke_instruction->GetNumberOfArguments(),
invoke_instruction->GetType(),
invoke_instruction->GetDexPc(),
MethodReference(invoke_instruction->GetMethodReference().dex_file, dex_method_index),
method,
- dispatch_info,
- kDirect,
MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ method->GetMethodIndex());
HInputsRef inputs = invoke_instruction->GetInputs();
- DCHECK_EQ(inputs.size(), invoke_instruction->GetNumberOfArguments());
for (size_t index = 0; index != inputs.size(); ++index) {
new_invoke->SetArgumentAt(index, inputs[index]);
}
- if (HInvokeStaticOrDirect::NeedsCurrentMethodInput(dispatch_info)) {
- new_invoke->SetRawInputAt(new_invoke->GetCurrentMethodIndexUnchecked(),
- graph_->GetCurrentMethod());
- }
invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction);
new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment());
if (invoke_instruction->GetType() == DataType::Type::kReference) {