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_METHOD_INFO_H_
     18 #define ART_COMPILER_DEX_MIR_METHOD_INFO_H_
     19 
     20 #include "base/logging.h"
     21 #include "base/macros.h"
     22 #include "base/mutex.h"
     23 #include "invoke_type.h"
     24 #include "method_reference.h"
     25 
     26 namespace art {
     27 
     28 class CompilerDriver;
     29 class DexCompilationUnit;
     30 class DexFile;
     31 
     32 class MirMethodInfo {
     33  public:
     34   uint16_t MethodIndex() const {
     35     return method_idx_;
     36   }
     37 
     38   bool IsStatic() const {
     39     return (flags_ & kFlagIsStatic) != 0u;
     40   }
     41 
     42   bool IsResolved() const {
     43     return declaring_dex_file_ != nullptr;
     44   }
     45 
     46   const DexFile* DeclaringDexFile() const {
     47     return declaring_dex_file_;
     48   }
     49   void SetDeclaringDexFile(const DexFile* dex_file) {
     50     declaring_dex_file_ = dex_file;
     51   }
     52 
     53   uint16_t DeclaringClassIndex() const {
     54     return declaring_class_idx_;
     55   }
     56 
     57   uint16_t DeclaringMethodIndex() const {
     58     return declaring_method_idx_;
     59   }
     60 
     61  protected:
     62   enum {
     63     kBitIsStatic = 0,
     64     kMethodInfoBitEnd
     65   };
     66   static_assert(kMethodInfoBitEnd <= 16, "Too many flags");
     67   static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
     68 
     69   MirMethodInfo(uint16_t method_idx, uint16_t flags)
     70       : method_idx_(method_idx),
     71         flags_(flags),
     72         declaring_method_idx_(0u),
     73         declaring_class_idx_(0u),
     74         declaring_dex_file_(nullptr) {
     75   }
     76 
     77   // Make copy-ctor/assign/dtor protected to avoid slicing.
     78   MirMethodInfo(const MirMethodInfo& other) = default;
     79   MirMethodInfo& operator=(const MirMethodInfo& other) = default;
     80   ~MirMethodInfo() = default;
     81 
     82   // The method index in the compiling method's dex file.
     83   uint16_t method_idx_;
     84   // Flags, for volatility and derived class data.
     85   uint16_t flags_;
     86   // The method index in the dex file that defines the method, 0 if unresolved.
     87   uint16_t declaring_method_idx_;
     88   // The type index of the class declaring the method, 0 if unresolved.
     89   uint16_t declaring_class_idx_;
     90   // The dex file that defines the class containing the method and the method,
     91   // null if unresolved.
     92   const DexFile* declaring_dex_file_;
     93 };
     94 
     95 class MirMethodLoweringInfo : public MirMethodInfo {
     96  public:
     97   // For each requested method retrieve the method's declaring location (dex file, class
     98   // index and method index) and compute whether we can fast path the method call. For fast
     99   // path methods, retrieve the method's vtable index and direct code and method when applicable.
    100   static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
    101                       MirMethodLoweringInfo* method_infos, size_t count)
    102       LOCKS_EXCLUDED(Locks::mutator_lock_);
    103 
    104   MirMethodLoweringInfo(uint16_t method_idx, InvokeType type, bool is_quickened)
    105       : MirMethodInfo(method_idx,
    106                       ((type == kStatic) ? kFlagIsStatic : 0u) |
    107                       (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
    108                       (static_cast<uint16_t>(type) << kBitSharpTypeBegin) |
    109                       (is_quickened ? kFlagQuickened : 0u)),
    110         direct_code_(0u),
    111         direct_method_(0u),
    112         target_dex_file_(nullptr),
    113         target_method_idx_(0u),
    114         vtable_idx_(0u),
    115         stats_flags_(0) {
    116   }
    117 
    118   void SetDevirtualizationTarget(const MethodReference& ref) {
    119     DCHECK(target_dex_file_ == nullptr);
    120     DCHECK_EQ(target_method_idx_, 0u);
    121     DCHECK_LE(ref.dex_method_index, 0xffffu);
    122     target_dex_file_ = ref.dex_file;
    123     target_method_idx_ = ref.dex_method_index;
    124   }
    125 
    126   bool FastPath() const {
    127     return (flags_ & kFlagFastPath) != 0u;
    128   }
    129 
    130   bool IsIntrinsic() const {
    131     return (flags_ & kFlagIsIntrinsic) != 0u;
    132   }
    133 
    134   bool IsSpecial() const {
    135     return (flags_ & kFlagIsSpecial) != 0u;
    136   }
    137 
    138   bool IsReferrersClass() const {
    139     return (flags_ & kFlagIsReferrersClass) != 0;
    140   }
    141 
    142   bool IsClassInitialized() const {
    143     return (flags_ & kFlagClassIsInitialized) != 0u;
    144   }
    145 
    146   // Returns true iff the method invoke is INVOKE_VIRTUAL_QUICK or INVOKE_VIRTUAL_RANGE_QUICK.
    147   bool IsQuickened() const {
    148     return (flags_ & kFlagQuickened) != 0u;
    149   }
    150 
    151   InvokeType GetInvokeType() const {
    152     return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
    153   }
    154 
    155   art::InvokeType GetSharpType() const {
    156     return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
    157   }
    158 
    159   MethodReference GetTargetMethod() const {
    160     return MethodReference(target_dex_file_, target_method_idx_);
    161   }
    162 
    163   uint16_t VTableIndex() const {
    164     return vtable_idx_;
    165   }
    166   void SetVTableIndex(uint16_t index) {
    167     vtable_idx_ = index;
    168   }
    169 
    170   uintptr_t DirectCode() const {
    171     return direct_code_;
    172   }
    173 
    174   uintptr_t DirectMethod() const {
    175     return direct_method_;
    176   }
    177 
    178   int StatsFlags() const {
    179     return stats_flags_;
    180   }
    181 
    182   void CheckEquals(const MirMethodLoweringInfo& info) const {
    183     CHECK_EQ(method_idx_, info.method_idx_);
    184     CHECK_EQ(flags_, info.flags_);
    185     CHECK_EQ(declaring_method_idx_, info.declaring_method_idx_);
    186     CHECK_EQ(declaring_class_idx_, info.declaring_class_idx_);
    187     CHECK_EQ(declaring_dex_file_, info.declaring_dex_file_);
    188     CHECK_EQ(direct_code_, info.direct_code_);
    189     CHECK_EQ(direct_method_, info.direct_method_);
    190     CHECK_EQ(target_dex_file_, info.target_dex_file_);
    191     CHECK_EQ(target_method_idx_, info.target_method_idx_);
    192     CHECK_EQ(vtable_idx_, info.vtable_idx_);
    193     CHECK_EQ(stats_flags_, info.stats_flags_);
    194   }
    195 
    196  private:
    197   enum {
    198     kBitFastPath = kMethodInfoBitEnd,
    199     kBitIsIntrinsic,
    200     kBitIsSpecial,
    201     kBitInvokeTypeBegin,
    202     kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3,  // 3 bits for invoke type.
    203     kBitSharpTypeBegin = kBitInvokeTypeEnd,
    204     kBitSharpTypeEnd = kBitSharpTypeBegin + 3,  // 3 bits for sharp type.
    205     kBitIsReferrersClass = kBitSharpTypeEnd,
    206     kBitClassIsInitialized,
    207     kBitQuickened,
    208     kMethodLoweringInfoBitEnd
    209   };
    210   static_assert(kMethodLoweringInfoBitEnd <= 16, "Too many flags");
    211   static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
    212   static constexpr uint16_t kFlagIsIntrinsic = 1u << kBitIsIntrinsic;
    213   static constexpr uint16_t kFlagIsSpecial = 1u << kBitIsSpecial;
    214   static constexpr uint16_t kFlagIsReferrersClass = 1u << kBitIsReferrersClass;
    215   static constexpr uint16_t kFlagClassIsInitialized = 1u << kBitClassIsInitialized;
    216   static constexpr uint16_t kFlagQuickened = 1u << kBitQuickened;
    217   static constexpr uint16_t kInvokeTypeMask = 7u;
    218   static_assert((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
    219                 "assert invoke type bits failed");
    220   static_assert((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
    221                 "assert sharp type bits failed");
    222 
    223   uintptr_t direct_code_;
    224   uintptr_t direct_method_;
    225   // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
    226   // devirtualized invoke target if available, null and 0u otherwise.
    227   // After Resolve() they hold the actual target method that will be called; it will be either
    228   // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
    229   const DexFile* target_dex_file_;
    230   uint16_t target_method_idx_;
    231   uint16_t vtable_idx_;
    232   int stats_flags_;
    233 
    234   friend class MirOptimizationTest;
    235   friend class TypeInferenceTest;
    236 };
    237 
    238 }  // namespace art
    239 
    240 #endif  // ART_COMPILER_DEX_MIR_METHOD_INFO_H_
    241