dex_file_method_inliner.h revision 0e54c0160c84894696c05af6cad9eae3690f9496
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 34class BasicBlock; 35struct CallInfo; 36class 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_REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_); 66 67 /** 68 * Check whether a particular method index corresponds to an intrinsic or special function. 69 */ 70 InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) REQUIRES(!lock_); 71 72 /** 73 * Check whether a particular method index corresponds to an intrinsic function. 74 */ 75 bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) REQUIRES(!lock_); 76 77 /** 78 * Generate code for an intrinsic function invocation. 79 */ 80 bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) REQUIRES(!lock_); 81 82 /** 83 * Check whether a particular method index corresponds to a special function. 84 */ 85 bool IsSpecial(uint32_t method_index) REQUIRES(!lock_); 86 87 /** 88 * Generate code for a special function. 89 */ 90 bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) REQUIRES(!lock_); 91 92 /** 93 * Try to inline an invoke. 94 */ 95 bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx) 96 REQUIRES(!lock_); 97 98 /** 99 * Gets the thread pointer entrypoint offset for a string init method index and pointer size. 100 */ 101 uint32_t GetOffsetForStringInit(uint32_t method_index, size_t pointer_size) 102 REQUIRES(!lock_); 103 104 /** 105 * Check whether a particular method index is a string init. 106 */ 107 bool IsStringInitMethodIndex(uint32_t method_index) REQUIRES(!lock_); 108 109 /** 110 * To avoid multiple lookups of a class by its descriptor, we cache its 111 * type index in the IndexCache. These are the indexes into the IndexCache 112 * class_indexes array. 113 */ 114 enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 115 kClassCacheFirst = 0, 116 kClassCacheBoolean = kClassCacheFirst, 117 kClassCacheByte, 118 kClassCacheChar, 119 kClassCacheShort, 120 kClassCacheInt, 121 kClassCacheLong, 122 kClassCacheFloat, 123 kClassCacheDouble, 124 kClassCacheVoid, 125 kClassCacheJavaLangByteArray, 126 kClassCacheJavaLangCharArray, 127 kClassCacheJavaLangIntArray, 128 kClassCacheJavaLangObject, 129 kClassCacheJavaLangRefReference, 130 kClassCacheJavaLangString, 131 kClassCacheJavaLangStringBuffer, 132 kClassCacheJavaLangStringBuilder, 133 kClassCacheJavaLangStringFactory, 134 kClassCacheJavaLangDouble, 135 kClassCacheJavaLangFloat, 136 kClassCacheJavaLangInteger, 137 kClassCacheJavaLangLong, 138 kClassCacheJavaLangShort, 139 kClassCacheJavaLangMath, 140 kClassCacheJavaLangStrictMath, 141 kClassCacheJavaLangThread, 142 kClassCacheJavaNioCharsetCharset, 143 kClassCacheLibcoreIoMemory, 144 kClassCacheSunMiscUnsafe, 145 kClassCacheJavaLangSystem, 146 kClassCacheLast 147 }; 148 149 /** 150 * To avoid multiple lookups of a method name string, we cache its string 151 * index in the IndexCache. These are the indexes into the IndexCache 152 * name_indexes array. 153 */ 154 enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 155 kNameCacheFirst = 0, 156 kNameCacheReverse = kNameCacheFirst, 157 kNameCacheReverseBytes, 158 kNameCacheDoubleToRawLongBits, 159 kNameCacheLongBitsToDouble, 160 kNameCacheFloatToRawIntBits, 161 kNameCacheIntBitsToFloat, 162 kNameCacheAbs, 163 kNameCacheMax, 164 kNameCacheMin, 165 kNameCacheCos, 166 kNameCacheSin, 167 kNameCacheAcos, 168 kNameCacheAsin, 169 kNameCacheAtan, 170 kNameCacheAtan2, 171 kNameCacheCbrt, 172 kNameCacheCosh, 173 kNameCacheExp, 174 kNameCacheExpm1, 175 kNameCacheHypot, 176 kNameCacheLog, 177 kNameCacheLog10, 178 kNameCacheNextAfter, 179 kNameCacheSinh, 180 kNameCacheTan, 181 kNameCacheTanh, 182 kNameCacheSqrt, 183 kNameCacheCeil, 184 kNameCacheFloor, 185 kNameCacheRint, 186 kNameCacheRound, 187 kNameCacheReferenceGetReferent, 188 kNameCacheCharAt, 189 kNameCacheCompareTo, 190 kNameCacheEquals, 191 kNameCacheGetCharsNoCheck, 192 kNameCacheIsEmpty, 193 kNameCacheFloatToIntBits, 194 kNameCacheDoubleToLongBits, 195 kNameCacheIsInfinite, 196 kNameCacheIsNaN, 197 kNameCacheIndexOf, 198 kNameCacheLength, 199 kNameCacheInit, 200 kNameCacheNewStringFromBytes, 201 kNameCacheNewStringFromChars, 202 kNameCacheNewStringFromString, 203 kNameCacheCurrentThread, 204 kNameCachePeekByte, 205 kNameCachePeekIntNative, 206 kNameCachePeekLongNative, 207 kNameCachePeekShortNative, 208 kNameCachePokeByte, 209 kNameCachePokeIntNative, 210 kNameCachePokeLongNative, 211 kNameCachePokeShortNative, 212 kNameCacheCompareAndSwapInt, 213 kNameCacheCompareAndSwapLong, 214 kNameCacheCompareAndSwapObject, 215 kNameCacheGetInt, 216 kNameCacheGetIntVolatile, 217 kNameCachePutInt, 218 kNameCachePutIntVolatile, 219 kNameCachePutOrderedInt, 220 kNameCacheGetLong, 221 kNameCacheGetLongVolatile, 222 kNameCachePutLong, 223 kNameCachePutLongVolatile, 224 kNameCachePutOrderedLong, 225 kNameCacheGetObject, 226 kNameCacheGetObjectVolatile, 227 kNameCachePutObject, 228 kNameCachePutObjectVolatile, 229 kNameCachePutOrderedObject, 230 kNameCacheGetAndAddInt, 231 kNameCacheGetAndAddLong, 232 kNameCacheGetAndSetInt, 233 kNameCacheGetAndSetLong, 234 kNameCacheGetAndSetObject, 235 kNameCacheLoadFence, 236 kNameCacheStoreFence, 237 kNameCacheFullFence, 238 kNameCacheArrayCopy, 239 kNameCacheBitCount, 240 kNameCacheCompare, 241 kNameCacheHighestOneBit, 242 kNameCacheLowestOneBit, 243 kNameCacheNumberOfLeadingZeros, 244 kNameCacheNumberOfTrailingZeros, 245 kNameCacheRotateRight, 246 kNameCacheRotateLeft, 247 kNameCacheSignum, 248 kNameCacheLast 249 }; 250 251 /** 252 * To avoid multiple lookups of a method signature, we cache its proto 253 * index in the IndexCache. These are the indexes into the IndexCache 254 * proto_indexes array. 255 */ 256 enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed 257 kProtoCacheFirst = 0, 258 kProtoCacheI_I = kProtoCacheFirst, 259 kProtoCacheJ_J, 260 kProtoCacheS_S, 261 kProtoCacheD_D, 262 kProtoCacheDD_D, 263 kProtoCacheF_F, 264 kProtoCacheFF_F, 265 kProtoCacheD_J, 266 kProtoCacheD_Z, 267 kProtoCacheJ_D, 268 kProtoCacheF_I, 269 kProtoCacheF_Z, 270 kProtoCacheI_F, 271 kProtoCacheII_I, 272 kProtoCacheI_C, 273 kProtoCacheString_I, 274 kProtoCache_Z, 275 kProtoCache_I, 276 kProtoCache_Object, 277 kProtoCache_Thread, 278 kProtoCacheJ_B, 279 kProtoCacheJ_I, 280 kProtoCacheJ_S, 281 kProtoCacheJB_V, 282 kProtoCacheJI_V, 283 kProtoCacheJJ_J, 284 kProtoCacheJJ_I, 285 kProtoCacheJJ_V, 286 kProtoCacheJS_V, 287 kProtoCacheObject_Z, 288 kProtoCacheJI_J, 289 kProtoCacheObjectJII_Z, 290 kProtoCacheObjectJJJ_Z, 291 kProtoCacheObjectJObjectObject_Z, 292 kProtoCacheObjectJ_I, 293 kProtoCacheObjectJI_I, 294 kProtoCacheObjectJI_V, 295 kProtoCacheObjectJ_J, 296 kProtoCacheObjectJJ_J, 297 kProtoCacheObjectJJ_V, 298 kProtoCacheObjectJ_Object, 299 kProtoCacheObjectJObject_V, 300 kProtoCacheObjectJObject_Object, 301 kProtoCacheCharArrayICharArrayII_V, 302 kProtoCacheObjectIObjectII_V, 303 kProtoCacheIICharArrayI_V, 304 kProtoCacheByteArrayIII_String, 305 kProtoCacheIICharArray_String, 306 kProtoCacheString_String, 307 kProtoCache_V, 308 kProtoCacheByteArray_V, 309 kProtoCacheByteArrayI_V, 310 kProtoCacheByteArrayII_V, 311 kProtoCacheByteArrayIII_V, 312 kProtoCacheByteArrayIIString_V, 313 kProtoCacheByteArrayString_V, 314 kProtoCacheByteArrayIICharset_V, 315 kProtoCacheByteArrayCharset_V, 316 kProtoCacheCharArray_V, 317 kProtoCacheCharArrayII_V, 318 kProtoCacheIICharArray_V, 319 kProtoCacheIntArrayII_V, 320 kProtoCacheString_V, 321 kProtoCacheStringBuffer_V, 322 kProtoCacheStringBuilder_V, 323 kProtoCacheLast 324 }; 325 326 private: 327 /** 328 * The maximum number of method parameters we support in the ProtoDef. 329 */ 330 static constexpr uint32_t kProtoMaxParams = 6; 331 332 /** 333 * The method signature (proto) definition using cached class indexes. 334 * The return_type and params are used with the IndexCache to look up 335 * appropriate class indexes to be passed to DexFile::FindProtoId(). 336 */ 337 struct ProtoDef { 338 ClassCacheIndex return_type; 339 uint8_t param_count; 340 ClassCacheIndex params[kProtoMaxParams]; 341 }; 342 343 /** 344 * The method definition using cached class, name and proto indexes. 345 * The class index, method name index and proto index are used with 346 * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). 347 */ 348 struct MethodDef { 349 ClassCacheIndex declaring_class; 350 NameCacheIndex name; 351 ProtoCacheIndex proto; 352 }; 353 354 /** 355 * The definition of an intrinsic function binds the method definition 356 * to an Intrinsic. 357 */ 358 struct IntrinsicDef { 359 MethodDef method_def; 360 InlineMethod intrinsic; 361 }; 362 363 /** 364 * Cache for class, method name and method signature indexes used during 365 * intrinsic function lookup to avoid multiple lookups of the same items. 366 * 367 * Many classes have multiple intrinsics and/or they are used in multiple 368 * method signatures and we want to avoid repeated lookups since they are 369 * not exactly cheap. The method names and method signatures are sometimes 370 * reused and therefore cached as well. 371 */ 372 struct IndexCache { 373 IndexCache(); 374 375 uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; 376 uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; 377 uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; 378 }; 379 380 static const char* const kClassCacheNames[]; 381 static const char* const kNameCacheNames[]; 382 static const ProtoDef kProtoCacheDefs[]; 383 static const IntrinsicDef kIntrinsicMethods[]; 384 385 static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); 386 static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); 387 388 static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, 389 ClassCacheIndex index); 390 static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, 391 NameCacheIndex index); 392 static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, 393 ProtoCacheIndex index); 394 static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, 395 const MethodDef& method_def); 396 397 /** 398 * Find all known intrinsic methods in the dex_file and cache their indices. 399 * 400 * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. 401 */ 402 void FindIntrinsics(const DexFile* dex_file) REQUIRES(lock_); 403 404 friend class DexFileToMethodInlinerMap; 405 406 bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) REQUIRES(!lock_); 407 408 static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 409 MIR* move_result, const InlineMethod& method); 410 static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 411 MIR* move_result, const InlineMethod& method); 412 static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 413 MIR* move_result, const InlineMethod& method); 414 static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, 415 MIR* move_result, const InlineMethod& method); 416 417 ReaderWriterMutex lock_; 418 /* 419 * Maps method indexes (for the particular DexFile) to Intrinsic defintions. 420 */ 421 SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); 422 const DexFile* dex_file_; 423 424 DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); 425}; 426 427} // namespace art 428 429#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ 430