blob: b2349504506a1b0d8800001d61ea2b2850f87f1b [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
19#include "driver/compiler_driver.h"
20#include "driver/dex_compilation_unit.h"
21#include "driver/compiler_driver-inl.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070022#include "mirror/class_loader.h" // Only to allow casts in Handle<ClassLoader>.
23#include "mirror/dex_cache.h" // Only to allow casts in Handle<DexCache>.
Vladimir Markof096aad2014-01-23 15:51:58 +000024#include "scoped_thread_state_change.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070025#include "handle_scope-inl.h"
Vladimir Markof096aad2014-01-23 15:51:58 +000026
27namespace art {
28
29void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver,
30 const DexCompilationUnit* mUnit,
31 MirMethodLoweringInfo* method_infos, size_t count) {
32 if (kIsDebugBuild) {
33 DCHECK(method_infos != nullptr);
34 DCHECK_NE(count, 0u);
35 for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
36 MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType());
37 if (it->target_dex_file_ != nullptr) {
38 unresolved.target_dex_file_ = it->target_dex_file_;
39 unresolved.target_method_idx_ = it->target_method_idx_;
40 }
41 DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0);
42 }
43 }
44
45 // We're going to resolve methods and check access in a tight loop. It's better to hold
46 // the lock and needed references once than re-acquiring them again and again.
47 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070048 StackHandleScope<3> hs(soa.Self());
49 Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit)));
50 Handle<mirror::ClassLoader> class_loader(
51 hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit)));
52 Handle<mirror::Class> referrer_class(hs.NewHandle(
53 compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit)));
Vladimir Markof096aad2014-01-23 15:51:58 +000054 // Even if the referrer class is unresolved (i.e. we're compiling a method without class
55 // definition) we still want to resolve methods and record all available info.
56
57 for (auto it = method_infos, end = method_infos + count; it != end; ++it) {
58 // Remember devirtualized invoke target and set the called method to the default.
59 MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
60 MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
61 it->target_dex_file_ = mUnit->GetDexFile();
62 it->target_method_idx_ = it->MethodIndex();
63
64 InvokeType invoke_type = it->GetInvokeType();
65 mirror::ArtMethod* resolved_method =
66 compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(),
67 invoke_type);
68 if (UNLIKELY(resolved_method == nullptr)) {
69 continue;
70 }
71 compiler_driver->GetResolvedMethodDexFileLocation(resolved_method,
72 &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_);
73 it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type);
74
75 MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex());
76 int fast_path_flags = compiler_driver->IsFastInvoke(
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070077 soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type,
Vladimir Markof096aad2014-01-23 15:51:58 +000078 &target_method, devirt_target, &it->direct_code_, &it->direct_method_);
Vladimir Marko66c6d7b2014-10-16 15:41:48 +010079 bool is_referrers_class = (referrer_class.Get() == resolved_method->GetDeclaringClass());
80 bool is_class_initialized =
81 compiler_driver->IsMethodsClassInitialized(referrer_class.Get(), resolved_method);
Vladimir Marko9820b7c2014-01-02 16:40:37 +000082 uint16_t other_flags = it->flags_ &
Vladimir Marko66c6d7b2014-10-16 15:41:48 +010083 ~(kFlagFastPath | kFlagClassIsInitialized | (kInvokeTypeMask << kBitSharpTypeBegin));
Vladimir Markof096aad2014-01-23 15:51:58 +000084 it->flags_ = other_flags |
85 (fast_path_flags != 0 ? kFlagFastPath : 0u) |
Vladimir Marko9820b7c2014-01-02 16:40:37 +000086 (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin) |
Vladimir Marko66c6d7b2014-10-16 15:41:48 +010087 (is_referrers_class ? kFlagIsReferrersClass : 0u) |
88 (is_class_initialized ? kFlagClassIsInitialized : 0u);
Vladimir Markof096aad2014-01-23 15:51:58 +000089 it->target_dex_file_ = target_method.dex_file;
90 it->target_method_idx_ = target_method.dex_method_index;
91 it->stats_flags_ = fast_path_flags;
92 }
93}
94
95} // namespace art