blob: 98b2da829937bdb8267830ab95db9b0096c38094 [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"
22#include "offsets.h"
Vladimir Markoaf6925b2014-10-31 16:37:32 +000023#include "utils/dex_instruction_utils.h"
Vladimir Markobe0e5462014-02-26 11:24:15 +000024
25namespace art {
26
27class CompilerDriver;
28class DexCompilationUnit;
29
30/*
31 * Field info is calculated from the perspective of the compilation unit that accesses
32 * the field and stored in that unit's MIRGraph. Therefore it does not need to reference the
33 * dex file or method for which it has been calculated. However, we do store the declaring
34 * field index, class index and dex file of the resolved field to help distinguish between fields.
35 */
36
37class MirFieldInfo {
38 public:
39 uint16_t FieldIndex() const {
40 return field_idx_;
41 }
42
43 bool IsStatic() const {
44 return (flags_ & kFlagIsStatic) != 0u;
45 }
46
47 bool IsResolved() const {
48 return declaring_dex_file_ != nullptr;
49 }
50
51 const DexFile* DeclaringDexFile() const {
52 return declaring_dex_file_;
53 }
54
55 uint16_t DeclaringClassIndex() const {
56 return declaring_class_idx_;
57 }
58
59 uint16_t DeclaringFieldIndex() const {
60 return declaring_field_idx_;
61 }
62
63 bool IsVolatile() const {
64 return (flags_ & kFlagIsVolatile) != 0u;
65 }
66
Vladimir Markoaf6925b2014-10-31 16:37:32 +000067 DexMemAccessType MemAccessType() const {
68 return static_cast<DexMemAccessType>((flags_ >> kBitMemAccessTypeBegin) & kMemAccessTypeMask);
69 }
70
Vladimir Markobe0e5462014-02-26 11:24:15 +000071 protected:
72 enum {
73 kBitIsStatic = 0,
74 kBitIsVolatile,
Vladimir Markoaf6925b2014-10-31 16:37:32 +000075 kBitMemAccessTypeBegin,
76 kBitMemAccessTypeEnd = kBitMemAccessTypeBegin + 3, // 3 bits for raw type.
77 kFieldInfoBitEnd = kBitMemAccessTypeEnd
Vladimir Markobe0e5462014-02-26 11:24:15 +000078 };
79 static constexpr uint16_t kFlagIsVolatile = 1u << kBitIsVolatile;
80 static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
Vladimir Markoaf6925b2014-10-31 16:37:32 +000081 static constexpr uint16_t kMemAccessTypeMask = 7u;
82 static_assert((1u << (kBitMemAccessTypeEnd - kBitMemAccessTypeBegin)) - 1u == kMemAccessTypeMask,
83 "Invalid raw type mask");
Vladimir Markobe0e5462014-02-26 11:24:15 +000084
Vladimir Markoaf6925b2014-10-31 16:37:32 +000085 MirFieldInfo(uint16_t field_idx, uint16_t flags, DexMemAccessType type)
Vladimir Markobe0e5462014-02-26 11:24:15 +000086 : field_idx_(field_idx),
Vladimir Markoaf6925b2014-10-31 16:37:32 +000087 flags_(flags | static_cast<uint16_t>(type) << kBitMemAccessTypeBegin),
Vladimir Markobe0e5462014-02-26 11:24:15 +000088 declaring_field_idx_(0u),
89 declaring_class_idx_(0u),
90 declaring_dex_file_(nullptr) {
91 }
92
93 // Make copy-ctor/assign/dtor protected to avoid slicing.
94 MirFieldInfo(const MirFieldInfo& other) = default;
95 MirFieldInfo& operator=(const MirFieldInfo& other) = default;
96 ~MirFieldInfo() = default;
97
98 // The field index in the compiling method's dex file.
99 uint16_t field_idx_;
100 // Flags, for volatility and derived class data.
101 uint16_t flags_;
102 // The field index in the dex file that defines field, 0 if unresolved.
103 uint16_t declaring_field_idx_;
104 // The type index of the class declaring the field, 0 if unresolved.
105 uint16_t declaring_class_idx_;
106 // The dex file that defines the class containing the field and the field, nullptr if unresolved.
107 const DexFile* declaring_dex_file_;
108};
109
110class MirIFieldLoweringInfo : public MirFieldInfo {
111 public:
112 // For each requested instance field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000113 // index and field index) and volatility and compute whether we can fast path the access
Vladimir Markobe0e5462014-02-26 11:24:15 +0000114 // with IGET/IPUT. For fast path fields, retrieve the field offset.
115 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
116 MirIFieldLoweringInfo* field_infos, size_t count)
117 LOCKS_EXCLUDED(Locks::mutator_lock_);
118
119 // Construct an unresolved instance field lowering info.
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000120 explicit MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type)
121 : MirFieldInfo(field_idx, kFlagIsVolatile, type), // Without kFlagIsStatic.
Vladimir Markobe0e5462014-02-26 11:24:15 +0000122 field_offset_(0u) {
123 }
124
125 bool FastGet() const {
126 return (flags_ & kFlagFastGet) != 0u;
127 }
128
129 bool FastPut() const {
130 return (flags_ & kFlagFastPut) != 0u;
131 }
132
133 MemberOffset FieldOffset() const {
134 return field_offset_;
135 }
136
137 private:
138 enum {
139 kBitFastGet = kFieldInfoBitEnd,
140 kBitFastPut,
141 kIFieldLoweringInfoBitEnd
142 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800143 static_assert(kIFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000144 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
145 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
146
147 // The member offset of the field, 0u if unresolved.
148 MemberOffset field_offset_;
149
Vladimir Marko7baa6f82014-10-09 18:01:24 +0100150 friend class NullCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100151 friend class GlobalValueNumberingTest;
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000152 friend class GvnDeadCodeEliminationTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000153 friend class LocalValueNumberingTest;
154};
155
156class MirSFieldLoweringInfo : public MirFieldInfo {
157 public:
158 // For each requested static field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000159 // index and field index) and volatility and compute whether we can fast path the access with
Vladimir Markobe0e5462014-02-26 11:24:15 +0000160 // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
161 // the field access, i.e. the field offset, whether the field is in the same class as the
162 // method being compiled, whether the declaring class can be safely assumed to be initialized
163 // and the type index of the declaring class in the compiled method's dex file.
164 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
165 MirSFieldLoweringInfo* field_infos, size_t count)
166 LOCKS_EXCLUDED(Locks::mutator_lock_);
167
168 // Construct an unresolved static field lowering info.
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000169 explicit MirSFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type)
170 : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic, type),
Vladimir Markobe0e5462014-02-26 11:24:15 +0000171 field_offset_(0u),
172 storage_index_(DexFile::kDexNoIndex) {
173 }
174
175 bool FastGet() const {
176 return (flags_ & kFlagFastGet) != 0u;
177 }
178
179 bool FastPut() const {
180 return (flags_ & kFlagFastPut) != 0u;
181 }
182
183 bool IsReferrersClass() const {
184 return (flags_ & kFlagIsReferrersClass) != 0u;
185 }
186
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100187 bool IsClassInitialized() const {
188 return (flags_ & kFlagClassIsInitialized) != 0u;
189 }
190
191 bool IsClassInDexCache() const {
192 return (flags_ & kFlagClassIsInDexCache) != 0u;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000193 }
194
195 MemberOffset FieldOffset() const {
196 return field_offset_;
197 }
198
199 uint32_t StorageIndex() const {
200 return storage_index_;
201 }
202
203 private:
204 enum {
205 kBitFastGet = kFieldInfoBitEnd,
206 kBitFastPut,
207 kBitIsReferrersClass,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100208 kBitClassIsInitialized,
209 kBitClassIsInDexCache,
Vladimir Markobe0e5462014-02-26 11:24:15 +0000210 kSFieldLoweringInfoBitEnd
211 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800212 static_assert(kSFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000213 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
214 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
215 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100216 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
217 static constexpr uint16_t kFlagClassIsInDexCache = 1u << kBitClassIsInDexCache;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000218
219 // The member offset of the field, 0u if unresolved.
220 MemberOffset field_offset_;
221 // The type index of the declaring class in the compiling method's dex file,
222 // -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
223 uint32_t storage_index_;
224
Vladimir Markobfea9c22014-01-17 17:49:33 +0000225 friend class ClassInitCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100226 friend class GlobalValueNumberingTest;
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000227 friend class GvnDeadCodeEliminationTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000228 friend class LocalValueNumberingTest;
229};
230
231} // namespace art
232
233#endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_