diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/bounds_check_elimination.cc | 11 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 9 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.h | 1 | ||||
-rw-r--r-- | compiler/optimizing/inliner.cc | 42 | ||||
-rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 6 |
5 files changed, 55 insertions, 14 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index 659c6f8497..b65e98a120 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -552,7 +552,11 @@ class BCEVisitor : public HGraphVisitor { DCHECK(!IsAddedBlock(block)); first_index_bounds_check_map_.clear(); HGraphVisitor::VisitBasicBlock(block); - AddComparesWithDeoptimization(block); + // We should never deoptimize from an osr method, otherwise we might wrongly optimize + // code dominated by the deoptimization. + if (!GetGraph()->IsCompilingOsr()) { + AddComparesWithDeoptimization(block); + } } void Finish() { @@ -1358,6 +1362,11 @@ class BCEVisitor : public HGraphVisitor { if (loop->IsIrreducible()) { return false; } + // We should never deoptimize from an osr method, otherwise we might wrongly optimize + // code dominated by the deoptimization. + if (GetGraph()->IsCompilingOsr()) { + return false; + } // A try boundary preheader is hard to handle. // TODO: remove this restriction. if (loop->GetPreHeader()->GetLastInstruction()->IsTryBoundary()) { diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 96837a8266..968e26724d 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -258,6 +258,15 @@ void GraphChecker::VisitBoundsCheck(HBoundsCheck* check) { VisitInstruction(check); } +void GraphChecker::VisitDeoptimize(HDeoptimize* deopt) { + if (GetGraph()->IsCompilingOsr()) { + AddError(StringPrintf("A graph compiled OSR cannot have a HDeoptimize instruction")); + } + + // Perform the instruction base checks too. + VisitInstruction(deopt); +} + void GraphChecker::VisitTryBoundary(HTryBoundary* try_boundary) { ArrayRef<HBasicBlock* const> handlers = try_boundary->GetExceptionHandlers(); diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index 83b198474c..3060c80073 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -57,6 +57,7 @@ class GraphChecker : public HGraphDelegateVisitor { void VisitCheckCast(HCheckCast* check) OVERRIDE; void VisitCondition(HCondition* op) OVERRIDE; void VisitConstant(HConstant* instruction) OVERRIDE; + void VisitDeoptimize(HDeoptimize* instruction) OVERRIDE; void VisitIf(HIf* instruction) OVERRIDE; void VisitInstanceOf(HInstanceOf* check) OVERRIDE; void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE; diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 836bcfa4c1..bb199cfa23 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -322,7 +322,13 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { return false; } else if (ic.IsMonomorphic()) { MaybeRecordStat(kMonomorphicCall); - return TryInlineMonomorphicCall(invoke_instruction, resolved_method, ic); + if (outermost_graph_->IsCompilingOsr()) { + // If we are compiling OSR, we pretend this call is polymorphic, as we may come from the + // interpreter and it may have seen different receiver types. + return TryInlinePolymorphicCall(invoke_instruction, resolved_method, ic); + } else { + return TryInlineMonomorphicCall(invoke_instruction, resolved_method, ic); + } } else if (ic.IsPolymorphic()) { MaybeRecordStat(kPolymorphicCall); return TryInlinePolymorphicCall(invoke_instruction, resolved_method, ic); @@ -510,6 +516,11 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, bool deoptimize = all_targets_inlined && (i != InlineCache::kIndividualCacheSize - 1) && (ic.GetTypeAt(i + 1) == nullptr); + + if (outermost_graph_->IsCompilingOsr()) { + // We do not support HDeoptimize in OSR methods. + deoptimize = false; + } HInstruction* compare = AddTypeGuard( receiver, cursor, bb_cursor, class_index, is_referrer, invoke_instruction, deoptimize); if (deoptimize) { @@ -672,7 +683,8 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, HInstruction* cursor = invoke_instruction->GetPrevious(); HBasicBlock* bb_cursor = invoke_instruction->GetBlock(); - if (!TryInlineAndReplace(invoke_instruction, actual_method, /* do_rtp */ false)) { + HInstruction* return_replacement = nullptr; + if (!TryBuildAndInline(invoke_instruction, actual_method, &return_replacement)) { return false; } @@ -701,9 +713,6 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, } HNotEqual* compare = new (graph_->GetArena()) HNotEqual(class_table_get, constant); - HDeoptimize* deoptimize = new (graph_->GetArena()) HDeoptimize( - compare, invoke_instruction->GetDexPc()); - // TODO: Extend reference type propagation to understand the guard. if (cursor != nullptr) { bb_cursor->InsertInstructionAfter(receiver_class, cursor); } else { @@ -711,8 +720,19 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, } bb_cursor->InsertInstructionAfter(class_table_get, receiver_class); bb_cursor->InsertInstructionAfter(compare, class_table_get); - bb_cursor->InsertInstructionAfter(deoptimize, compare); - deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); + + if (outermost_graph_->IsCompilingOsr()) { + CreateDiamondPatternForPolymorphicInline(compare, return_replacement, invoke_instruction); + } else { + // TODO: Extend reference type propagation to understand the guard. + HDeoptimize* deoptimize = new (graph_->GetArena()) HDeoptimize( + compare, invoke_instruction->GetDexPc()); + bb_cursor->InsertInstructionAfter(deoptimize, compare); + deoptimize->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); + if (return_replacement != nullptr) { + invoke_instruction->ReplaceWith(return_replacement); + } + } // Run type propagation to get the guard typed. ReferenceTypePropagation rtp_fixup(graph_, @@ -744,6 +764,12 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction, HInstruction** return_replacement) { const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); + if (method->IsProxyMethod()) { + VLOG(compiler) << "Method " << PrettyMethod(method) + << " is not inlined because of unimplemented inline support for proxy methods."; + return false; + } + // Check whether we're allowed to inline. The outermost compilation unit is the relevant // dex file here (though the transitivity of an inline chain would allow checking the calller). if (!compiler_driver_->MayInline(method->GetDexFile(), @@ -1260,6 +1286,8 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, size_t HInliner::RunOptimizations(HGraph* callee_graph, const DexFile::CodeItem* code_item, const DexCompilationUnit& dex_compilation_unit) { + // Note: if the outermost_graph_ is being compiled OSR, we should not run any + // optimization that could lead to a HDeoptimize. The following optimizations do not. HDeadCodeElimination dce(callee_graph, stats_); HConstantFolding fold(callee_graph); HSharpening sharpening(callee_graph, codegen_, dex_compilation_unit, compiler_driver_); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 04c9ff9d6d..6eebe7f79a 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -664,12 +664,6 @@ void ReferenceTypePropagation::VisitPhi(HPhi* phi) { } if (phi->GetBlock()->IsLoopHeader()) { - if (!is_first_run_ && graph_->IsCompilingOsr()) { - // Don't update the type of a loop phi when compiling OSR: we may have done - // speculative optimizations dominating that phi, that do not hold at the - // point the interpreter jumps to that loop header. - return; - } // Set the initial type for the phi. Use the non back edge input for reaching // a fixed point faster. HInstruction* first_input = phi->InputAt(0); |