From e828df143f5eefedfede026d8913b20725f528a0 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Mon, 18 Dec 2023 15:16:16 +0000 Subject: Always pass the receiver type. There were some missed opportunities when inlining, where we were not passing the type of the receiver, and so were not using it when doing local optimizations. Test: test.py Change-Id: I927be763590d7331db009a149090b7106a20b0db --- compiler/optimizing/inliner.cc | 44 +++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'compiler/optimizing') 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 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 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(); -- cgit v1.2.3-59-g8ed1b