summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/inliner.cc44
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();