blob: 831ad42682a5dc988ae03f275f6ce5d4f77fd54a [file] [log] [blame]
Vladimir Markof096aad2014-01-23 15:51:58 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17# include "mir_method_info.h"
18
Vladimir Marko20f85592015-03-19 10:07:02 +000019#include "dex/verified_method.h"
Vladimir Markof096aad2014-01-23 15:51:58 +000020#include "driver/compiler_driver.h"
21#include "driver/dex_compilation_unit.h"
22#include "driver/compiler_driver-inl.h"
Vladimir Marko20f85592015-03-19 10:07:02 +000023#include "driver/compiler_options.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070024#include "mirror/class_loader.h" // Only to allow casts in Handle<ClassLoader>.
25#include "mirror/dex_cache.h" // Only to allow casts in Handle<DexCache>.
Vladimir Markof096aad2014-01-23 15:51:58 +000026#include "scoped_thread_state_change.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070027#include "handle_scope-inl.h"
Vladimir Markof096aad2014-01-23 15:51:58 +000028
29namespace art {
30
31void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver,
32 const DexCompilationUnit* mUnit,
33 MirMethodLoweringInfo* method_infos, size_t count) {
34 if (kIsDebugBuild) {
35 DCHECK(method_infos != nullptr);
36 DCHECK_NE(count, 0u);
37 for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080038 MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType(), it->IsQuickened());
39 unresolved.declaring_dex_file_ = it->declaring_dex_file_;
40 unresolved.vtable_idx_ = it->vtable_idx_;
Vladimir Markof096aad2014-01-23 15:51:58 +000041 if (it->target_dex_file_ != nullptr) {
42 unresolved.target_dex_file_ = it->target_dex_file_;
43 unresolved.target_method_idx_ = it->target_method_idx_;
44 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080045 if (kIsDebugBuild) {
46 unresolved.CheckEquals(*it);
47 }
Vladimir Markof096aad2014-01-23 15:51:58 +000048 }
49 }
50
51 // We're going to resolve methods and check access in a tight loop. It's better to hold
52 // the lock and needed references once than re-acquiring them again and again.
53 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080054 StackHandleScope<4> hs(soa.Self());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070055 Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit)));
56 Handle<mirror::ClassLoader> class_loader(
57 hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit)));
58 Handle<mirror::Class> referrer_class(hs.NewHandle(
59 compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit)));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080060 auto current_dex_cache(hs.NewHandle<mirror::DexCache>(nullptr));
Vladimir Markof096aad2014-01-23 15:51:58 +000061 // Even if the referrer class is unresolved (i.e. we're compiling a method without class
62 // definition) we still want to resolve methods and record all available info.
Mathieu Chartier091d2382015-03-06 10:59:06 -080063 Runtime* const runtime = Runtime::Current();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080064 const DexFile* const dex_file = mUnit->GetDexFile();
Mathieu Chartier091d2382015-03-06 10:59:06 -080065 const bool use_jit = runtime->UseJit();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080066 const VerifiedMethod* const verified_method = mUnit->GetVerifiedMethod();
Vladimir Markof096aad2014-01-23 15:51:58 +000067
68 for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080069 // For quickened invokes, the dex method idx is actually the mir offset.
70 if (it->IsQuickened()) {
71 const auto* dequicken_ref = verified_method->GetDequickenIndex(it->method_idx_);
72 CHECK(dequicken_ref != nullptr);
73 it->target_dex_file_ = dequicken_ref->dex_file;
74 it->target_method_idx_ = dequicken_ref->index;
75 }
Vladimir Markof096aad2014-01-23 15:51:58 +000076 // Remember devirtualized invoke target and set the called method to the default.
77 MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
78 MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
Vladimir Markof096aad2014-01-23 15:51:58 +000079 InvokeType invoke_type = it->GetInvokeType();
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080080 mirror::ArtMethod* resolved_method = nullptr;
81 if (!it->IsQuickened()) {
82 it->target_dex_file_ = dex_file;
83 it->target_method_idx_ = it->MethodIndex();
84 current_dex_cache.Assign(dex_cache.Get());
85 resolved_method = compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit,
Mathieu Chartier091d2382015-03-06 10:59:06 -080086 it->target_method_idx_, invoke_type, true);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080087 } else {
88 // The method index is actually the dex PC in this case.
89 // Calculate the proper dex file and target method idx.
90 CHECK(use_jit);
91 CHECK_EQ(invoke_type, kVirtual);
92 // Don't devirt if we are in a different dex file since we can't have direct invokes in
93 // another dex file unless we always put a direct / patch pointer.
94 devirt_target = nullptr;
Mathieu Chartier091d2382015-03-06 10:59:06 -080095 current_dex_cache.Assign(runtime->GetClassLinker()->FindDexCache(*it->target_dex_file_));
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080096 CHECK(current_dex_cache.Get() != nullptr);
97 DexCompilationUnit cu(
98 mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(),
99 *it->target_dex_file_, nullptr /* code_item not used */, 0u /* class_def_idx not used */,
100 it->target_method_idx_, 0u /* access_flags not used */,
101 nullptr /* verified_method not used */);
102 resolved_method = compiler_driver->ResolveMethod(soa, current_dex_cache, class_loader, &cu,
103 it->target_method_idx_, invoke_type, false);
Mathieu Chartier091d2382015-03-06 10:59:06 -0800104 if (resolved_method == nullptr) {
105 // If the method is null then it should be a miranda method, in this case try
106 // re-loading it, this time as an interface method. The actual miranda method is in the
107 // vtable, but it will resolve to an interface method.
108 resolved_method = compiler_driver->ResolveMethod(
109 soa, current_dex_cache, class_loader, &cu, it->target_method_idx_, kInterface, false);
110 CHECK(resolved_method != nullptr);
111 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800112 if (resolved_method != nullptr) {
113 // Since this was a dequickened virtual, it is guaranteed to be resolved. However, it may be
114 // resolved to an interface method. If this is the case then change the invoke type to
115 // interface with the assumption that sharp_type will be kVirtual.
116 if (resolved_method->GetInvokeType() == kInterface) {
117 it->flags_ = (it->flags_ & ~(kInvokeTypeMask << kBitInvokeTypeBegin)) |
118 (static_cast<uint16_t>(kInterface) << kBitInvokeTypeBegin);
119 }
120 }
121 }
Vladimir Markof096aad2014-01-23 15:51:58 +0000122 if (UNLIKELY(resolved_method == nullptr)) {
123 continue;
124 }
125 compiler_driver->GetResolvedMethodDexFileLocation(resolved_method,
126 &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_);
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800127 if (!it->IsQuickened()) {
128 // For quickened invoke virtuals we may have desharpened to an interface method which
129 // wont give us the right method index, in this case blindly dispatch or else we can't
130 // compile the method. Converting the invoke to interface dispatch doesn't work since we
131 // have no way to get the dex method index for quickened invoke virtuals in the interface
132 // trampolines.
133 it->vtable_idx_ =
134 compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
135 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800136 MethodReference target_method(it->target_dex_file_, it->target_method_idx_);
Vladimir Markof096aad2014-01-23 15:51:58 +0000137 int fast_path_flags = compiler_driver->IsFastInvoke(
Mathieu Chartier091d2382015-03-06 10:59:06 -0800138 soa, current_dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800139 &invoke_type, &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
140 const bool is_referrers_class = referrer_class.Get() == resolved_method->GetDeclaringClass();
141 const bool is_class_initialized =
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100142 compiler_driver->IsMethodsClassInitialized(referrer_class.Get(), resolved_method);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000143 uint16_t other_flags = it->flags_ &
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100144 ~(kFlagFastPath | kFlagClassIsInitialized | (kInvokeTypeMask << kBitSharpTypeBegin));
Vladimir Markof096aad2014-01-23 15:51:58 +0000145 it->flags_ = other_flags |
146 (fast_path_flags != 0 ? kFlagFastPath : 0u) |
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000147 (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin) |
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100148 (is_referrers_class ? kFlagIsReferrersClass : 0u) |
149 (is_class_initialized ? kFlagClassIsInitialized : 0u);
Vladimir Markof096aad2014-01-23 15:51:58 +0000150 it->target_dex_file_ = target_method.dex_file;
151 it->target_method_idx_ = target_method.dex_method_index;
152 it->stats_flags_ = fast_path_flags;
153 }
154}
155
156} // namespace art