summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r--compiler/optimizing/instruction_builder.cc19
1 files changed, 16 insertions, 3 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 4ae94b7b3f..1e7b48e4a5 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1002,14 +1002,27 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
resolved_method->GetMethodIndex());
} else {
DCHECK_EQ(invoke_type, kInterface);
- ScopedObjectAccess soa(Thread::Current()); // Needed for the IMT index.
- invoke = new (allocator_) HInvokeInterface(allocator_,
+ ScopedObjectAccess soa(Thread::Current()); // Needed for the IMT index and class check below.
+ if (resolved_method->GetDeclaringClass()->IsObjectClass()) {
+ // If the resolved method is from j.l.Object, emit a virtual call instead.
+ // The IMT conflict stub only handles interface methods.
+ invoke = new (allocator_) HInvokeVirtual(allocator_,
number_of_arguments,
return_type,
dex_pc,
method_idx,
resolved_method,
- ImTable::GetImtIndex(resolved_method));
+ resolved_method->GetMethodIndex());
+ } else {
+ DCHECK(resolved_method->GetDeclaringClass()->IsInterface());
+ invoke = new (allocator_) HInvokeInterface(allocator_,
+ number_of_arguments,
+ return_type,
+ dex_pc,
+ method_idx,
+ resolved_method,
+ ImTable::GetImtIndex(resolved_method));
+ }
}
return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false, clinit_check);
}