blob: e131c96a81f6f3b5f272609af6e22c5345ae1833 [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#ifndef ART_COMPILER_DEX_MIR_METHOD_INFO_H_
18#define ART_COMPILER_DEX_MIR_METHOD_INFO_H_
19
20#include "base/logging.h"
21#include "base/macros.h"
22#include "base/mutex.h"
23#include "invoke_type.h"
24#include "method_reference.h"
25
26namespace art {
27
28class CompilerDriver;
29class DexCompilationUnit;
30class DexFile;
31
32class MirMethodInfo {
33 public:
34 uint16_t MethodIndex() const {
35 return method_idx_;
36 }
37
38 bool IsStatic() const {
39 return (flags_ & kFlagIsStatic) != 0u;
40 }
41
42 bool IsResolved() const {
43 return declaring_dex_file_ != nullptr;
44 }
45
46 const DexFile* DeclaringDexFile() const {
47 return declaring_dex_file_;
48 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080049 void SetDeclaringDexFile(const DexFile* dex_file) {
50 declaring_dex_file_ = dex_file;
51 }
Vladimir Markof096aad2014-01-23 15:51:58 +000052
53 uint16_t DeclaringClassIndex() const {
54 return declaring_class_idx_;
55 }
56
57 uint16_t DeclaringMethodIndex() const {
58 return declaring_method_idx_;
59 }
60
61 protected:
62 enum {
63 kBitIsStatic = 0,
64 kMethodInfoBitEnd
65 };
Andreas Gampe785d2f22014-11-03 22:57:30 -080066 static_assert(kMethodInfoBitEnd <= 16, "Too many flags");
Vladimir Markof096aad2014-01-23 15:51:58 +000067 static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
68
69 MirMethodInfo(uint16_t method_idx, uint16_t flags)
70 : method_idx_(method_idx),
71 flags_(flags),
72 declaring_method_idx_(0u),
73 declaring_class_idx_(0u),
74 declaring_dex_file_(nullptr) {
75 }
76
77 // Make copy-ctor/assign/dtor protected to avoid slicing.
78 MirMethodInfo(const MirMethodInfo& other) = default;
79 MirMethodInfo& operator=(const MirMethodInfo& other) = default;
80 ~MirMethodInfo() = default;
81
82 // The method index in the compiling method's dex file.
83 uint16_t method_idx_;
84 // Flags, for volatility and derived class data.
85 uint16_t flags_;
86 // The method index in the dex file that defines the method, 0 if unresolved.
87 uint16_t declaring_method_idx_;
88 // The type index of the class declaring the method, 0 if unresolved.
89 uint16_t declaring_class_idx_;
90 // The dex file that defines the class containing the method and the method,
91 // nullptr if unresolved.
92 const DexFile* declaring_dex_file_;
93};
94
95class MirMethodLoweringInfo : public MirMethodInfo {
96 public:
97 // For each requested method retrieve the method's declaring location (dex file, class
98 // index and method index) and compute whether we can fast path the method call. For fast
99 // path methods, retrieve the method's vtable index and direct code and method when applicable.
100 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
101 MirMethodLoweringInfo* method_infos, size_t count)
102 LOCKS_EXCLUDED(Locks::mutator_lock_);
103
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800104 MirMethodLoweringInfo(uint16_t method_idx, InvokeType type, bool is_quickened)
Vladimir Markof096aad2014-01-23 15:51:58 +0000105 : MirMethodInfo(method_idx,
106 ((type == kStatic) ? kFlagIsStatic : 0u) |
107 (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800108 (static_cast<uint16_t>(type) << kBitSharpTypeBegin) |
109 (is_quickened ? kFlagQuickened : 0u)),
Vladimir Markof096aad2014-01-23 15:51:58 +0000110 direct_code_(0u),
111 direct_method_(0u),
112 target_dex_file_(nullptr),
113 target_method_idx_(0u),
114 vtable_idx_(0u),
115 stats_flags_(0) {
116 }
117
118 void SetDevirtualizationTarget(const MethodReference& ref) {
119 DCHECK(target_dex_file_ == nullptr);
120 DCHECK_EQ(target_method_idx_, 0u);
121 DCHECK_LE(ref.dex_method_index, 0xffffu);
122 target_dex_file_ = ref.dex_file;
123 target_method_idx_ = ref.dex_method_index;
124 }
125
126 bool FastPath() const {
127 return (flags_ & kFlagFastPath) != 0u;
128 }
129
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100130 bool IsReferrersClass() const {
131 return (flags_ & kFlagIsReferrersClass) != 0;
132 }
133
134 bool IsClassInitialized() const {
135 return (flags_ & kFlagClassIsInitialized) != 0u;
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000136 }
137
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800138 // Returns true iff the method invoke is INVOKE_VIRTUAL_QUICK or INVOKE_VIRTUAL_RANGE_QUICK.
139 bool IsQuickened() const {
140 return (flags_ & kFlagQuickened) != 0u;
141 }
142
Vladimir Markof096aad2014-01-23 15:51:58 +0000143 InvokeType GetInvokeType() const {
144 return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
145 }
146
147 art::InvokeType GetSharpType() const {
148 return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
149 }
150
151 MethodReference GetTargetMethod() const {
152 return MethodReference(target_dex_file_, target_method_idx_);
153 }
154
155 uint16_t VTableIndex() const {
156 return vtable_idx_;
157 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800158 void SetVTableIndex(uint16_t index) {
159 vtable_idx_ = index;
160 }
Vladimir Markof096aad2014-01-23 15:51:58 +0000161
162 uintptr_t DirectCode() const {
163 return direct_code_;
164 }
165
166 uintptr_t DirectMethod() const {
167 return direct_method_;
168 }
169
170 int StatsFlags() const {
171 return stats_flags_;
172 }
173
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800174 void CheckEquals(const MirMethodLoweringInfo& info) const {
175 CHECK_EQ(method_idx_, info.method_idx_);
176 CHECK_EQ(flags_, info.flags_);
177 CHECK_EQ(declaring_method_idx_, info.declaring_method_idx_);
178 CHECK_EQ(declaring_class_idx_, info.declaring_class_idx_);
179 CHECK_EQ(declaring_dex_file_, info.declaring_dex_file_);
180 CHECK_EQ(direct_code_, info.direct_code_);
181 CHECK_EQ(direct_method_, info.direct_method_);
182 CHECK_EQ(target_dex_file_, info.target_dex_file_);
183 CHECK_EQ(target_method_idx_, info.target_method_idx_);
184 CHECK_EQ(vtable_idx_, info.vtable_idx_);
185 CHECK_EQ(stats_flags_, info.stats_flags_);
186 }
187
Vladimir Markof096aad2014-01-23 15:51:58 +0000188 private:
189 enum {
190 kBitFastPath = kMethodInfoBitEnd,
191 kBitInvokeTypeBegin,
192 kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3, // 3 bits for invoke type.
193 kBitSharpTypeBegin,
194 kBitSharpTypeEnd = kBitSharpTypeBegin + 3, // 3 bits for sharp type.
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100195 kBitIsReferrersClass = kBitSharpTypeEnd,
196 kBitClassIsInitialized,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800197 kBitQuickened,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100198 kMethodLoweringInfoBitEnd
Vladimir Markof096aad2014-01-23 15:51:58 +0000199 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800200 static_assert(kMethodLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markof096aad2014-01-23 15:51:58 +0000201 static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100202 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
203 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800204 static constexpr uint16_t kFlagQuickened = 1u << kBitQuickened;
Vladimir Markof096aad2014-01-23 15:51:58 +0000205 static constexpr uint16_t kInvokeTypeMask = 7u;
Andreas Gampe785d2f22014-11-03 22:57:30 -0800206 static_assert((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
207 "assert invoke type bits failed");
208 static_assert((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
209 "assert sharp type bits failed");
Vladimir Markof096aad2014-01-23 15:51:58 +0000210
211 uintptr_t direct_code_;
212 uintptr_t direct_method_;
213 // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
214 // devirtualized invoke target if available, nullptr and 0u otherwise.
215 // After Resolve() they hold the actual target method that will be called; it will be either
216 // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
217 const DexFile* target_dex_file_;
218 uint16_t target_method_idx_;
219 uint16_t vtable_idx_;
220 int stats_flags_;
Vladimir Markobfea9c22014-01-17 17:49:33 +0000221
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100222 friend class MirOptimizationTest;
Vladimir Markof096aad2014-01-23 15:51:58 +0000223};
224
225} // namespace art
226
227#endif // ART_COMPILER_DEX_MIR_METHOD_INFO_H_