From 4f97a212b6ff801eb9f7f88a87f44e0584339cca Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Thu, 25 Feb 2016 16:17:54 +0000 Subject: [PATCH] Cleanup polymorphic inlining to the same target. - Don't do expensive lookups, just fetch the ArtMethods from the imtable or vtable. - Don't perform the optimization if we may end up in the conflicting trampoline. bug:27398183 Change-Id: I327c9f7c3a85d570a057ff8f18602e8e52402fdc --- compiler/optimizing/inliner.cc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index d55009554..494a6ee9c 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -603,6 +603,10 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, DCHECK(resolved_method != nullptr); ArtMethod* actual_method = nullptr; + size_t method_index = invoke_instruction->IsInvokeVirtual() + ? invoke_instruction->AsInvokeVirtual()->GetVTableIndex() + : invoke_instruction->AsInvokeInterface()->GetImtIndex(); + // Check whether we are actually calling the same method among // the different types seen. for (size_t i = 0; i < InlineCache::kIndividualCacheSize; ++i) { @@ -611,13 +615,18 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, } ArtMethod* new_method = nullptr; if (invoke_instruction->IsInvokeInterface()) { - new_method = ic.GetTypeAt(i)->FindVirtualMethodForInterface( - resolved_method, pointer_size); + new_method = ic.GetTypeAt(i)->GetEmbeddedImTableEntry( + method_index % mirror::Class::kImtSize, pointer_size); + if (new_method->IsRuntimeMethod()) { + // Bail out as soon as we see a conflict trampoline in one of the target's + // interface table. + return false; + } } else { DCHECK(invoke_instruction->IsInvokeVirtual()); - new_method = ic.GetTypeAt(i)->FindVirtualMethodForVirtual( - resolved_method, pointer_size); + new_method = ic.GetTypeAt(i)->GetEmbeddedVTableEntry(method_index, pointer_size); } + DCHECK(new_method != nullptr); if (actual_method == nullptr) { actual_method = new_method; } else if (actual_method != new_method) { @@ -641,10 +650,6 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, HInstanceFieldGet* receiver_class = BuildGetReceiverClass( class_linker, receiver, invoke_instruction->GetDexPc()); - size_t method_offset = invoke_instruction->IsInvokeVirtual() - ? actual_method->GetVtableIndex() - : invoke_instruction->AsInvokeInterface()->GetImtIndex(); - Primitive::Type type = Is64BitInstructionSet(graph_->GetInstructionSet()) ? Primitive::kPrimLong : Primitive::kPrimInt; @@ -653,7 +658,7 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, type, invoke_instruction->IsInvokeVirtual() ? HClassTableGet::TableKind::kVTable : HClassTableGet::TableKind::kIMTable, - method_offset, + method_index, invoke_instruction->GetDexPc()); HConstant* constant; -- 2.11.0