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: MethodIndex()34 uint16_t MethodIndex() const { 35 return method_idx_; 36 } 37 IsStatic()38 bool IsStatic() const { 39 return (flags_ & kFlagIsStatic) != 0u; 40 } 41 IsResolved()42 bool IsResolved() const { 43 return declaring_dex_file_ != nullptr; 44 } 45 DeclaringDexFile()46 const DexFile* DeclaringDexFile() const { 47 return declaring_dex_file_; 48 } SetDeclaringDexFile(const DexFile * dex_file)49 void SetDeclaringDexFile(const DexFile* dex_file) { 50 declaring_dex_file_ = dex_file; 51 } 52 DeclaringClassIndex()53 uint16_t DeclaringClassIndex() const { 54 return declaring_class_idx_; 55 } 56 DeclaringMethodIndex()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 MirMethodInfo(uint16_t method_idx,uint16_t flags)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 MirMethodLoweringInfo(uint16_t method_idx,InvokeType type,bool is_quickened)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 SetDevirtualizationTarget(const MethodReference & ref)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 FastPath()126 bool FastPath() const { 127 return (flags_ & kFlagFastPath) != 0u; 128 } 129 IsIntrinsic()130 bool IsIntrinsic() const { 131 return (flags_ & kFlagIsIntrinsic) != 0u; 132 } 133 IsSpecial()134 bool IsSpecial() const { 135 return (flags_ & kFlagIsSpecial) != 0u; 136 } 137 IsReferrersClass()138 bool IsReferrersClass() const { 139 return (flags_ & kFlagIsReferrersClass) != 0; 140 } 141 IsClassInitialized()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. IsQuickened()147 bool IsQuickened() const { 148 return (flags_ & kFlagQuickened) != 0u; 149 } 150 GetInvokeType()151 InvokeType GetInvokeType() const { 152 return static_cast<InvokeType>((flags_ >> kBitInvokeTypeBegin) & kInvokeTypeMask); 153 } 154 GetSharpType()155 art::InvokeType GetSharpType() const { 156 return static_cast<InvokeType>((flags_ >> kBitSharpTypeBegin) & kInvokeTypeMask); 157 } 158 GetTargetMethod()159 MethodReference GetTargetMethod() const { 160 return MethodReference(target_dex_file_, target_method_idx_); 161 } 162 VTableIndex()163 uint16_t VTableIndex() const { 164 return vtable_idx_; 165 } SetVTableIndex(uint16_t index)166 void SetVTableIndex(uint16_t index) { 167 vtable_idx_ = index; 168 } 169 DirectCode()170 uintptr_t DirectCode() const { 171 return direct_code_; 172 } 173 DirectMethod()174 uintptr_t DirectMethod() const { 175 return direct_method_; 176 } 177 StatsFlags()178 int StatsFlags() const { 179 return stats_flags_; 180 } 181 CheckEquals(const MirMethodLoweringInfo & info)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