blob: e97f7a00f5cce1d995599557617550b9271fb86b [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"
23
24namespace art {
25
26class CompilerDriver;
27class DexCompilationUnit;
28
29/*
30 * Field info is calculated from the perspective of the compilation unit that accesses
31 * the field and stored in that unit's MIRGraph. Therefore it does not need to reference the
32 * dex file or method for which it has been calculated. However, we do store the declaring
33 * field index, class index and dex file of the resolved field to help distinguish between fields.
34 */
35
36class MirFieldInfo {
37 public:
38 uint16_t FieldIndex() const {
39 return field_idx_;
40 }
41
42 bool IsStatic() const {
43 return (flags_ & kFlagIsStatic) != 0u;
44 }
45
46 bool IsResolved() const {
47 return declaring_dex_file_ != nullptr;
48 }
49
50 const DexFile* DeclaringDexFile() const {
51 return declaring_dex_file_;
52 }
53
54 uint16_t DeclaringClassIndex() const {
55 return declaring_class_idx_;
56 }
57
58 uint16_t DeclaringFieldIndex() const {
59 return declaring_field_idx_;
60 }
61
62 bool IsVolatile() const {
63 return (flags_ & kFlagIsVolatile) != 0u;
64 }
65
66 protected:
67 enum {
68 kBitIsStatic = 0,
69 kBitIsVolatile,
70 kFieldInfoBitEnd
71 };
72 static constexpr uint16_t kFlagIsVolatile = 1u << kBitIsVolatile;
73 static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
74
75 MirFieldInfo(uint16_t field_idx, uint16_t flags)
76 : field_idx_(field_idx),
77 flags_(flags),
78 declaring_field_idx_(0u),
79 declaring_class_idx_(0u),
80 declaring_dex_file_(nullptr) {
81 }
82
83 // Make copy-ctor/assign/dtor protected to avoid slicing.
84 MirFieldInfo(const MirFieldInfo& other) = default;
85 MirFieldInfo& operator=(const MirFieldInfo& other) = default;
86 ~MirFieldInfo() = default;
87
88 // The field index in the compiling method's dex file.
89 uint16_t field_idx_;
90 // Flags, for volatility and derived class data.
91 uint16_t flags_;
92 // The field index in the dex file that defines field, 0 if unresolved.
93 uint16_t declaring_field_idx_;
94 // The type index of the class declaring the field, 0 if unresolved.
95 uint16_t declaring_class_idx_;
96 // The dex file that defines the class containing the field and the field, nullptr if unresolved.
97 const DexFile* declaring_dex_file_;
98};
99
100class MirIFieldLoweringInfo : public MirFieldInfo {
101 public:
102 // For each requested instance field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000103 // index and field index) and volatility and compute whether we can fast path the access
Vladimir Markobe0e5462014-02-26 11:24:15 +0000104 // with IGET/IPUT. For fast path fields, retrieve the field offset.
105 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
106 MirIFieldLoweringInfo* field_infos, size_t count)
107 LOCKS_EXCLUDED(Locks::mutator_lock_);
108
109 // Construct an unresolved instance field lowering info.
110 explicit MirIFieldLoweringInfo(uint16_t field_idx)
111 : MirFieldInfo(field_idx, kFlagIsVolatile), // Without kFlagIsStatic.
112 field_offset_(0u) {
113 }
114
115 bool FastGet() const {
116 return (flags_ & kFlagFastGet) != 0u;
117 }
118
119 bool FastPut() const {
120 return (flags_ & kFlagFastPut) != 0u;
121 }
122
123 MemberOffset FieldOffset() const {
124 return field_offset_;
125 }
126
127 private:
128 enum {
129 kBitFastGet = kFieldInfoBitEnd,
130 kBitFastPut,
131 kIFieldLoweringInfoBitEnd
132 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800133 static_assert(kIFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000134 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
135 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
136
137 // The member offset of the field, 0u if unresolved.
138 MemberOffset field_offset_;
139
Vladimir Marko7baa6f82014-10-09 18:01:24 +0100140 friend class NullCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100141 friend class GlobalValueNumberingTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000142 friend class LocalValueNumberingTest;
143};
144
145class MirSFieldLoweringInfo : public MirFieldInfo {
146 public:
147 // For each requested static field retrieve the field's declaring location (dex file, class
Vladimir Markoa24122d2014-03-07 10:18:14 +0000148 // index and field index) and volatility and compute whether we can fast path the access with
Vladimir Markobe0e5462014-02-26 11:24:15 +0000149 // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
150 // the field access, i.e. the field offset, whether the field is in the same class as the
151 // method being compiled, whether the declaring class can be safely assumed to be initialized
152 // and the type index of the declaring class in the compiled method's dex file.
153 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
154 MirSFieldLoweringInfo* field_infos, size_t count)
155 LOCKS_EXCLUDED(Locks::mutator_lock_);
156
157 // Construct an unresolved static field lowering info.
158 explicit MirSFieldLoweringInfo(uint16_t field_idx)
159 : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic),
160 field_offset_(0u),
161 storage_index_(DexFile::kDexNoIndex) {
162 }
163
164 bool FastGet() const {
165 return (flags_ & kFlagFastGet) != 0u;
166 }
167
168 bool FastPut() const {
169 return (flags_ & kFlagFastPut) != 0u;
170 }
171
172 bool IsReferrersClass() const {
173 return (flags_ & kFlagIsReferrersClass) != 0u;
174 }
175
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100176 bool IsClassInitialized() const {
177 return (flags_ & kFlagClassIsInitialized) != 0u;
178 }
179
180 bool IsClassInDexCache() const {
181 return (flags_ & kFlagClassIsInDexCache) != 0u;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000182 }
183
184 MemberOffset FieldOffset() const {
185 return field_offset_;
186 }
187
188 uint32_t StorageIndex() const {
189 return storage_index_;
190 }
191
192 private:
193 enum {
194 kBitFastGet = kFieldInfoBitEnd,
195 kBitFastPut,
196 kBitIsReferrersClass,
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100197 kBitClassIsInitialized,
198 kBitClassIsInDexCache,
Vladimir Markobe0e5462014-02-26 11:24:15 +0000199 kSFieldLoweringInfoBitEnd
200 };
Andreas Gampe785d2f22014-11-03 22:57:30 -0800201 static_assert(kSFieldLoweringInfoBitEnd <= 16, "Too many flags");
Vladimir Markobe0e5462014-02-26 11:24:15 +0000202 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
203 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
204 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
Vladimir Marko66c6d7b2014-10-16 15:41:48 +0100205 static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
206 static constexpr uint16_t kFlagClassIsInDexCache = 1u << kBitClassIsInDexCache;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000207
208 // The member offset of the field, 0u if unresolved.
209 MemberOffset field_offset_;
210 // The type index of the declaring class in the compiling method's dex file,
211 // -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
212 uint32_t storage_index_;
213
Vladimir Markobfea9c22014-01-17 17:49:33 +0000214 friend class ClassInitCheckEliminationTest;
Vladimir Marko95a05972014-05-30 10:01:32 +0100215 friend class GlobalValueNumberingTest;
Vladimir Markobe0e5462014-02-26 11:24:15 +0000216 friend class LocalValueNumberingTest;
217};
218
219} // namespace art
220
221#endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_