blob: ff427f88d0e81b4561094edd58db5d4654a2326d [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 Markobe0e5462014-02-26 11:24:15 +0000152 friend class LocalValueNumberingTest;
153};
154
155class MirSFieldLoweringInfo : public MirFieldInfo {
156 public:
157 // For each requested static field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000158 // index and field index) and volatility and compute whether we can fast path the access with
Vladimir Markobe0e5462014-02-26 11:24:15 +0000159 // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
160 // the field access, i.e. the field offset, whether the field is in the same class as the
161 // method being compiled, whether the declaring class can be safely assumed to be initialized
162 // and the type index of the declaring class in the compiled method's dex file.
163 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
164 MirSFieldLoweringInfo* field_infos, size_t count)
165 LOCKS_EXCLUDED(Locks::mutator_lock_);
166
167 // Construct an unresolved static field lowering info.
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000168 explicit MirSFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type)
169 : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic, type),
Vladimir Markobe0e5462014-02-26 11:24:15 +0000170 field_offset_(0u),
171 storage_index_(DexFile::kDexNoIndex) {
172 }
173
174 bool FastGet() const {
175 return (flags_ & kFlagFastGet) != 0u;
176 }
177
178 bool FastPut() const {
179 return (flags_ & kFlagFastPut) != 0u;
180 }
181
182 bool IsReferrersClass() const {
183 return (flags_ & kFlagIsReferrersClass) != 0u;
184 }
185
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100186 bool IsClassInitialized() const {
187 return (flags_ & kFlagClassIsInitialized) != 0u;
188 }
189
190 bool IsClassInDexCache() const {
191 return (flags_ & kFlagClassIsInDexCache) != 0u;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000192 }
193
194 MemberOffset FieldOffset() const {
195 return field_offset_;
196 }
197
198 uint32_t StorageIndex() const {
199 return storage_index_;
200 }
201
202 private:
203 enum {
204 kBitFastGet = kFieldInfoBitEnd,
205 kBitFastPut,
206 kBitIsReferrersClass,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100207 kBitClassIsInitialized,
208 kBitClassIsInDexCache,
Vladimir Markobe0e5462014-02-26 11:24:15 +0000209 kSFieldLoweringInfoBitEnd
210 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800211 static_assert(kSFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000212 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
213 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
214 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100215 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
216 static constexpr uint16_t kFlagClassIsInDexCache = 1u << kBitClassIsInDexCache;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000217
218 // The member offset of the field, 0u if unresolved.
219 MemberOffset field_offset_;
220 // The type index of the declaring class in the compiling method's dex file,
221 // -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
222 uint32_t storage_index_;
223
Vladimir Markobfea9c22014-01-17 17:49:33 +0000224 friend class ClassInitCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100225 friend class GlobalValueNumberingTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000226 friend class LocalValueNumberingTest;
227};
228
229} // namespace art
230
231#endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_