Home | History | Annotate | Download | only in dex
      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
    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 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.
    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 
    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