diff options
author | 2023-12-18 15:16:16 +0000 | |
---|---|---|
committer | 2023-12-19 10:54:54 +0000 | |
commit | e828df143f5eefedfede026d8913b20725f528a0 (patch) | |
tree | a2082e3eab128e88cea7245e770bf5035e1dd2a6 /compiler/optimizing | |
parent | c6371b52df0da31acc174a3526274417b7aac0a7 (diff) |
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
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(); |