diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/inliner.cc | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index f65941090d..66a536d33b 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -228,7 +228,7 @@ static bool IsMethodOrDeclaringClassFinal(ArtMethod* method) * the actual runtime target of an interface or virtual call. * Return nullptr if the runtime target cannot be proven. */ -static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke) +static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke, ReferenceTypeInfo info) REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* resolved_method = invoke->GetResolvedMethod(); if (IsMethodOrDeclaringClassFinal(resolved_method)) { @@ -236,14 +236,6 @@ static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke) return resolved_method; } - HInstruction* receiver = invoke->InputAt(0); - if (receiver->IsNullCheck()) { - // Due to multiple levels of inlining within the same pass, it might be that - // null check does not have the reference type of the actual receiver. - receiver = receiver->InputAt(0); - } - ReferenceTypeInfo info = receiver->GetReferenceTypeInfo(); - DCHECK(info.IsValid()) << "Invalid RTI for " << receiver->DebugName(); if (!info.IsExact()) { // We currently only support inlining with known receivers. // TODO: Remove this check, we should be able to inline final methods @@ -477,15 +469,31 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { return false; } - ArtMethod* actual_method = invoke_instruction->IsInvokeStaticOrDirect() - ? invoke_instruction->GetResolvedMethod() - : FindVirtualOrInterfaceTarget(invoke_instruction); + ArtMethod* actual_method = nullptr; + ReferenceTypeInfo receiver_info = ReferenceTypeInfo::CreateInvalid(); + if (invoke_instruction->GetInvokeType() == kStatic) { + actual_method = invoke_instruction->GetResolvedMethod(); + } else { + HInstruction* receiver = invoke_instruction->InputAt(0); + while (receiver->IsNullCheck()) { + // Due to multiple levels of inlining within the same pass, it might be that + // null check does not have the reference type of the actual receiver. + receiver = receiver->InputAt(0); + } + receiver_info = receiver->GetReferenceTypeInfo(); + DCHECK(receiver_info.IsValid()) << "Invalid RTI for " << receiver->DebugName(); + if (invoke_instruction->IsInvokeStaticOrDirect()) { + actual_method = invoke_instruction->GetResolvedMethod(); + } else { + actual_method = FindVirtualOrInterfaceTarget(invoke_instruction, receiver_info); + } + } if (actual_method != nullptr) { // Single target. bool result = TryInlineAndReplace(invoke_instruction, actual_method, - ReferenceTypeInfo::CreateInvalid(), + receiver_info, /* do_rtp= */ true, /* is_speculative= */ false); if (result) { @@ -546,9 +554,10 @@ bool HInliner::TryInlineFromCHA(HInvoke* invoke_instruction) { uint32_t dex_pc = invoke_instruction->GetDexPc(); HInstruction* cursor = invoke_instruction->GetPrevious(); HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); + Handle<mirror::Class> cls = graph_->GetHandleCache()->NewHandle(method->GetDeclaringClass()); if (!TryInlineAndReplace(invoke_instruction, method, - ReferenceTypeInfo::CreateInvalid(), + ReferenceTypeInfo::Create(cls), /* do_rtp= */ true, /* is_speculative= */ true)) { return false; @@ -1191,9 +1200,11 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget( HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); HInstruction* return_replacement = nullptr; + Handle<mirror::Class> cls = + graph_->GetHandleCache()->NewHandle(actual_method->GetDeclaringClass()); if (!TryBuildAndInline(invoke_instruction, actual_method, - ReferenceTypeInfo::CreateInvalid(), + ReferenceTypeInfo::Create(cls), &return_replacement, /* is_speculative= */ true)) { return false; @@ -2069,7 +2080,8 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, ReferenceTypeInfo receiver_type, HInstruction** return_replacement, bool is_speculative) { - DCHECK(!(resolved_method->IsStatic() && receiver_type.IsValid())); + DCHECK_IMPLIES(resolved_method->IsStatic(), !receiver_type.IsValid()); + DCHECK_IMPLIES(!resolved_method->IsStatic(), receiver_type.IsValid()); const dex::CodeItem* code_item = resolved_method->GetCodeItem(); const DexFile& callee_dex_file = *resolved_method->GetDexFile(); uint32_t method_index = resolved_method->GetDexMethodIndex(); |