diff options
Diffstat (limited to 'compiler/dex/mir_method_info.cc')
-rw-r--r-- | compiler/dex/mir_method_info.cc | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc index b234950..3d3d979 100644 --- a/compiler/dex/mir_method_info.cc +++ b/compiler/dex/mir_method_info.cc @@ -33,51 +33,103 @@ void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver, DCHECK(method_infos != nullptr); DCHECK_NE(count, 0u); for (auto it = method_infos, end = method_infos + count; it != end; ++it) { - MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType()); + MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType(), it->IsQuickened()); + unresolved.declaring_dex_file_ = it->declaring_dex_file_; + unresolved.vtable_idx_ = it->vtable_idx_; if (it->target_dex_file_ != nullptr) { unresolved.target_dex_file_ = it->target_dex_file_; unresolved.target_method_idx_ = it->target_method_idx_; } - DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0); + if (kIsDebugBuild) { + unresolved.CheckEquals(*it); + } } } // We're going to resolve methods and check access in a tight loop. It's better to hold // the lock and needed references once than re-acquiring them again and again. ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<3> hs(soa.Self()); + StackHandleScope<4> hs(soa.Self()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit))); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit))); Handle<mirror::Class> referrer_class(hs.NewHandle( compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit))); + auto current_dex_cache(hs.NewHandle<mirror::DexCache>(nullptr)); // Even if the referrer class is unresolved (i.e. we're compiling a method without class // definition) we still want to resolve methods and record all available info. + const DexFile* const dex_file = mUnit->GetDexFile(); + const bool use_jit = Runtime::Current()->UseJit(); + const VerifiedMethod* const verified_method = mUnit->GetVerifiedMethod(); for (auto it = method_infos, end = method_infos + count; it != end; ++it) { + // For quickened invokes, the dex method idx is actually the mir offset. + if (it->IsQuickened()) { + const auto* dequicken_ref = verified_method->GetDequickenIndex(it->method_idx_); + CHECK(dequicken_ref != nullptr); + it->target_dex_file_ = dequicken_ref->dex_file; + it->target_method_idx_ = dequicken_ref->index; + } // Remember devirtualized invoke target and set the called method to the default. MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_); MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr; - it->target_dex_file_ = mUnit->GetDexFile(); - it->target_method_idx_ = it->MethodIndex(); - InvokeType invoke_type = it->GetInvokeType(); - mirror::ArtMethod* resolved_method = - compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(), - invoke_type); + mirror::ArtMethod* resolved_method = nullptr; + if (!it->IsQuickened()) { + it->target_dex_file_ = dex_file; + it->target_method_idx_ = it->MethodIndex(); + current_dex_cache.Assign(dex_cache.Get()); + resolved_method = compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, + it->MethodIndex(), invoke_type); + } else { + // The method index is actually the dex PC in this case. + // Calculate the proper dex file and target method idx. + CHECK(use_jit); + CHECK_EQ(invoke_type, kVirtual); + // Don't devirt if we are in a different dex file since we can't have direct invokes in + // another dex file unless we always put a direct / patch pointer. + devirt_target = nullptr; + current_dex_cache.Assign( + Runtime::Current()->GetClassLinker()->FindDexCache(*it->target_dex_file_)); + CHECK(current_dex_cache.Get() != nullptr); + DexCompilationUnit cu( + mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(), + *it->target_dex_file_, nullptr /* code_item not used */, 0u /* class_def_idx not used */, + it->target_method_idx_, 0u /* access_flags not used */, + nullptr /* verified_method not used */); + resolved_method = compiler_driver->ResolveMethod(soa, current_dex_cache, class_loader, &cu, + it->target_method_idx_, invoke_type, false); + if (resolved_method != nullptr) { + // Since this was a dequickened virtual, it is guaranteed to be resolved. However, it may be + // resolved to an interface method. If this is the case then change the invoke type to + // interface with the assumption that sharp_type will be kVirtual. + if (resolved_method->GetInvokeType() == kInterface) { + it->flags_ = (it->flags_ & ~(kInvokeTypeMask << kBitInvokeTypeBegin)) | + (static_cast<uint16_t>(kInterface) << kBitInvokeTypeBegin); + } + } + } if (UNLIKELY(resolved_method == nullptr)) { continue; } compiler_driver->GetResolvedMethodDexFileLocation(resolved_method, &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_); - it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type); + if (!it->IsQuickened()) { + // For quickened invoke virtuals we may have desharpened to an interface method which + // wont give us the right method index, in this case blindly dispatch or else we can't + // compile the method. Converting the invoke to interface dispatch doesn't work since we + // have no way to get the dex method index for quickened invoke virtuals in the interface + // trampolines. + it->vtable_idx_ = + compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type); + } - MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex()); + MethodReference target_method(it->target_dex_file_, it->target_method_idx_); int fast_path_flags = compiler_driver->IsFastInvoke( - soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type, - &target_method, devirt_target, &it->direct_code_, &it->direct_method_); - bool is_referrers_class = (referrer_class.Get() == resolved_method->GetDeclaringClass()); - bool is_class_initialized = + soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, + &invoke_type, &target_method, devirt_target, &it->direct_code_, &it->direct_method_); + const bool is_referrers_class = referrer_class.Get() == resolved_method->GetDeclaringClass(); + const bool is_class_initialized = compiler_driver->IsMethodsClassInitialized(referrer_class.Get(), resolved_method); uint16_t other_flags = it->flags_ & ~(kFlagFastPath | kFlagClassIsInitialized | (kInvokeTypeMask << kBitSharpTypeBegin)); |