summaryrefslogtreecommitdiffstats
path: root/compiler/dex/mir_method_info.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/mir_method_info.cc')
-rw-r--r--compiler/dex/mir_method_info.cc82
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));