dex_file_method_inliner.h revision d85614222fa062ec809af9d65f04ab6b7dc1c248
1/* 2 * Copyright (C) 2013 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_QUICK_DEX_FILE_METHOD_INLINER_H_ 18#define ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 19 20#include <stdint.h> 21#include "base/mutex.h" 22#include "base/macros.h" 23#include "safe_map.h" 24#include "dex/compiler_enums.h" 25#include "dex_file.h" 26#include "quick/inline_method_analyser.h" 27 28namespace art { 29 30namespace verifier { 31class MethodVerifier; 32} // namespace verifier 33 34struct BasicBlock; 35struct CallInfo; 36struct MIR; 37class MIRGraph; 38class Mir2Lir; 39 40/** 41 * Handles inlining of methods from a particular DexFile. 42 * 43 * Intrinsics are a special case of inline methods. The DexFile indices for 44 * all the supported intrinsic methods are looked up once by the FindIntrinsics 45 * function and cached by this class for quick lookup by the method index. 46 * 47 * TODO: Detect short methods (at least getters, setters and empty functions) 48 * from the verifier and mark them for inlining. Inline these methods early 49 * during compilation to allow further optimizations. Similarly, provide 50 * additional information about intrinsics to the early phases of compilation. 51 */ 52class DexFileMethodInliner { 53 public: 54 DexFileMethodInliner(); 55 ~DexFileMethodInliner(); 56 57 /** 58 * Analyse method code to determine if the method is a candidate for inlining. 59 * If it is, record its data for later. 60 * 61 * @param verifier the method verifier holding data about the method to analyse. 62 * @return true if the method is a candidate for inlining, false otherwise. 63 */ 64 bool AnalyseMethodCode(verifier::MethodVerifier* verifier) 65 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_); 66 67 /** 68 * Check whether a particular method index corresponds to an intrinsic function. 69 */ 70 bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_); 71 72 /** 73 * Generate code for an intrinsic function invocation. 74 */ 75 bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_); 76 77 /** 78 * Check whether a particular method index corresponds to a special function. 79 */ 80 bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_); 81 82 /** 83 * Generate code for a special function. 84 */ 85 bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) LOCKS_EXCLUDED(lock_); 86 87 /** 88 * Try to inline an invoke. 89 */ 90 bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx) 91 LOCKS_EXCLUDED(lock_); 92 93 /** 94 * To avoid multiple lookups of a class by its descriptor, we cache its 95 * type index in the IndexCache. These are the indexes into the IndexCache 96 * class_indexes array. 97 */ 98 enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 99 kClassCacheFirst = 0, 100 kClassCacheBoolean = kClassCacheFirst, 101 kClassCacheByte, 102 kClassCacheChar, 103 kClassCacheShort, 104 kClassCacheInt, 105 kClassCacheLong, 106 kClassCacheFloat, 107 kClassCacheDouble, 108 kClassCacheVoid, 109 kClassCacheJavaLangObject, 110 kClassCacheJavaLangRefReference, 111 kClassCacheJavaLangString, 112 kClassCacheJavaLangDouble, 113 kClassCacheJavaLangFloat, 114 kClassCacheJavaLangInteger, 115 kClassCacheJavaLangLong, 116 kClassCacheJavaLangShort, 117 kClassCacheJavaLangMath, 118 kClassCacheJavaLangStrictMath, 119 kClassCacheJavaLangThread, 120 kClassCacheLibcoreIoMemory, 121 kClassCacheSunMiscUnsafe, 122 kClassCacheJavaLangSystem, 123 kClassCacheJavaLangCharArray, 124 kClassCacheLast 125 }; 126 127 /** 128 * To avoid multiple lookups of a method name string, we cache its string 129 * index in the IndexCache. These are the indexes into the IndexCache 130 * name_indexes array. 131 */ 132 enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 133 kNameCacheFirst = 0, 134 kNameCacheReverse = kNameCacheFirst, 135 kNameCacheReverseBytes, 136 kNameCacheDoubleToRawLongBits, 137 kNameCacheLongBitsToDouble, 138 kNameCacheFloatToRawIntBits, 139 kNameCacheIntBitsToFloat, 140 kNameCacheAbs, 141 kNameCacheMax, 142 kNameCacheMin, 143 kNameCacheSqrt, 144 kNameCacheGet, 145 kNameCacheCharAt, 146 kNameCacheCompareTo, 147 kNameCacheIsEmpty, 148 kNameCacheIndexOf, 149 kNameCacheLength, 150 kNameCacheCurrentThread, 151 kNameCachePeekByte, 152 kNameCachePeekIntNative, 153 kNameCachePeekLongNative, 154 kNameCachePeekShortNative, 155 kNameCachePokeByte, 156 kNameCachePokeIntNative, 157 kNameCachePokeLongNative, 158 kNameCachePokeShortNative, 159 kNameCacheCompareAndSwapInt, 160 kNameCacheCompareAndSwapLong, 161 kNameCacheCompareAndSwapObject, 162 kNameCacheGetInt, 163 kNameCacheGetIntVolatile, 164 kNameCachePutInt, 165 kNameCachePutIntVolatile, 166 kNameCachePutOrderedInt, 167 kNameCacheGetLong, 168 kNameCacheGetLongVolatile, 169 kNameCachePutLong, 170 kNameCachePutLongVolatile, 171 kNameCachePutOrderedLong, 172 kNameCacheGetObject, 173 kNameCacheGetObjectVolatile, 174 kNameCachePutObject, 175 kNameCachePutObjectVolatile, 176 kNameCachePutOrderedObject, 177 kNameCacheArrayCopy, 178 kNameCacheLast 179 }; 180 181 /** 182 * To avoid multiple lookups of a method signature, we cache its proto 183 * index in the IndexCache. These are the indexes into the IndexCache 184 * proto_indexes array. 185 */ 186 enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 187 kProtoCacheFirst = 0, 188 kProtoCacheI_I = kProtoCacheFirst, 189 kProtoCacheJ_J, 190 kProtoCacheS_S, 191 kProtoCacheD_D, 192 kProtoCacheDD_D, 193 kProtoCacheF_F, 194 kProtoCacheFF_F, 195 kProtoCacheD_J, 196 kProtoCacheJ_D, 197 kProtoCacheF_I, 198 kProtoCacheI_F, 199 kProtoCacheII_I, 200 kProtoCacheI_C, 201 kProtoCacheString_I, 202 kProtoCache_Z, 203 kProtoCache_I, 204 kProtoCache_Object, 205 kProtoCache_Thread, 206 kProtoCacheJ_B, 207 kProtoCacheJ_I, 208 kProtoCacheJ_S, 209 kProtoCacheJB_V, 210 kProtoCacheJI_V, 211 kProtoCacheJJ_J, 212 kProtoCacheJJ_V, 213 kProtoCacheJS_V, 214 kProtoCacheObjectJII_Z, 215 kProtoCacheObjectJJJ_Z, 216 kProtoCacheObjectJObjectObject_Z, 217 kProtoCacheObjectJ_I, 218 kProtoCacheObjectJI_V, 219 kProtoCacheObjectJ_J, 220 kProtoCacheObjectJJ_V, 221 kProtoCacheObjectJ_Object, 222 kProtoCacheObjectJObject_V, 223 kProtoCacheCharArrayICharArrayII_V, 224 kProtoCacheLast 225 }; 226 227 private: 228 /** 229 * The maximum number of method parameters we support in the ProtoDef. 230 */ 231 static constexpr uint32_t kProtoMaxParams = 6; 232 233 /** 234 * The method signature (proto) definition using cached class indexes. 235 * The return_type and params are used with the IndexCache to look up 236 * appropriate class indexes to be passed to DexFile::FindProtoId(). 237 */ 238 struct ProtoDef { 239 ClassCacheIndex return_type; 240 uint8_t param_count; 241 ClassCacheIndex params[kProtoMaxParams]; 242 }; 243 244 /** 245 * The method definition using cached class, name and proto indexes. 246 * The class index, method name index and proto index are used with 247 * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). 248 */ 249 struct MethodDef { 250 ClassCacheIndex declaring_class; 251 NameCacheIndex name; 252 ProtoCacheIndex proto; 253 }; 254 255 /** 256 * The definition of an intrinsic function binds the method definition 257 * to an Intrinsic. 258 */ 259 struct IntrinsicDef { 260 MethodDef method_def; 261 InlineMethod intrinsic; 262 }; 263 264 /** 265 * Cache for class, method name and method signature indexes used during 266 * intrinsic function lookup to avoid multiple lookups of the same items. 267 * 268 * Many classes have multiple intrinsics and/or they are used in multiple 269 * method signatures and we want to avoid repeated lookups since they are 270 * not exactly cheap. The method names and method signatures are sometimes 271 * reused and therefore cached as well. 272 */ 273 struct IndexCache { 274 IndexCache(); 275 276 uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; 277 uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; 278 uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; 279 }; 280 281 static const char* const kClassCacheNames[]; 282 static const char* const kNameCacheNames[]; 283 static const ProtoDef kProtoCacheDefs[]; 284 static const IntrinsicDef kIntrinsicMethods[]; 285 286 static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); 287 static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); 288 289 static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, 290 ClassCacheIndex index); 291 static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, 292 NameCacheIndex index); 293 static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, 294 ProtoCacheIndex index); 295 static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, 296 const MethodDef& method_def); 297 298 /** 299 * Find all known intrinsic methods in the dex_file and cache their indices. 300 * 301 * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. 302 */ 303 void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_); 304 305 friend class DexFileToMethodInlinerMap; 306 307 bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_); 308 309 static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 310 MIR* move_result, const InlineMethod& method); 311 static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 312 MIR* move_result, const InlineMethod& method); 313 static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 314 MIR* move_result, const InlineMethod& method, uint32_t method_idx); 315 static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 316 MIR* move_result, const InlineMethod& method, uint32_t method_idx); 317 318 ReaderWriterMutex lock_; 319 /* 320 * Maps method indexes (for the particular DexFile) to Intrinsic defintions. 321 */ 322 SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); 323 const DexFile* dex_file_; 324 325 DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); 326}; 327 328} // namespace art 329 330#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 331