diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/dex/mir_dataflow.cc | 10 | ||||
-rw-r--r-- | src/compiler/dex/quick/gen_invoke.cc | 2 | ||||
-rw-r--r-- | src/compiler/driver/compiler_driver.cc | 51 | ||||
-rw-r--r-- | src/compiler/driver/compiler_driver.h | 7 | ||||
-rw-r--r-- | src/compiler/llvm/gbc_expander.cc | 4 |
5 files changed, 62 insertions, 12 deletions
diff --git a/src/compiler/dex/mir_dataflow.cc b/src/compiler/dex/mir_dataflow.cc index 23bf24889..444874dce 100644 --- a/src/compiler/dex/mir_dataflow.cc +++ b/src/compiler/dex/mir_dataflow.cc @@ -1249,11 +1249,13 @@ bool MIRGraph::InvokeUsesMethodStar(MIR* mir) int vtable_idx; uintptr_t direct_code; uintptr_t direct_method; + uint32_t current_offset = static_cast<uint32_t>(current_offset_); bool fast_path = - cu_->compiler_driver->ComputeInvokeInfo(dex_method_idx, &m_unit, type, - vtable_idx, direct_code, - direct_method) && - !(cu_->enable_debug & (1 << kDebugSlowInvokePath)); + cu_->compiler_driver->ComputeInvokeInfo(dex_method_idx, current_offset, + &m_unit, type, + vtable_idx, direct_code, + direct_method) && + !(cu_->enable_debug & (1 << kDebugSlowInvokePath)); return (((type == kDirect) || (type == kStatic)) && fast_path && ((direct_code == 0) || (direct_method == 0))); } diff --git a/src/compiler/dex/quick/gen_invoke.cc b/src/compiler/dex/quick/gen_invoke.cc index 2eab673e2..efacff0ab 100644 --- a/src/compiler/dex/quick/gen_invoke.cc +++ b/src/compiler/dex/quick/gen_invoke.cc @@ -1329,7 +1329,7 @@ void Mir2Lir::GenInvoke(CallInfo* info) uintptr_t direct_method; bool skip_this; bool fast_path = cu_->compiler_driver->ComputeInvokeInfo( - dex_method_idx, mir_graph_->GetCurrentDexCompilationUnit(), info->type, vtable_idx, + dex_method_idx, current_dalvik_offset_, mir_graph_->GetCurrentDexCompilationUnit(), info->type, vtable_idx, direct_code, direct_method) && !SLOW_INVOKE_PATH; if (info->type == kInterface) { if (fast_path) { diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index 1660914ce..bed9ac141 100644 --- a/src/compiler/driver/compiler_driver.cc +++ b/src/compiler/driver/compiler_driver.cc @@ -71,7 +71,8 @@ class AOTCompilationStats { strings_in_dex_cache_(0), strings_not_in_dex_cache_(0), resolved_types_(0), unresolved_types_(0), resolved_instance_fields_(0), unresolved_instance_fields_(0), - resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0) { + resolved_local_static_fields_(0), resolved_static_fields_(0), unresolved_static_fields_(0), + type_based_devirtualization_(0) { for (size_t i = 0; i <= kMaxInvokeType; i++) { resolved_methods_[i] = 0; unresolved_methods_[i] = 0; @@ -90,6 +91,8 @@ class AOTCompilationStats { "static fields resolved"); DumpStat(resolved_local_static_fields_, resolved_static_fields_ + unresolved_static_fields_, "static fields local to a class"); + DumpStat(type_based_devirtualization_,virtual_made_direct_[kInterface] + virtual_made_direct_[kVirtual] + - type_based_devirtualization_, "sharpened calls based on type information"); for (size_t i = 0; i <= kMaxInvokeType; i++) { std::ostringstream oss; @@ -181,6 +184,11 @@ class AOTCompilationStats { unresolved_static_fields_++; } + void PreciseTypeDevirtualization() { + STATS_LOCK(); + type_based_devirtualization_++; + } + void ResolvedMethod(InvokeType type) { DCHECK_LE(type, kMaxInvokeType); STATS_LOCK(); @@ -229,6 +237,8 @@ class AOTCompilationStats { size_t resolved_local_static_fields_; size_t resolved_static_fields_; size_t unresolved_static_fields_; + // Type based devirtualization for invoke interface and virtual. + size_t type_based_devirtualization_; size_t resolved_methods_[kMaxInvokeType + 1]; size_t unresolved_methods_[kMaxInvokeType + 1]; @@ -805,15 +815,24 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType type, InvokeType s } } -bool CompilerDriver::ComputeInvokeInfo(uint32_t method_idx, const DexCompilationUnit* mUnit, - InvokeType& type, int& vtable_idx, uintptr_t& direct_code, +bool CompilerDriver::ComputeInvokeInfo(uint32_t method_idx,const uint32_t dex_pc, + const DexCompilationUnit* mUnit, InvokeType& type, + int& vtable_idx, uintptr_t& direct_code, uintptr_t& direct_method) { ScopedObjectAccess soa(Thread::Current()); + + const bool kEnableVerifierBasedSharpening = true; + const CompilerDriver::MethodReference ref_caller(mUnit->GetDexFile(), mUnit->GetDexMethodIndex()); + const CompilerDriver::MethodReference* ref_sharpen = verifier::MethodVerifier::GetDevirtMap(ref_caller, dex_pc); + bool can_devirtualize = (dex_pc != art::kDexPCNotReady) && (ref_sharpen != NULL); + vtable_idx = -1; direct_code = 0; direct_method = 0; mirror::AbstractMethod* resolved_method = ComputeMethodReferencedFromCompilingMethod(soa, mUnit, method_idx, type); + + if (resolved_method != NULL) { // Don't try to fast-path if we don't understand the caller's class or this appears to be an // Incompatible Class Change Error. @@ -836,8 +855,10 @@ bool CompilerDriver::ComputeInvokeInfo(uint32_t method_idx, const DexCompilation } if (referrer_class->CanAccess(methods_class) && referrer_class->CanAccessMember(methods_class, resolved_method->GetAccessFlags())) { + vtable_idx = resolved_method->GetMethodIndex(); const bool kEnableSharpening = true; + // Sharpen a virtual call into a direct call when the target is known. bool can_sharpen = type == kVirtual && (resolved_method->IsFinal() || methods_class->IsFinal()); @@ -846,6 +867,7 @@ bool CompilerDriver::ComputeInvokeInfo(uint32_t method_idx, const DexCompilation referrer_class->IsSubClass(methods_class) && vtable_idx < methods_class->GetVTable()->GetLength() && methods_class->GetVTable()->Get(vtable_idx) == resolved_method); + if (kEnableSharpening && can_sharpen) { stats_->ResolvedMethod(type); // Sharpen a virtual call into a direct call. The method_idx is into referrer's @@ -857,7 +879,28 @@ bool CompilerDriver::ComputeInvokeInfo(uint32_t method_idx, const DexCompilation direct_code, direct_method); type = kDirect; return true; - } else if (type == kSuper) { + + } else if(can_devirtualize && kEnableSharpening && kEnableVerifierBasedSharpening) { + // If traditional sharpening fails, try the sharpening based on type information (Devirtualization) + mirror::DexCache* dex_cache = mUnit->GetClassLinker()->FindDexCache(*ref_sharpen->first); + mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); + mirror::AbstractMethod* concrete_method = mUnit->GetClassLinker()->ResolveMethod( + *ref_sharpen->first, ref_sharpen->second, dex_cache, class_loader, NULL, kVirtual); + CHECK(concrete_method != NULL); + CHECK(!concrete_method->IsAbstract()); + // TODO: fix breakage in image patching to be able to devirtualize cases with different + // resolved and concrete methods. + if(resolved_method == concrete_method) { + GetCodeAndMethodForDirectCall(type, kDirect, referrer_class, concrete_method, direct_code, direct_method); + type = kDirect; + stats_->VirtualMadeDirect(type); + stats_->PreciseTypeDevirtualization(); + } + stats_->ResolvedMethod(type); + + return true; + } + else if (type == kSuper) { // Unsharpened super calls are suspicious so go slow-path. } else { stats_->ResolvedMethod(type); diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h index a20e5ef58..e28955827 100644 --- a/src/compiler/driver/compiler_driver.h +++ b/src/compiler/driver/compiler_driver.h @@ -39,6 +39,8 @@ class ParallelCompilationManager; class DexCompilationUnit; class TimingLogger; +const uint32_t kDexPCNotReady = 0xFFFFFF; + enum CompilerBackend { kQuick, kPortable, @@ -149,8 +151,9 @@ class CompilerDriver { // Can we fastpath a interface, super class or virtual method call? Computes method's vtable // index. - bool ComputeInvokeInfo(uint32_t method_idx, const DexCompilationUnit* mUnit, InvokeType& type, - int& vtable_idx, uintptr_t& direct_code, uintptr_t& direct_method) + bool ComputeInvokeInfo(uint32_t method_idx, uint32_t dex_pc, + const DexCompilationUnit* mUnit, InvokeType& type, int& vtable_idx, + uintptr_t& direct_code, uintptr_t& direct_method) LOCKS_EXCLUDED(Locks::mutator_lock_); // Record patch information for later fix up. diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc index 94eb74103..c1e35a69a 100644 --- a/src/compiler/llvm/gbc_expander.cc +++ b/src/compiler/llvm/gbc_expander.cc @@ -785,8 +785,10 @@ llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) { int vtable_idx = -1; uintptr_t direct_code = 0; uintptr_t direct_method = 0; + // TODO: pass actual value of dex PC (instead of kDexPCNotready) needed by verifier based + // sharpening after LLVM re-factoring is finished. bool is_fast_path = driver_-> - ComputeInvokeInfo(callee_method_idx, dex_compilation_unit_, + ComputeInvokeInfo(callee_method_idx, art::kDexPCNotReady, dex_compilation_unit_, invoke_type, vtable_idx, direct_code, direct_method); // Load the method object |