diff options
author | 2016-07-06 10:19:23 +0100 | |
---|---|---|
committer | 2016-07-06 13:30:13 +0100 | |
commit | d9faceaa8da92f4a56c2907de949081bd42faf79 (patch) | |
tree | 2efc00cfe8d5211e420174db81e732f8e92cbb33 /compiler/optimizing/inliner.cc | |
parent | 74c0d1bb67f9c6ee8306f0318ab7251d56dc99d6 (diff) |
Inline and optimize interface calls.
- Support for inlining methods with invoke-interface (the
previous performance limitation is now fixed with the new
ImtConflictTable).
- Turn non inlineable invoke-interface into invoke-virtual to
avoid any potential execution of the conflict trampoline.
test:609-checker-inline-interface
Change-Id: Ibe33bc945deaada8fb78541e6e0bf034ebb52420
Diffstat (limited to 'compiler/optimizing/inliner.cc')
-rw-r--r-- | compiler/optimizing/inliner.cc | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index c67b2d5fe9..8ee04dd396 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -750,7 +750,35 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, ArtMethod* method, bool do_rtp) { HInstruction* return_replacement = nullptr; if (!TryBuildAndInline(invoke_instruction, method, &return_replacement)) { - return false; + if (invoke_instruction->IsInvokeInterface()) { + // 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. + HInvokeVirtual* new_invoke = new (graph_->GetArena()) HInvokeVirtual( + graph_->GetArena(), + invoke_instruction->GetNumberOfArguments(), + invoke_instruction->GetType(), + invoke_instruction->GetDexPc(), + invoke_instruction->GetDexMethodIndex(), + method->GetMethodIndex()); + HInputsRef inputs = invoke_instruction->GetInputs(); + size_t index = 0; + for (HInstruction* instr : inputs) { + new_invoke->SetArgumentAt(index++, instr); + } + invoke_instruction->GetBlock()->InsertInstructionBefore(new_invoke, invoke_instruction); + new_invoke->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); + if (invoke_instruction->GetType() == Primitive::kPrimNot) { + new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo()); + } + return_replacement = new_invoke; + } else { + // TODO: Consider sharpening an invoke virtual once it is not dependent on the + // compiler driver. + return false; + } } if (return_replacement != nullptr) { invoke_instruction->ReplaceWith(return_replacement); @@ -1239,14 +1267,6 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, return false; } - if (current->IsInvokeInterface()) { - // Disable inlining of interface calls. The cost in case of entering the - // resolution conflict is currently too high. - VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) - << " could not be inlined because it has an interface call."; - return false; - } - if (!same_dex_file && current->NeedsEnvironment()) { VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) << " could not be inlined because " << current->DebugName() |