diff options
author | 2013-04-30 12:09:45 -0700 | |
---|---|---|
committer | 2013-05-02 14:19:17 -0700 | |
commit | 02c42237741b5573f9d790a5a0f17f408dceb543 (patch) | |
tree | 293d72039e2e1a0e56fbcb572c6d92ccedc5581a /src/compiler/driver/compiler_driver.cc | |
parent | cf9773a7adff883012dbd519a66e85f1f7aaaa11 (diff) |
Supporting de-virtualization for precise types.
Sharpening invoke-virtual and invoke-interface calls to invoke-direct for cases
where the type of "this" pointer in the invoke- params is precisely known.
Instructions that have an invoke opcode are marked as interesting, for each invoke-virtual/interface
we come across with a precise type for "this" we mark the location as a candidate for sharpening,
resolve the concrete method and save its method reference <DexFile, DexMethodIndex> to be sharpened
in CompilerDriver::ComputeInvokeInfo().
Added a new entry to AOT statistics showing the percentage of sharpened calls that were based on
type analysis.
Fix a minor bug in type creation for GetSuperClass(). Previously super class of a precise reference
had precise types created which is not necessarily the case.
Fixed DCHECK in Class::FindVirtualMethodForVirtual to handle cases for Miranda methods.
Sharpening only takes place for cases where no soft failures happen at verification time.
Change-Id: Ic027d0226d6f95260c1918014cb6313f2e0ca455
Diffstat (limited to 'src/compiler/driver/compiler_driver.cc')
-rw-r--r-- | src/compiler/driver/compiler_driver.cc | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc index bc34073020..3e1e7436aa 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,10 @@ class AOTCompilationStats { unresolved_static_fields_++; } + void PreciseTypeDevirtualization() { + STATS_LOCK(); + type_based_devirtualization_++; + } void ResolvedMethod(InvokeType type) { DCHECK_LE(type, kMaxInvokeType); STATS_LOCK(); @@ -229,6 +236,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]; @@ -804,10 +813,16 @@ 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; @@ -845,6 +860,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 @@ -856,7 +872,26 @@ 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); + stats_->VirtualMadeDirect(type); + type = kDirect; + stats_->PreciseTypeDevirtualization(); + } + stats_->ResolvedMethod(type); + return true; + } + else if (type == kSuper) { // Unsharpened super calls are suspicious so go slow-path. } else { stats_->ResolvedMethod(type); |