diff options
Diffstat (limited to 'compiler/optimizing/inliner.cc')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 58 | 
1 files changed, 48 insertions, 10 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index b2ad8ec400..035e5ce3e1 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -392,6 +392,35 @@ ArtMethod* HInliner::TryCHADevirtualization(ArtMethod* resolved_method) {    return single_impl;  } +static bool AlwaysThrows(ArtMethod* method) +    REQUIRES_SHARED(Locks::mutator_lock_) { +  CodeItemDataAccessor accessor(method->DexInstructionData()); +  // Skip native methods, methods with try blocks, and methods that are too large. +  if (!accessor.HasCodeItem() || +      accessor.TriesSize() != 0 || +      accessor.InsnsSizeInCodeUnits() > kMaximumNumberOfTotalInstructions) { +    return false; +  } +  // Scan for exits. +  bool throw_seen = false; +  for (const DexInstructionPcPair& pair : accessor) { +    switch (pair.Inst().Opcode()) { +      case Instruction::RETURN: +      case Instruction::RETURN_VOID: +      case Instruction::RETURN_WIDE: +      case Instruction::RETURN_OBJECT: +      case Instruction::RETURN_VOID_NO_BARRIER: +        return false;  // found regular control flow back +      case Instruction::THROW: +        throw_seen = true; +        break; +      default: +        break; +    } +  } +  return throw_seen; +} +  bool HInliner::TryInline(HInvoke* invoke_instruction) {    if (invoke_instruction->IsInvokeUnresolved() ||        invoke_instruction->IsInvokePolymorphic()) { @@ -431,20 +460,29 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) {    }    if (actual_method != nullptr) { +    // Single target.      bool result = TryInlineAndReplace(invoke_instruction,                                        actual_method,                                        ReferenceTypeInfo::CreateInvalid(),                                        /* do_rtp */ true,                                        cha_devirtualize); -    if (result && !invoke_instruction->IsInvokeStaticOrDirect()) { -      if (cha_devirtualize) { -        // Add dependency due to devirtulization. We've assumed resolved_method -        // has single implementation. -        outermost_graph_->AddCHASingleImplementationDependency(resolved_method); -        MaybeRecordStat(stats_, MethodCompilationStat::kCHAInline); -      } else { -        MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface); +    if (result) { +      // Successfully inlined. +      if (!invoke_instruction->IsInvokeStaticOrDirect()) { +        if (cha_devirtualize) { +          // Add dependency due to devirtualization. We've assumed resolved_method +          // has single implementation. +          outermost_graph_->AddCHASingleImplementationDependency(resolved_method); +          MaybeRecordStat(stats_, MethodCompilationStat::kCHAInline); +        } else { +          MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface); +        }        } +    } else if (!cha_devirtualize && AlwaysThrows(actual_method)) { +      // Set always throws property for non-inlined method call with single target +      // (unless it was obtained through CHA, because that would imply we have +      // to add the CHA dependency, which seems not worth it). +      invoke_instruction->SetAlwaysThrows(true);      }      return result;    } @@ -1381,7 +1419,7 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,    bool same_dex_file = IsSameDexFile(*outer_compilation_unit_.GetDexFile(), *method->GetDexFile()); -  CodeItemDataAccessor accessor(method); +  CodeItemDataAccessor accessor(method->DexInstructionData());    if (!accessor.HasCodeItem()) {      LOG_FAIL_NO_STAT() @@ -1660,7 +1698,7 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,    const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();    const DexFile& callee_dex_file = *resolved_method->GetDexFile();    uint32_t method_index = resolved_method->GetDexMethodIndex(); -  CodeItemDebugInfoAccessor code_item_accessor(callee_dex_file, code_item); +  CodeItemDebugInfoAccessor code_item_accessor(resolved_method->DexInstructionDebugInfo());    ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();    Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),                                                              caller_compilation_unit_.GetDexCache(),  |