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 24 namespace art { 25 26 class CompilerDriver; 27 class 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 36 class MirFieldInfo { 37 public: FieldIndex()38 uint16_t FieldIndex() const { 39 return field_idx_; 40 } 41 IsStatic()42 bool IsStatic() const { 43 return (flags_ & kFlagIsStatic) != 0u; 44 } 45 IsResolved()46 bool IsResolved() const { 47 return declaring_dex_file_ != nullptr; 48 } 49 DeclaringDexFile()50 const DexFile* DeclaringDexFile() const { 51 return declaring_dex_file_; 52 } 53 DeclaringClassIndex()54 uint16_t DeclaringClassIndex() const { 55 return declaring_class_idx_; 56 } 57 DeclaringFieldIndex()58 uint16_t DeclaringFieldIndex() const { 59 return declaring_field_idx_; 60 } 61 IsVolatile()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 MirFieldInfo(uint16_t field_idx,uint16_t flags)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 100 class 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. MirIFieldLoweringInfo(uint16_t field_idx)110 explicit MirIFieldLoweringInfo(uint16_t field_idx) 111 : MirFieldInfo(field_idx, kFlagIsVolatile), // Without kFlagIsStatic. 112 field_offset_(0u) { 113 } 114 FastGet()115 bool FastGet() const { 116 return (flags_ & kFlagFastGet) != 0u; 117 } 118 FastPut()119 bool FastPut() const { 120 return (flags_ & kFlagFastPut) != 0u; 121 } 122 FieldOffset()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 GlobalValueNumberingTest; 141 friend class LocalValueNumberingTest; 142 }; 143 144 class MirSFieldLoweringInfo : public MirFieldInfo { 145 public: 146 // For each requested static field retrieve the field's declaring location (dex file, class 147 // index and field index) and volatility and compute whether we can fast path the access with 148 // IGET/IPUT. For fast path fields (at least for IGET), retrieve the information needed for 149 // the field access, i.e. the field offset, whether the field is in the same class as the 150 // method being compiled, whether the declaring class can be safely assumed to be initialized 151 // and the type index of the declaring class in the compiled method's dex file. 152 static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit, 153 MirSFieldLoweringInfo* field_infos, size_t count) 154 LOCKS_EXCLUDED(Locks::mutator_lock_); 155 156 // Construct an unresolved static field lowering info. MirSFieldLoweringInfo(uint16_t field_idx)157 explicit MirSFieldLoweringInfo(uint16_t field_idx) 158 : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic), 159 field_offset_(0u), 160 storage_index_(DexFile::kDexNoIndex) { 161 } 162 FastGet()163 bool FastGet() const { 164 return (flags_ & kFlagFastGet) != 0u; 165 } 166 FastPut()167 bool FastPut() const { 168 return (flags_ & kFlagFastPut) != 0u; 169 } 170 IsReferrersClass()171 bool IsReferrersClass() const { 172 return (flags_ & kFlagIsReferrersClass) != 0u; 173 } 174 IsInitialized()175 bool IsInitialized() const { 176 return (flags_ & kFlagIsInitialized) != 0u; 177 } 178 FieldOffset()179 MemberOffset FieldOffset() const { 180 return field_offset_; 181 } 182 StorageIndex()183 uint32_t StorageIndex() const { 184 return storage_index_; 185 } 186 187 private: 188 enum { 189 kBitFastGet = kFieldInfoBitEnd, 190 kBitFastPut, 191 kBitIsReferrersClass, 192 kBitIsInitialized, 193 kSFieldLoweringInfoBitEnd 194 }; 195 COMPILE_ASSERT(kSFieldLoweringInfoBitEnd <= 16, too_many_flags); 196 static constexpr uint16_t kFlagFastGet = 1u << kBitFastGet; 197 static constexpr uint16_t kFlagFastPut = 1u << kBitFastPut; 198 static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass; 199 static constexpr uint16_t kFlagIsInitialized = 1u << kBitIsInitialized; 200 201 // The member offset of the field, 0u if unresolved. 202 MemberOffset field_offset_; 203 // The type index of the declaring class in the compiling method's dex file, 204 // -1 if the field is unresolved or there's no appropriate TypeId in that dex file. 205 uint32_t storage_index_; 206 207 friend class ClassInitCheckEliminationTest; 208 friend class GlobalValueNumberingTest; 209 friend class LocalValueNumberingTest; 210 }; 211 212 } // namespace art 213 214 #endif // ART_COMPILER_DEX_MIR_FIELD_INFO_H_ 215