blob: b6dc27d26eece6a6efeae153f41111a9a2c8865b [file] [log] [blame]
Vladimir Markobe0e5462014-02-26 11:24:15 +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_FIELD_INFO_H_
18#define ART_COMPILER_DEX_MIR_FIELD_INFO_H_
19
20#include "base/macros.h"
21#include "dex_file.h"
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080022#include "dex_instruction_utils.h"
Vladimir Markobe0e5462014-02-26 11:24:15 +000023#include "offsets.h"
24
25namespace art {
26
27class CompilerDriver;
28class DexCompilationUnit;
Mathieu Chartier736b5602015-09-02 14:54:11 -070029class ScopedObjectAccess;
Vladimir Markobe0e5462014-02-26 11:24:15 +000030
31/*
32 * Field info is calculated from the perspective of the compilation unit that accesses
33 * the field and stored in that unit's MIRGraph. Therefore it does not need to reference the
34 * dex file or method for which it has been calculated. However, we do store the declaring
35 * field index, class index and dex file of the resolved field to help distinguish between fields.
36 */
37
38class MirFieldInfo {
39 public:
40 uint16_t FieldIndex() const {
41 return field_idx_;
42 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080043 void SetFieldIndex(uint16_t field_idx) {
44 field_idx_ = field_idx;
45 }
Vladimir Markobe0e5462014-02-26 11:24:15 +000046
47 bool IsStatic() const {
48 return (flags_ & kFlagIsStatic) != 0u;
49 }
50
51 bool IsResolved() const {
52 return declaring_dex_file_ != nullptr;
53 }
54
55 const DexFile* DeclaringDexFile() const {
56 return declaring_dex_file_;
57 }
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080058 void SetDeclaringDexFile(const DexFile* dex_file) {
59 declaring_dex_file_ = dex_file;
60 }
Vladimir Markobe0e5462014-02-26 11:24:15 +000061
62 uint16_t DeclaringClassIndex() const {
63 return declaring_class_idx_;
64 }
65
66 uint16_t DeclaringFieldIndex() const {
67 return declaring_field_idx_;
68 }
69
70 bool IsVolatile() const {
71 return (flags_ & kFlagIsVolatile) != 0u;
72 }
73
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080074 // IGET_QUICK, IGET_BYTE_QUICK, ...
75 bool IsQuickened() const {
76 return (flags_ & kFlagIsQuickened) != 0u;
77 }
78
Vladimir Markoaf6925b2014-10-31 16:37:32 +000079 DexMemAccessType MemAccessType() const {
80 return static_cast<DexMemAccessType>((flags_ >> kBitMemAccessTypeBegin) & kMemAccessTypeMask);
81 }
82
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080083 void CheckEquals(const MirFieldInfo& other) const {
84 CHECK_EQ(field_idx_, other.field_idx_);
85 CHECK_EQ(flags_, other.flags_);
86 CHECK_EQ(declaring_field_idx_, other.declaring_field_idx_);
87 CHECK_EQ(declaring_class_idx_, other.declaring_class_idx_);
88 CHECK_EQ(declaring_dex_file_, other.declaring_dex_file_);
89 }
90
Vladimir Markobe0e5462014-02-26 11:24:15 +000091 protected:
92 enum {
93 kBitIsStatic = 0,
94 kBitIsVolatile,
Mathieu Chartiere5f13e52015-02-24 09:37:21 -080095 kBitIsQuickened,
Vladimir Markoaf6925b2014-10-31 16:37:32 +000096 kBitMemAccessTypeBegin,
97 kBitMemAccessTypeEnd = kBitMemAccessTypeBegin + 3, // 3 bits for raw type.
98 kFieldInfoBitEnd = kBitMemAccessTypeEnd
Vladimir Markobe0e5462014-02-26 11:24:15 +000099 };
100 static constexpr uint16_t kFlagIsVolatile = 1u << kBitIsVolatile;
101 static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800102 static constexpr uint16_t kFlagIsQuickened = 1u << kBitIsQuickened;
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000103 static constexpr uint16_t kMemAccessTypeMask = 7u;
104 static_assert((1u << (kBitMemAccessTypeEnd - kBitMemAccessTypeBegin)) - 1u == kMemAccessTypeMask,
105 "Invalid raw type mask");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000106
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000107 MirFieldInfo(uint16_t field_idx, uint16_t flags, DexMemAccessType type)
Vladimir Markobe0e5462014-02-26 11:24:15 +0000108 : field_idx_(field_idx),
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000109 flags_(flags | static_cast<uint16_t>(type) << kBitMemAccessTypeBegin),
Vladimir Markobe0e5462014-02-26 11:24:15 +0000110 declaring_field_idx_(0u),
111 declaring_class_idx_(0u),
112 declaring_dex_file_(nullptr) {
113 }
114
115 // Make copy-ctor/assign/dtor protected to avoid slicing.
116 MirFieldInfo(const MirFieldInfo& other) = default;
117 MirFieldInfo& operator=(const MirFieldInfo& other) = default;
118 ~MirFieldInfo() = default;
119
120 // The field index in the compiling method's dex file.
121 uint16_t field_idx_;
122 // Flags, for volatility and derived class data.
123 uint16_t flags_;
124 // The field index in the dex file that defines field, 0 if unresolved.
125 uint16_t declaring_field_idx_;
126 // The type index of the class declaring the field, 0 if unresolved.
127 uint16_t declaring_class_idx_;
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700128 // The dex file that defines the class containing the field and the field, null if unresolved.
Vladimir Markobe0e5462014-02-26 11:24:15 +0000129 const DexFile* declaring_dex_file_;
130};
131
132class MirIFieldLoweringInfo : public MirFieldInfo {
133 public:
134 // For each requested instance field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000135 // index and field index) and volatility and compute whether we can fast path the access
Vladimir Markobe0e5462014-02-26 11:24:15 +0000136 // with IGET/IPUT. For fast path fields, retrieve the field offset.
Mathieu Chartier736b5602015-09-02 14:54:11 -0700137 static void Resolve(const ScopedObjectAccess& soa,
138 CompilerDriver* compiler_driver,
139 const DexCompilationUnit* mUnit,
140 MirIFieldLoweringInfo* field_infos,
141 size_t count)
142 SHARED_REQUIRES(Locks::mutator_lock_);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000143
144 // Construct an unresolved instance field lowering info.
Roland Levillain3887c462015-08-12 18:15:42 +0100145 MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type, bool is_quickened)
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800146 : MirFieldInfo(field_idx,
147 kFlagIsVolatile | (is_quickened ? kFlagIsQuickened : 0u),
148 type), // Without kFlagIsStatic.
Vladimir Markobe0e5462014-02-26 11:24:15 +0000149 field_offset_(0u) {
150 }
151
152 bool FastGet() const {
153 return (flags_ & kFlagFastGet) != 0u;
154 }
155
156 bool FastPut() const {
157 return (flags_ & kFlagFastPut) != 0u;
158 }
159
160 MemberOffset FieldOffset() const {
161 return field_offset_;
162 }
163
Mathieu Chartiere5f13e52015-02-24 09:37:21 -0800164 void CheckEquals(const MirIFieldLoweringInfo& other) const {
165 MirFieldInfo::CheckEquals(other);
166 CHECK_EQ(field_offset_.Uint32Value(), other.field_offset_.Uint32Value());
167 }
168
Vladimir Markobe0e5462014-02-26 11:24:15 +0000169 private:
170 enum {
171 kBitFastGet = kFieldInfoBitEnd,
172 kBitFastPut,
173 kIFieldLoweringInfoBitEnd
174 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800175 static_assert(kIFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000176 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
177 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
178
179 // The member offset of the field, 0u if unresolved.
180 MemberOffset field_offset_;
181
Vladimir Marko7baa6f82014-10-09 18:01:24 +0100182 friend class NullCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100183 friend class GlobalValueNumberingTest;
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000184 friend class GvnDeadCodeEliminationTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000185 friend class LocalValueNumberingTest;
Vladimir Markoc91df2d2015-04-23 09:29:21 +0000186 friend class TypeInferenceTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000187};
188
189class MirSFieldLoweringInfo : public MirFieldInfo {
190 public:
191 // For each requested static field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000192 // index and field index) and volatility and compute whether we can fast path the access with
Vladimir Markobe0e5462014-02-26 11:24:15 +0000193 // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
194 // the field access, i.e. the field offset, whether the field is in the same class as the
195 // method being compiled, whether the declaring class can be safely assumed to be initialized
196 // and the type index of the declaring class in the compiled method's dex file.
197 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
198 MirSFieldLoweringInfo* field_infos, size_t count)
Mathieu Chartier90443472015-07-16 20:32:27 -0700199 REQUIRES(!Locks::mutator_lock_);
Vladimir Markobe0e5462014-02-26 11:24:15 +0000200
201 // Construct an unresolved static field lowering info.
Roland Levillain3887c462015-08-12 18:15:42 +0100202 MirSFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type)
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000203 : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic, type),
Vladimir Markobe0e5462014-02-26 11:24:15 +0000204 field_offset_(0u),
205 storage_index_(DexFile::kDexNoIndex) {
206 }
207
208 bool FastGet() const {
209 return (flags_ & kFlagFastGet) != 0u;
210 }
211
212 bool FastPut() const {
213 return (flags_ & kFlagFastPut) != 0u;
214 }
215
216 bool IsReferrersClass() const {
217 return (flags_ & kFlagIsReferrersClass) != 0u;
218 }
219
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100220 bool IsClassInitialized() const {
221 return (flags_ & kFlagClassIsInitialized) != 0u;
222 }
223
224 bool IsClassInDexCache() const {
225 return (flags_ & kFlagClassIsInDexCache) != 0u;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000226 }
227
228 MemberOffset FieldOffset() const {
229 return field_offset_;
230 }
231
232 uint32_t StorageIndex() const {
233 return storage_index_;
234 }
235
236 private:
237 enum {
238 kBitFastGet = kFieldInfoBitEnd,
239 kBitFastPut,
240 kBitIsReferrersClass,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100241 kBitClassIsInitialized,
242 kBitClassIsInDexCache,
Vladimir Markobe0e5462014-02-26 11:24:15 +0000243 kSFieldLoweringInfoBitEnd
244 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800245 static_assert(kSFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000246 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
247 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
248 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100249 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
250 static constexpr uint16_t kFlagClassIsInDexCache = 1u << kBitClassIsInDexCache;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000251
252 // The member offset of the field, 0u if unresolved.
253 MemberOffset field_offset_;
254 // The type index of the declaring class in the compiling method's dex file,
255 // -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
256 uint32_t storage_index_;
257
Vladimir Markobfea9c22014-01-17 17:49:33 +0000258 friend class ClassInitCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100259 friend class GlobalValueNumberingTest;
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000260 friend class GvnDeadCodeEliminationTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000261 friend class LocalValueNumberingTest;
Vladimir Markoc91df2d2015-04-23 09:29:21 +0000262 friend class TypeInferenceTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000263};
264
265} // namespace art
266
267#endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_