| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 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: | 
 | 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 |  | 
 | 100 | class MirIFieldLoweringInfo : public MirFieldInfo { | 
 | 101 |  public: | 
 | 102 |   // For each requested instance field retrieve the field's declaring location (dex file, class | 
| Vladimir Marko | a24122d | 2014-03-07 10:18:14 +0000 | [diff] [blame] | 103 |   // index and field index) and volatility and compute whether we can fast path the access | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 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 |  | 
| Vladimir Marko | 95a0597 | 2014-05-30 10:01:32 +0100 | [diff] [blame] | 140 |   friend class GlobalValueNumberingTest; | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 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 | 
| Vladimir Marko | a24122d | 2014-03-07 10:18:14 +0000 | [diff] [blame] | 147 |   // index and field index) and volatility and compute whether we can fast path the access with | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 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. | 
 | 157 |   explicit MirSFieldLoweringInfo(uint16_t field_idx) | 
 | 158 |       : MirFieldInfo(field_idx, kFlagIsVolatile | kFlagIsStatic), | 
 | 159 |         field_offset_(0u), | 
 | 160 |         storage_index_(DexFile::kDexNoIndex) { | 
 | 161 |   } | 
 | 162 |  | 
 | 163 |   bool FastGet() const { | 
 | 164 |     return (flags_ & kFlagFastGet) != 0u; | 
 | 165 |   } | 
 | 166 |  | 
 | 167 |   bool FastPut() const { | 
 | 168 |     return (flags_ & kFlagFastPut) != 0u; | 
 | 169 |   } | 
 | 170 |  | 
 | 171 |   bool IsReferrersClass() const { | 
 | 172 |     return (flags_ & kFlagIsReferrersClass) != 0u; | 
 | 173 |   } | 
 | 174 |  | 
 | 175 |   bool IsInitialized() const { | 
 | 176 |     return (flags_ & kFlagIsInitialized) != 0u; | 
 | 177 |   } | 
 | 178 |  | 
 | 179 |   MemberOffset FieldOffset() const { | 
 | 180 |     return field_offset_; | 
 | 181 |   } | 
 | 182 |  | 
 | 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 |  | 
| Vladimir Marko | bfea9c2 | 2014-01-17 17:49:33 +0000 | [diff] [blame] | 207 |   friend class ClassInitCheckEliminationTest; | 
| Vladimir Marko | 95a0597 | 2014-05-30 10:01:32 +0100 | [diff] [blame] | 208 |   friend class GlobalValueNumberingTest; | 
| Vladimir Marko | be0e546 | 2014-02-26 11:24:15 +0000 | [diff] [blame] | 209 |   friend class LocalValueNumberingTest; | 
 | 210 | }; | 
 | 211 |  | 
 | 212 | }  // namespace art | 
 | 213 |  | 
 | 214 | #endif  // ART_COMPILER_DEX_MIR_FIELD_INFO_H_ |