mir_field_info.h revision a24122dc3aaa74b0385bb0ce30959f8a19c4a300
1/*
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
103  // index and field index) and volatility and compute whether we can fast path the access
104  // 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  };
133  COMPILE_ASSERT(kIFieldLoweringInfoBitEnd <= 16, too_many_flags);
134  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
140  friend class LocalValueNumberingTest;
141};
142
143class MirSFieldLoweringInfo : public MirFieldInfo {
144 public:
145  // For each requested static field retrieve the field's declaring location (dex file, class
146  // index and field index) and volatility and compute whether we can fast path the access with
147  // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for
148  // the field access, i.e. the field offset, whether the field is in the same class as the
149  // method being compiled, whether the declaring class can be safely assumed to be initialized
150  // and the type index of the declaring class in the compiled method's dex file.
151  static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
152                      MirSFieldLoweringInfo* field_infos, size_t count)
153      LOCKS_EXCLUDED(Locks::mutator_lock_);
154
155  // Construct an unresolved static field lowering info.
156  explicit MirSFieldLoweringInfo(uint16_t field_idx)
157      : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic),
158        field_offset_(0u),
159        storage_index_(DexFile::kDexNoIndex) {
160  }
161
162  bool FastGet() const {
163    return (flags_ & kFlagFastGet) != 0u;
164  }
165
166  bool FastPut() const {
167    return (flags_ & kFlagFastPut) != 0u;
168  }
169
170  bool IsReferrersClass() const {
171    return (flags_ & kFlagIsReferrersClass) != 0u;
172  }
173
174  bool IsInitialized() const {
175    return (flags_ & kFlagIsInitialized) != 0u;
176  }
177
178  MemberOffset FieldOffset() const {
179    return field_offset_;
180  }
181
182  uint32_t StorageIndex() const {
183    return storage_index_;
184  }
185
186 private:
187  enum {
188    kBitFastGet = kFieldInfoBitEnd,
189    kBitFastPut,
190    kBitIsReferrersClass,
191    kBitIsInitialized,
192    kSFieldLoweringInfoBitEnd
193  };
194  COMPILE_ASSERT(kSFieldLoweringInfoBitEnd <= 16, too_many_flags);
195  static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet;
196  static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut;
197  static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
198  static constexpr uint16_t kFlagIsInitialized = 1u << kBitIsInitialized;
199
200  // The member offset of the field, 0u if unresolved.
201  MemberOffset field_offset_;
202  // The type index of the declaring class in the compiling method's dex file,
203  // -1 if the field is unresolved or there's no appropriate TypeId in that dex file.
204  uint32_t storage_index_;
205
206  friend class LocalValueNumberingTest;
207};
208
209}  // namespace art
210
211#endif  // ART_COMPILER_DEX_MIR_FIELD_INFO_H_
212