blob: 946c74becf7d442a5ad00ab4eb7d1e086747c320 [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,
Mathieu Chartier2cebb242015-04-21 16:50:40 -070091 // null if unresolved.
Vladimir Markof096aad2014-01-23 15:51:58 +000092 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 Marko87b7c522015-04-08 10:01:01 +0100130 bool IsIntrinsic() const {
131 return (flags_ & kFlagIsIntrinsic) != 0u;
132 }
133
134 bool IsSpecial() const {
135 return (flags_ & kFlagIsSpecial) != 0u;
136 }
137
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100138 bool IsReferrersClass() const {
139 return (flags_ & kFlagIsReferrersClass) != 0;
140 }
141
142 bool IsClassInitialized() const {
143 return (flags_ & kFlagClassIsInitialized) != 0u;
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000144 }
145
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800146 // Returns true iff the method invoke is INVOKE_VIRTUAL_QUICK or INVOKE_VIRTUAL_RANGE_QUICK.
147 bool IsQuickened() const {
148 return (flags_ & kFlagQuickened) != 0u;
149 }
150
Vladimir Markof096aad2014-01-23 15:51:58 +0000151 InvokeType GetInvokeType() const {
152 return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
153 }
154
155 art::InvokeType GetSharpType() const {
156 return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
157 }
158
159 MethodReference GetTargetMethod() const {
160 return MethodReference(target_dex_file_, target_method_idx_);
161 }
162
163 uint16_t VTableIndex() const {
164 return vtable_idx_;
165 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800166 void SetVTableIndex(uint16_t index) {
167 vtable_idx_ = index;
168 }
Vladimir Markof096aad2014-01-23 15:51:58 +0000169
170 uintptr_t DirectCode() const {
171 return direct_code_;
172 }
173
174 uintptr_t DirectMethod() const {
175 return direct_method_;
176 }
177
178 int StatsFlags() const {
179 return stats_flags_;
180 }
181
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800182 void CheckEquals(const MirMethodLoweringInfo& info) const {
183 CHECK_EQ(method_idx_, info.method_idx_);
184 CHECK_EQ(flags_, info.flags_);
185 CHECK_EQ(declaring_method_idx_, info.declaring_method_idx_);
186 CHECK_EQ(declaring_class_idx_, info.declaring_class_idx_);
187 CHECK_EQ(declaring_dex_file_, info.declaring_dex_file_);
188 CHECK_EQ(direct_code_, info.direct_code_);
189 CHECK_EQ(direct_method_, info.direct_method_);
190 CHECK_EQ(target_dex_file_, info.target_dex_file_);
191 CHECK_EQ(target_method_idx_, info.target_method_idx_);
192 CHECK_EQ(vtable_idx_, info.vtable_idx_);
193 CHECK_EQ(stats_flags_, info.stats_flags_);
194 }
195
Vladimir Markof096aad2014-01-23 15:51:58 +0000196 private:
197 enum {
198 kBitFastPath = kMethodInfoBitEnd,
Vladimir Marko87b7c522015-04-08 10:01:01 +0100199 kBitIsIntrinsic,
200 kBitIsSpecial,
Vladimir Markof096aad2014-01-23 15:51:58 +0000201 kBitInvokeTypeBegin,
202 kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3, // 3 bits for invoke type.
Vladimir Marko87b7c522015-04-08 10:01:01 +0100203 kBitSharpTypeBegin = kBitInvokeTypeEnd,
Vladimir Markof096aad2014-01-23 15:51:58 +0000204 kBitSharpTypeEnd = kBitSharpTypeBegin + 3, // 3 bits for sharp type.
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100205 kBitIsReferrersClass = kBitSharpTypeEnd,
206 kBitClassIsInitialized,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800207 kBitQuickened,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100208 kMethodLoweringInfoBitEnd
Vladimir Markof096aad2014-01-23 15:51:58 +0000209 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800210 static_assert(kMethodLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markof096aad2014-01-23 15:51:58 +0000211 static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
Vladimir Marko87b7c522015-04-08 10:01:01 +0100212 static constexpr uint16_t kFlagIsIntrinsic = 1u << kBitIsIntrinsic;
213 static constexpr uint16_t kFlagIsSpecial = 1u << kBitIsSpecial;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100214 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
215 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800216 static constexpr uint16_t kFlagQuickened = 1u << kBitQuickened;
Vladimir Markof096aad2014-01-23 15:51:58 +0000217 static constexpr uint16_t kInvokeTypeMask = 7u;
Andreas Gampe785d2f22014-11-03 22:57:30 -0800218 static_assert((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
219 "assert invoke type bits failed");
220 static_assert((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
221 "assert sharp type bits failed");
Vladimir Markof096aad2014-01-23 15:51:58 +0000222
223 uintptr_t direct_code_;
224 uintptr_t direct_method_;
225 // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700226 // devirtualized invoke target if available, null and 0u otherwise.
Vladimir Markof096aad2014-01-23 15:51:58 +0000227 // After Resolve() they hold the actual target method that will be called; it will be either
228 // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
229 const DexFile* target_dex_file_;
230 uint16_t target_method_idx_;
231 uint16_t vtable_idx_;
232 int stats_flags_;
Vladimir Markobfea9c22014-01-17 17:49:33 +0000233
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100234 friend class MirOptimizationTest;
Vladimir Markoc91df2d2015-04-23 09:29:21 +0000235 friend class TypeInferenceTest;
Vladimir Markof096aad2014-01-23 15:51:58 +0000236};
237
238} // namespace art
239
240#endif // ART_COMPILER_DEX_MIR_METHOD_INFO_H_