diff options
Diffstat (limited to 'compiler/optimizing/inliner.cc')
-rw-r--r-- | compiler/optimizing/inliner.cc | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index c67b2d5fe9..f9e78b0a8f 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -187,12 +187,12 @@ static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke, ArtMethod* resol static uint32_t FindMethodIndexIn(ArtMethod* method, const DexFile& dex_file, - uint32_t referrer_index) + uint32_t name_and_signature_index) SHARED_REQUIRES(Locks::mutator_lock_) { if (IsSameDexFile(*method->GetDexFile(), dex_file)) { return method->GetDexMethodIndex(); } else { - return method->FindDexMethodIndexInOtherDexFile(dex_file, referrer_index); + return method->FindDexMethodIndexInOtherDexFile(dex_file, name_and_signature_index); } } @@ -750,7 +750,40 @@ 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. + const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); + uint32_t method_index = FindMethodIndexIn( + method, caller_dex_file, invoke_instruction->GetDexMethodIndex()); + if (method_index == DexFile::kDexNoIndex) { + return false; + } + HInvokeVirtual* new_invoke = new (graph_->GetArena()) HInvokeVirtual( + graph_->GetArena(), + invoke_instruction->GetNumberOfArguments(), + invoke_instruction->GetType(), + invoke_instruction->GetDexPc(), + method_index, + method->GetMethodIndex()); + HInputsRef inputs = invoke_instruction->GetInputs(); + for (size_t index = 0; index != inputs.size(); ++index) { + new_invoke->SetArgumentAt(index, inputs[index]); + } + 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 +1272,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() |