diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/inliner.cc | 111 | ||||
| -rw-r--r-- | compiler/optimizing/inliner.h | 5 | ||||
| -rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 12 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 17 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.h | 7 |
5 files changed, 21 insertions, 131 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 07d0dd6b49..5c73fd8696 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -27,7 +27,6 @@ #include "mirror/class_loader.h" #include "mirror/dex_cache.h" #include "nodes.h" -#include "reference_type_propagation.h" #include "register_allocator.h" #include "ssa_phi_elimination.h" #include "scoped_thread_state_change.h" @@ -58,7 +57,7 @@ void HInliner::Run() { next_block = (i == blocks.Size() - 1) ? nullptr : blocks.Get(i + 1); for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) { HInstruction* next = instruction->GetNext(); - HInvoke* call = instruction->AsInvoke(); + HInvokeStaticOrDirect* call = instruction->AsInvokeStaticOrDirect(); // As long as the call is not intrinsified, it is worth trying to inline. if (call != nullptr && call->GetIntrinsic() == Intrinsics::kNone) { // We use the original invoke type to ensure the resolution of the called method @@ -84,82 +83,6 @@ void HInliner::Run() { } } -static bool IsMethodOrDeclaringClassFinal(ArtMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return method->IsFinal() || method->GetDeclaringClass()->IsFinal(); -} - -/** - * Given the `resolved_method` looked up in the dex cache, try to find - * the actual runtime target of an interface or virtual call. - * Return nullptr if the runtime target cannot be proven. - */ -static ArtMethod* FindVirtualOrInterfaceTarget(HInvoke* invoke, ArtMethod* resolved_method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (IsMethodOrDeclaringClassFinal(resolved_method)) { - // No need to lookup further, the resolved method will be the target. - 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(); - if (info.IsTop()) { - // We have no information on the receiver. - return nullptr; - } else if (!info.IsExact()) { - // We currently only support inlining with known receivers. - // TODO: Remove this check, we should be able to inline final methods - // on unknown receivers. - return nullptr; - } else if (info.GetTypeHandle()->IsInterface()) { - // Statically knowing that the receiver has an interface type cannot - // help us find what is the target method. - return nullptr; - } else if (!resolved_method->GetDeclaringClass()->IsAssignableFrom(info.GetTypeHandle().Get())) { - // The method that we're trying to call is not in the receiver's class or super classes. - return nullptr; - } - - ClassLinker* cl = Runtime::Current()->GetClassLinker(); - size_t pointer_size = cl->GetImagePointerSize(); - if (invoke->IsInvokeInterface()) { - resolved_method = info.GetTypeHandle()->FindVirtualMethodForInterface( - resolved_method, pointer_size); - } else { - DCHECK(invoke->IsInvokeVirtual()); - resolved_method = info.GetTypeHandle()->FindVirtualMethodForVirtual( - resolved_method, pointer_size); - } - - if (resolved_method == nullptr) { - // The information we had on the receiver was not enough to find - // the target method. Since we check above the exact type of the receiver, - // the only reason this can happen is an IncompatibleClassChangeError. - return nullptr; - } else if (resolved_method->IsAbstract()) { - // The information we had on the receiver was not enough to find - // the target method. Since we check above the exact type of the receiver, - // the only reason this can happen is an IncompatibleClassChangeError. - return nullptr; - } else if (IsMethodOrDeclaringClassFinal(resolved_method)) { - // A final method has to be the target method. - return resolved_method; - } else if (info.IsExact()) { - // If we found a method and the receiver's concrete type is statically - // known, we know for sure the target. - return resolved_method; - } else { - // Even if we did find a method, the receiver type was not enough to - // statically find the runtime target. - return nullptr; - } -} - bool HInliner::TryInline(HInvoke* invoke_instruction, uint32_t method_index, InvokeType invoke_type) const { @@ -167,34 +90,19 @@ bool HInliner::TryInline(HInvoke* invoke_instruction, const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile(); VLOG(compiler) << "Try inlining " << PrettyMethod(method_index, caller_dex_file); - ArtMethod* resolved_method = nullptr; - { - // Don't keep this handle scope on stack, otherwise we cannot do a reference type - // propagation while inlining. - StackHandleScope<2> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache( - hs.NewHandle(caller_compilation_unit_.GetClassLinker()->FindDexCache(caller_dex_file))); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle( - soa.Decode<mirror::ClassLoader*>(caller_compilation_unit_.GetClassLoader()))); - resolved_method = compiler_driver_->ResolveMethod( - soa, dex_cache, class_loader, &caller_compilation_unit_, method_index, invoke_type); - } + StackHandleScope<3> hs(soa.Self()); + Handle<mirror::DexCache> dex_cache( + hs.NewHandle(caller_compilation_unit_.GetClassLinker()->FindDexCache(caller_dex_file))); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle( + soa.Decode<mirror::ClassLoader*>(caller_compilation_unit_.GetClassLoader()))); + ArtMethod* resolved_method(compiler_driver_->ResolveMethod( + soa, dex_cache, class_loader, &caller_compilation_unit_, method_index, invoke_type)); if (resolved_method == nullptr) { VLOG(compiler) << "Method cannot be resolved " << PrettyMethod(method_index, caller_dex_file); return false; } - if (!invoke_instruction->IsInvokeStaticOrDirect()) { - resolved_method = FindVirtualOrInterfaceTarget(invoke_instruction, resolved_method); - if (resolved_method == nullptr) { - VLOG(compiler) << "Interface or virtual call to " - << PrettyMethod(method_index, caller_dex_file) - << "could not be statically determined"; - return false; - } - } - bool same_dex_file = true; const DexFile& outer_dex_file = *outer_compilation_unit_.GetDexFile(); if (resolved_method->GetDexFile()->GetLocation().compare(outer_dex_file.GetLocation()) != 0) { @@ -337,13 +245,11 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, // Run simple optimizations on the graph. HDeadCodeElimination dce(callee_graph, stats_); HConstantFolding fold(callee_graph); - ReferenceTypePropagation type_propagation(callee_graph, handles_); InstructionSimplifier simplify(callee_graph, stats_); HOptimization* optimizations[] = { &dce, &fold, - &type_propagation, &simplify, }; @@ -357,7 +263,6 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, outer_compilation_unit_, dex_compilation_unit, compiler_driver_, - handles_, stats_, depth_ + 1); inliner.Run(); diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h index ca713329f5..b86c1ed505 100644 --- a/compiler/optimizing/inliner.h +++ b/compiler/optimizing/inliner.h @@ -34,15 +34,13 @@ class HInliner : public HOptimization { const DexCompilationUnit& outer_compilation_unit, const DexCompilationUnit& caller_compilation_unit, CompilerDriver* compiler_driver, - StackHandleScopeCollection* handles, OptimizingCompilerStats* stats, size_t depth = 0) : HOptimization(outer_graph, true, kInlinerPassName, stats), outer_compilation_unit_(outer_compilation_unit), caller_compilation_unit_(caller_compilation_unit), compiler_driver_(compiler_driver), - depth_(depth), - handles_(handles) {} + depth_(depth) {} void Run() OVERRIDE; @@ -59,7 +57,6 @@ class HInliner : public HOptimization { const DexCompilationUnit& caller_compilation_unit_; CompilerDriver* const compiler_driver_; const size_t depth_; - StackHandleScopeCollection* const handles_; DISALLOW_COPY_AND_ASSIGN(HInliner); }; diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index bf0b9fac0f..f6ef2f7e82 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -326,7 +326,7 @@ static void RunOptimizations(HGraph* graph, InstructionSimplifier simplify1(graph, stats); HBooleanSimplifier boolean_simplify(graph); - HInliner inliner(graph, dex_compilation_unit, dex_compilation_unit, driver, handles, stats); + HInliner inliner(graph, dex_compilation_unit, dex_compilation_unit, driver, stats); HConstantFolding fold2(graph, "constant_folding_after_inlining"); SideEffectsAnalysis side_effects(graph); @@ -335,8 +335,6 @@ static void RunOptimizations(HGraph* graph, BoundsCheckElimination bce(graph); ReferenceTypePropagation type_propagation(graph, handles); InstructionSimplifier simplify2(graph, stats, "instruction_simplifier_after_types"); - InstructionSimplifier simplify3(graph, stats, "last_instruction_simplifier"); - ReferenceTypePropagation type_propagation2(graph, handles); IntrinsicsRecognizer intrinsics(graph, driver); @@ -345,12 +343,7 @@ static void RunOptimizations(HGraph* graph, &dce1, &fold1, &simplify1, - &type_propagation, - &simplify2, &inliner, - // Run another type propagation phase: inlining will open up more opprotunities - // to remove checkast/instanceof and null checks. - &type_propagation2, // BooleanSimplifier depends on the InstructionSimplifier removing redundant // suspend checks to recognize empty blocks. &boolean_simplify, @@ -359,7 +352,8 @@ static void RunOptimizations(HGraph* graph, &gvn, &licm, &bce, - &simplify3, + &type_propagation, + &simplify2, &dce2, }; diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 4edadef1a4..4f1f45769d 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -166,34 +166,31 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { } } -void ReferenceTypePropagation::SetClassAsTypeInfo(HInstruction* instr, - mirror::Class* klass, - bool is_exact) { +void ReferenceTypePropagation::SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass) { if (klass != nullptr) { ScopedObjectAccess soa(Thread::Current()); MutableHandle<mirror::Class> handle = handles_->NewHandle(klass); - instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact)); + instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true)); } } void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, - const DexFile& dex_file, - bool is_exact) { + const DexFile& dex_file) { DCHECK_EQ(instr->GetType(), Primitive::kPrimNot); ScopedObjectAccess soa(Thread::Current()); mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); // Get type from dex cache assuming it was populated by the verifier. - SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx), is_exact); + SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx)); } void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) { - UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true); + UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile()); } void ReferenceTypePropagation::VisitNewArray(HNewArray* instr) { - UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile(), /* is_exact */ true); + UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile()); } void ReferenceTypePropagation::UpdateFieldAccessTypeInfo(HInstruction* instr, @@ -209,7 +206,7 @@ void ReferenceTypePropagation::UpdateFieldAccessTypeInfo(HInstruction* instr, ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache); DCHECK(field != nullptr); mirror::Class* klass = field->GetType<false>(); - SetClassAsTypeInfo(instr, klass, /* is_exact */ false); + SetClassAsTypeInfo(instr, klass); } void ReferenceTypePropagation::VisitInstanceFieldGet(HInstanceFieldGet* instr) { diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h index 0a1d4c496e..74e425fb3e 100644 --- a/compiler/optimizing/reference_type_propagation.h +++ b/compiler/optimizing/reference_type_propagation.h @@ -46,17 +46,14 @@ class ReferenceTypePropagation : public HOptimization { void VisitPhi(HPhi* phi); void VisitBasicBlock(HBasicBlock* block); void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info); - void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass, bool is_exact); + void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass); void UpdateBoundType(HBoundType* bound_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void UpdatePhi(HPhi* phi) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void BoundTypeForIfNotNull(HBasicBlock* block); void BoundTypeForIfInstanceOf(HBasicBlock* block); - void UpdateReferenceTypeInfo(HInstruction* instr, - uint16_t type_idx, - const DexFile& dex_file, - bool is_exact); + void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file); void VisitInstanceFieldGet(HInstanceFieldGet* instr); void VisitStaticFieldGet(HStaticFieldGet* instr); |