diff options
Diffstat (limited to 'compiler/optimizing/inliner.cc')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 8d93867230..d84787984d 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -480,13 +480,11 @@ bool HInliner::TryInlineMonomorphicCall(HInvoke* invoke_instruction, } // We successfully inlined, now add a guard. - bool is_referrer = - (GetMonomorphicType(classes) == outermost_graph_->GetArtMethod()->GetDeclaringClass()); AddTypeGuard(receiver, cursor, bb_cursor, class_index, - is_referrer, + GetMonomorphicType(classes), invoke_instruction, /* with_deoptimization */ true); @@ -506,52 +504,62 @@ void HInliner::AddCHAGuard(HInstruction* invoke_instruction, uint32_t dex_pc, HInstruction* cursor, HBasicBlock* bb_cursor) { - HInstruction* deopt_flag = new (graph_->GetArena()) HShouldDeoptimizeFlag(dex_pc); - HInstruction* should_deopt = new (graph_->GetArena()) HNotEqual( + HShouldDeoptimizeFlag* deopt_flag = new (graph_->GetArena()) + HShouldDeoptimizeFlag(graph_->GetArena(), dex_pc); + HInstruction* compare = new (graph_->GetArena()) HNotEqual( deopt_flag, graph_->GetIntConstant(0, dex_pc)); - HInstruction* deopt = new (graph_->GetArena()) HDeoptimize(should_deopt, dex_pc); + HInstruction* deopt = new (graph_->GetArena()) HDeoptimize(compare, dex_pc); if (cursor != nullptr) { bb_cursor->InsertInstructionAfter(deopt_flag, cursor); } else { bb_cursor->InsertInstructionBefore(deopt_flag, bb_cursor->GetFirstInstruction()); } - bb_cursor->InsertInstructionAfter(should_deopt, deopt_flag); - bb_cursor->InsertInstructionAfter(deopt, should_deopt); + bb_cursor->InsertInstructionAfter(compare, deopt_flag); + bb_cursor->InsertInstructionAfter(deopt, compare); + + // Add receiver as input to aid CHA guard optimization later. + deopt_flag->AddInput(invoke_instruction->InputAt(0)); + DCHECK_EQ(deopt_flag->InputCount(), 1u); deopt->CopyEnvironmentFrom(invoke_instruction->GetEnvironment()); + outermost_graph_->IncrementNumberOfCHAGuards(); } HInstruction* HInliner::AddTypeGuard(HInstruction* receiver, HInstruction* cursor, HBasicBlock* bb_cursor, dex::TypeIndex class_index, - bool is_referrer, + mirror::Class* klass, HInstruction* invoke_instruction, bool with_deoptimization) { + ScopedAssertNoThreadSuspension sants("Adding compiler type guard"); + ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker(); HInstanceFieldGet* receiver_class = BuildGetReceiverClass( class_linker, receiver, invoke_instruction->GetDexPc()); + if (cursor != nullptr) { + bb_cursor->InsertInstructionAfter(receiver_class, cursor); + } else { + bb_cursor->InsertInstructionBefore(receiver_class, bb_cursor->GetFirstInstruction()); + } const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); + bool is_referrer = (klass == outermost_graph_->GetArtMethod()->GetDeclaringClass()); // Note that we will just compare the classes, so we don't need Java semantics access checks. - // Also, the caller of `AddTypeGuard` must have guaranteed that the class is in the dex cache. + // Note that the type index and the dex file are relative to the method this type guard is + // inlined into. HLoadClass* load_class = new (graph_->GetArena()) HLoadClass(graph_->GetCurrentMethod(), class_index, caller_dex_file, is_referrer, invoke_instruction->GetDexPc(), - /* needs_access_check */ false, - /* is_in_dex_cache */ true, - /* is_in_boot_image */ false); + /* needs_access_check */ false); + bb_cursor->InsertInstructionAfter(load_class, receiver_class); + // Sharpen after adding the instruction, as the sharpening may remove inputs. + HSharpening::SharpenClass(load_class, klass, handles_, codegen_, compiler_driver_); - HNotEqual* compare = new (graph_->GetArena()) HNotEqual(load_class, receiver_class); // TODO: Extend reference type propagation to understand the guard. - if (cursor != nullptr) { - bb_cursor->InsertInstructionAfter(receiver_class, cursor); - } else { - bb_cursor->InsertInstructionBefore(receiver_class, bb_cursor->GetFirstInstruction()); - } - bb_cursor->InsertInstructionAfter(load_class, receiver_class); + HNotEqual* compare = new (graph_->GetArena()) HNotEqual(load_class, receiver_class); bb_cursor->InsertInstructionAfter(compare, load_class); if (with_deoptimization) { HDeoptimize* deoptimize = new (graph_->GetArena()) HDeoptimize( @@ -604,7 +612,6 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, all_targets_inlined = false; } else { one_target_inlined = true; - bool is_referrer = (classes->Get(i) == outermost_graph_->GetArtMethod()->GetDeclaringClass()); // If we have inlined all targets before, and this receiver is the last seen, // we deoptimize instead of keeping the original invoke instruction. @@ -616,8 +623,13 @@ bool HInliner::TryInlinePolymorphicCall(HInvoke* invoke_instruction, // We do not support HDeoptimize in OSR methods. deoptimize = false; } - HInstruction* compare = AddTypeGuard( - receiver, cursor, bb_cursor, class_index, is_referrer, invoke_instruction, deoptimize); + HInstruction* compare = AddTypeGuard(receiver, + cursor, + bb_cursor, + class_index, + classes->Get(i), + invoke_instruction, + deoptimize); if (deoptimize) { if (return_replacement != nullptr) { invoke_instruction->ReplaceWith(return_replacement); @@ -1444,7 +1456,7 @@ size_t HInliner::RunOptimizations(HGraph* callee_graph, // optimization that could lead to a HDeoptimize. The following optimizations do not. HDeadCodeElimination dce(callee_graph, stats_, "dead_code_elimination$inliner"); HConstantFolding fold(callee_graph, "constant_folding$inliner"); - HSharpening sharpening(callee_graph, codegen_, dex_compilation_unit, compiler_driver_); + HSharpening sharpening(callee_graph, codegen_, dex_compilation_unit, compiler_driver_, handles_); InstructionSimplifier simplify(callee_graph, stats_); IntrinsicsRecognizer intrinsics(callee_graph, stats_); |