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 
     50   uint16_t DeclaringClassIndex() const {
     51     return declaring_class_idx_;
     52   }
     53 
     54   uint16_t DeclaringMethodIndex() const {
     55     return declaring_method_idx_;
     56   }
     57 
     58  protected:
     59   enum {
     60     kBitIsStatic = 0,
     61     kMethodInfoBitEnd
     62   };
     63   COMPILE_ASSERT(kMethodInfoBitEnd <= 16, too_many_flags);
     64   static constexpr uint16_t kFlagIsStatic = 1u << kBitIsStatic;
     65 
     66   MirMethodInfo(uint16_t method_idx, uint16_t flags)
     67       : method_idx_(method_idx),
     68         flags_(flags),
     69         declaring_method_idx_(0u),
     70         declaring_class_idx_(0u),
     71         declaring_dex_file_(nullptr) {
     72   }
     73 
     74   // Make copy-ctor/assign/dtor protected to avoid slicing.
     75   MirMethodInfo(const MirMethodInfo& other) = default;
     76   MirMethodInfo& operator=(const MirMethodInfo& other) = default;
     77   ~MirMethodInfo() = default;
     78 
     79   // The method index in the compiling method's dex file.
     80   uint16_t method_idx_;
     81   // Flags, for volatility and derived class data.
     82   uint16_t flags_;
     83   // The method index in the dex file that defines the method, 0 if unresolved.
     84   uint16_t declaring_method_idx_;
     85   // The type index of the class declaring the method, 0 if unresolved.
     86   uint16_t declaring_class_idx_;
     87   // The dex file that defines the class containing the method and the method,
     88   // nullptr if unresolved.
     89   const DexFile* declaring_dex_file_;
     90 };
     91 
     92 class MirMethodLoweringInfo : public MirMethodInfo {
     93  public:
     94   // For each requested method retrieve the method's declaring location (dex file, class
     95   // index and method index) and compute whether we can fast path the method call. For fast
     96   // path methods, retrieve the method's vtable index and direct code and method when applicable.
     97   static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit,
     98                       MirMethodLoweringInfo* method_infos, size_t count)
     99       LOCKS_EXCLUDED(Locks::mutator_lock_);
    100 
    101   MirMethodLoweringInfo(uint16_t method_idx, InvokeType type)
    102       : MirMethodInfo(method_idx,
    103                       ((type == kStatic) ? kFlagIsStatic : 0u) |
    104                       (static_cast<uint16_t>(type) << kBitInvokeTypeBegin) |
    105                       (static_cast<uint16_t>(type) << kBitSharpTypeBegin)),
    106         direct_code_(0u),
    107         direct_method_(0u),
    108         target_dex_file_(nullptr),
    109         target_method_idx_(0u),
    110         vtable_idx_(0u),
    111         stats_flags_(0) {
    112   }
    113 
    114   void SetDevirtualizationTarget(const MethodReference& ref) {
    115     DCHECK(target_dex_file_ == nullptr);
    116     DCHECK_EQ(target_method_idx_, 0u);
    117     DCHECK_LE(ref.dex_method_index, 0xffffu);
    118     target_dex_file_ = ref.dex_file;
    119     target_method_idx_ = ref.dex_method_index;
    120   }
    121 
    122   bool FastPath() const {
    123     return (flags_ & kFlagFastPath) != 0u;
    124   }
    125 
    126   bool NeedsClassInitialization() const {
    127     return (flags_ & kFlagNeedsClassInitialization) != 0u;
    128   }
    129 
    130   InvokeType GetInvokeType() const {
    131     return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask);
    132   }
    133 
    134   art::InvokeType GetSharpType() const {
    135     return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask);
    136   }
    137 
    138   MethodReference GetTargetMethod() const {
    139     return MethodReference(target_dex_file_, target_method_idx_);
    140   }
    141 
    142   uint16_t VTableIndex() const {
    143     return vtable_idx_;
    144   }
    145 
    146   uintptr_t DirectCode() const {
    147     return direct_code_;
    148   }
    149 
    150   uintptr_t DirectMethod() const {
    151     return direct_method_;
    152   }
    153 
    154   int StatsFlags() const {
    155     return stats_flags_;
    156   }
    157 
    158  private:
    159   enum {
    160     kBitFastPath = kMethodInfoBitEnd,
    161     kBitInvokeTypeBegin,
    162     kBitInvokeTypeEnd = kBitInvokeTypeBegin + 3,  // 3 bits for invoke type.
    163     kBitSharpTypeBegin,
    164     kBitSharpTypeEnd = kBitSharpTypeBegin + 3,  // 3 bits for sharp type.
    165     kBitNeedsClassInitialization = kBitSharpTypeEnd,
    166     kMethodLoweringInfoEnd
    167   };
    168   COMPILE_ASSERT(kMethodLoweringInfoEnd <= 16, too_many_flags);
    169   static constexpr uint16_t kFlagFastPath = 1u << kBitFastPath;
    170   static constexpr uint16_t kFlagNeedsClassInitialization = 1u << kBitNeedsClassInitialization;
    171   static constexpr uint16_t kInvokeTypeMask = 7u;
    172   COMPILE_ASSERT((1u << (kBitInvokeTypeEnd - kBitInvokeTypeBegin)) - 1u == kInvokeTypeMask,
    173                  assert_invoke_type_bits_ok);
    174   COMPILE_ASSERT((1u << (kBitSharpTypeEnd - kBitSharpTypeBegin)) - 1u == kInvokeTypeMask,
    175                  assert_sharp_type_bits_ok);
    176 
    177   uintptr_t direct_code_;
    178   uintptr_t direct_method_;
    179   // Before Resolve(), target_dex_file_ and target_method_idx_ hold the verification-based
    180   // devirtualized invoke target if available, nullptr and 0u otherwise.
    181   // After Resolve() they hold the actual target method that will be called; it will be either
    182   // a devirtualized target method or the compilation's unit's dex file and MethodIndex().
    183   const DexFile* target_dex_file_;
    184   uint16_t target_method_idx_;
    185   uint16_t vtable_idx_;
    186   int stats_flags_;
    187 
    188   friend class ClassInitCheckEliminationTest;
    189 };
    190 
    191 }  // namespace art
    192 
    193 #endif  // ART_COMPILER_DEX_MIR_METHOD_INFO_H_
    194