Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 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> |
Vladimir Marko | e13717e | 2013-11-20 12:44:55 +0000 | [diff] [blame] | 21 | #include "base/mutex.h" |
| 22 | #include "base/macros.h" |
Ian Rogers | dce164a | 2014-01-02 17:00:38 -0800 | [diff] [blame] | 23 | #include "safe_map.h" |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 24 | #include "dex/compiler_enums.h" |
| 25 | #include "dex_file.h" |
Vladimir Marko | e3e0260 | 2014-03-12 15:42:41 +0000 | [diff] [blame] | 26 | #include "quick/inline_method_analyser.h" |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 27 | |
| 28 | namespace art { |
| 29 | |
Vladimir Marko | 2bc4780 | 2014-02-10 09:43:07 +0000 | [diff] [blame] | 30 | namespace verifier { |
| 31 | class MethodVerifier; |
| 32 | } // namespace verifier |
| 33 | |
Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 34 | class BasicBlock; |
Ian Rogers | b48b9eb | 2014-02-28 16:20:21 -0800 | [diff] [blame] | 35 | struct CallInfo; |
Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 36 | class MIR; |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 37 | class MIRGraph; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 38 | class Mir2Lir; |
| 39 | |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 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 | */ |
| 52 | class DexFileMethodInliner { |
| 53 | public: |
Vladimir Marko | 867a2b3 | 2013-12-10 13:01:13 +0000 | [diff] [blame] | 54 | DexFileMethodInliner(); |
| 55 | ~DexFileMethodInliner(); |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 56 | |
| 57 | /** |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 58 | * Analyse method code to determine if the method is a candidate for inlining. |
| 59 | * If it is, record its data for later. |
| 60 | * |
Vladimir Marko | 84c072c | 2014-02-17 15:07:04 +0000 | [diff] [blame] | 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. |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 63 | */ |
Vladimir Marko | 2bc4780 | 2014-02-10 09:43:07 +0000 | [diff] [blame] | 64 | bool AnalyseMethodCode(verifier::MethodVerifier* verifier) |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 65 | SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_); |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 66 | |
| 67 | /** |
Vladimir Marko | 87b7c52 | 2015-04-08 10:01:01 +0100 | [diff] [blame] | 68 | * Check whether a particular method index corresponds to an intrinsic or special function. |
| 69 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 70 | InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) REQUIRES(!lock_); |
Vladimir Marko | 87b7c52 | 2015-04-08 10:01:01 +0100 | [diff] [blame] | 71 | |
| 72 | /** |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 73 | * Check whether a particular method index corresponds to an intrinsic function. |
| 74 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 75 | bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) REQUIRES(!lock_); |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 76 | |
| 77 | /** |
| 78 | * Generate code for an intrinsic function invocation. |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 79 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 80 | bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) REQUIRES(!lock_); |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 81 | |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 82 | /** |
| 83 | * Check whether a particular method index corresponds to a special function. |
| 84 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 85 | bool IsSpecial(uint32_t method_index) REQUIRES(!lock_); |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 86 | |
| 87 | /** |
| 88 | * Generate code for a special function. |
| 89 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 90 | bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) REQUIRES(!lock_); |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 91 | |
| 92 | /** |
| 93 | * Try to inline an invoke. |
| 94 | */ |
| 95 | bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx) |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 96 | REQUIRES(!lock_); |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 97 | |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 98 | /** |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 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) |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 102 | REQUIRES(!lock_); |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 103 | |
| 104 | /** |
| 105 | * Check whether a particular method index is a string init. |
| 106 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 107 | bool IsStringInitMethodIndex(uint32_t method_index) REQUIRES(!lock_); |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 108 | |
| 109 | /** |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 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, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 125 | kClassCacheJavaLangByteArray, |
| 126 | kClassCacheJavaLangCharArray, |
| 127 | kClassCacheJavaLangIntArray, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 128 | kClassCacheJavaLangObject, |
Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 129 | kClassCacheJavaLangRefReference, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 130 | kClassCacheJavaLangString, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 131 | kClassCacheJavaLangStringBuffer, |
| 132 | kClassCacheJavaLangStringBuilder, |
| 133 | kClassCacheJavaLangStringFactory, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 134 | kClassCacheJavaLangDouble, |
| 135 | kClassCacheJavaLangFloat, |
| 136 | kClassCacheJavaLangInteger, |
| 137 | kClassCacheJavaLangLong, |
| 138 | kClassCacheJavaLangShort, |
| 139 | kClassCacheJavaLangMath, |
| 140 | kClassCacheJavaLangStrictMath, |
| 141 | kClassCacheJavaLangThread, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 142 | kClassCacheJavaNioCharsetCharset, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 143 | kClassCacheLibcoreIoMemory, |
| 144 | kClassCacheSunMiscUnsafe, |
DaniilSokolov | 70c4f06 | 2014-06-24 17:34:00 -0700 | [diff] [blame] | 145 | kClassCacheJavaLangSystem, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 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, |
Serban Constantinescu | 23abec9 | 2014-07-02 16:13:38 +0100 | [diff] [blame] | 156 | kNameCacheReverse = kNameCacheFirst, |
| 157 | kNameCacheReverseBytes, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 158 | kNameCacheDoubleToRawLongBits, |
| 159 | kNameCacheLongBitsToDouble, |
| 160 | kNameCacheFloatToRawIntBits, |
| 161 | kNameCacheIntBitsToFloat, |
| 162 | kNameCacheAbs, |
| 163 | kNameCacheMax, |
| 164 | kNameCacheMin, |
Mark Mendell | a4f1220 | 2015-08-06 15:23:34 -0400 | [diff] [blame] | 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, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 182 | kNameCacheSqrt, |
Serban Constantinescu | 2eba1fa | 2014-07-31 19:07:17 +0100 | [diff] [blame] | 183 | kNameCacheCeil, |
| 184 | kNameCacheFloor, |
| 185 | kNameCacheRint, |
| 186 | kNameCacheRound, |
Mathieu Chartier | cd48f2d | 2014-09-09 13:51:09 -0700 | [diff] [blame] | 187 | kNameCacheReferenceGetReferent, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 188 | kNameCacheCharAt, |
| 189 | kNameCacheCompareTo, |
agicsaki | 7da072f | 2015-08-12 20:30:17 -0700 | [diff] [blame] | 190 | kNameCacheEquals, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 191 | kNameCacheGetCharsNoCheck, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 192 | kNameCacheIsEmpty, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 193 | kNameCacheIsInfinite, |
| 194 | kNameCacheIsNaN, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 195 | kNameCacheIndexOf, |
| 196 | kNameCacheLength, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 197 | kNameCacheInit, |
| 198 | kNameCacheNewStringFromBytes, |
| 199 | kNameCacheNewStringFromChars, |
| 200 | kNameCacheNewStringFromString, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 201 | kNameCacheCurrentThread, |
| 202 | kNameCachePeekByte, |
| 203 | kNameCachePeekIntNative, |
| 204 | kNameCachePeekLongNative, |
| 205 | kNameCachePeekShortNative, |
| 206 | kNameCachePokeByte, |
| 207 | kNameCachePokeIntNative, |
| 208 | kNameCachePokeLongNative, |
| 209 | kNameCachePokeShortNative, |
| 210 | kNameCacheCompareAndSwapInt, |
Vladimir Marko | 1c282e2 | 2013-11-21 14:49:47 +0000 | [diff] [blame] | 211 | kNameCacheCompareAndSwapLong, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 212 | kNameCacheCompareAndSwapObject, |
| 213 | kNameCacheGetInt, |
| 214 | kNameCacheGetIntVolatile, |
| 215 | kNameCachePutInt, |
| 216 | kNameCachePutIntVolatile, |
| 217 | kNameCachePutOrderedInt, |
| 218 | kNameCacheGetLong, |
| 219 | kNameCacheGetLongVolatile, |
| 220 | kNameCachePutLong, |
| 221 | kNameCachePutLongVolatile, |
| 222 | kNameCachePutOrderedLong, |
| 223 | kNameCacheGetObject, |
| 224 | kNameCacheGetObjectVolatile, |
| 225 | kNameCachePutObject, |
| 226 | kNameCachePutObjectVolatile, |
| 227 | kNameCachePutOrderedObject, |
DaniilSokolov | 70c4f06 | 2014-06-24 17:34:00 -0700 | [diff] [blame] | 228 | kNameCacheArrayCopy, |
Aart Bik | 3f67e69 | 2016-01-15 14:35:12 -0800 | [diff] [blame] | 229 | kNameCacheBitCount, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 230 | kNameCacheCompare, |
| 231 | kNameCacheHighestOneBit, |
| 232 | kNameCacheLowestOneBit, |
Scott Wakeling | 611d339 | 2015-07-10 11:42:06 +0100 | [diff] [blame] | 233 | kNameCacheNumberOfLeadingZeros, |
Scott Wakeling | 9ee23f4 | 2015-07-23 10:44:35 +0100 | [diff] [blame] | 234 | kNameCacheNumberOfTrailingZeros, |
| 235 | kNameCacheRotateRight, |
| 236 | kNameCacheRotateLeft, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 237 | kNameCacheSignum, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 238 | kNameCacheLast |
| 239 | }; |
| 240 | |
| 241 | /** |
| 242 | * To avoid multiple lookups of a method signature, we cache its proto |
| 243 | * index in the IndexCache. These are the indexes into the IndexCache |
| 244 | * proto_indexes array. |
| 245 | */ |
| 246 | enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed |
| 247 | kProtoCacheFirst = 0, |
| 248 | kProtoCacheI_I = kProtoCacheFirst, |
| 249 | kProtoCacheJ_J, |
| 250 | kProtoCacheS_S, |
| 251 | kProtoCacheD_D, |
Serban Constantinescu | 23abec9 | 2014-07-02 16:13:38 +0100 | [diff] [blame] | 252 | kProtoCacheDD_D, |
Yixin Shou | dbb17e3 | 2014-02-07 05:09:30 -0800 | [diff] [blame] | 253 | kProtoCacheF_F, |
Serban Constantinescu | 23abec9 | 2014-07-02 16:13:38 +0100 | [diff] [blame] | 254 | kProtoCacheFF_F, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 255 | kProtoCacheD_J, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 256 | kProtoCacheD_Z, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 257 | kProtoCacheJ_D, |
| 258 | kProtoCacheF_I, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 259 | kProtoCacheF_Z, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 260 | kProtoCacheI_F, |
| 261 | kProtoCacheII_I, |
| 262 | kProtoCacheI_C, |
| 263 | kProtoCacheString_I, |
| 264 | kProtoCache_Z, |
| 265 | kProtoCache_I, |
Fred Shih | 4ee7a66 | 2014-07-11 09:59:27 -0700 | [diff] [blame] | 266 | kProtoCache_Object, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 267 | kProtoCache_Thread, |
| 268 | kProtoCacheJ_B, |
| 269 | kProtoCacheJ_I, |
| 270 | kProtoCacheJ_S, |
| 271 | kProtoCacheJB_V, |
| 272 | kProtoCacheJI_V, |
Serban Constantinescu | 23abec9 | 2014-07-02 16:13:38 +0100 | [diff] [blame] | 273 | kProtoCacheJJ_J, |
Aart Bik | 59c9454 | 2016-01-25 14:20:58 -0800 | [diff] [blame] | 274 | kProtoCacheJJ_I, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 275 | kProtoCacheJJ_V, |
| 276 | kProtoCacheJS_V, |
agicsaki | 7da072f | 2015-08-12 20:30:17 -0700 | [diff] [blame] | 277 | kProtoCacheObject_Z, |
Scott Wakeling | 9ee23f4 | 2015-07-23 10:44:35 +0100 | [diff] [blame] | 278 | kProtoCacheJI_J, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 279 | kProtoCacheObjectJII_Z, |
Vladimir Marko | 1c282e2 | 2013-11-21 14:49:47 +0000 | [diff] [blame] | 280 | kProtoCacheObjectJJJ_Z, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 281 | kProtoCacheObjectJObjectObject_Z, |
| 282 | kProtoCacheObjectJ_I, |
| 283 | kProtoCacheObjectJI_V, |
| 284 | kProtoCacheObjectJ_J, |
| 285 | kProtoCacheObjectJJ_V, |
| 286 | kProtoCacheObjectJ_Object, |
| 287 | kProtoCacheObjectJObject_V, |
DaniilSokolov | 70c4f06 | 2014-06-24 17:34:00 -0700 | [diff] [blame] | 288 | kProtoCacheCharArrayICharArrayII_V, |
Nicolas Geoffray | ee3cf07 | 2015-10-06 11:45:02 +0100 | [diff] [blame] | 289 | kProtoCacheObjectIObjectII_V, |
Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 290 | kProtoCacheIICharArrayI_V, |
| 291 | kProtoCacheByteArrayIII_String, |
| 292 | kProtoCacheIICharArray_String, |
| 293 | kProtoCacheString_String, |
| 294 | kProtoCache_V, |
| 295 | kProtoCacheByteArray_V, |
| 296 | kProtoCacheByteArrayI_V, |
| 297 | kProtoCacheByteArrayII_V, |
| 298 | kProtoCacheByteArrayIII_V, |
| 299 | kProtoCacheByteArrayIIString_V, |
| 300 | kProtoCacheByteArrayString_V, |
| 301 | kProtoCacheByteArrayIICharset_V, |
| 302 | kProtoCacheByteArrayCharset_V, |
| 303 | kProtoCacheCharArray_V, |
| 304 | kProtoCacheCharArrayII_V, |
| 305 | kProtoCacheIICharArray_V, |
| 306 | kProtoCacheIntArrayII_V, |
| 307 | kProtoCacheString_V, |
| 308 | kProtoCacheStringBuffer_V, |
| 309 | kProtoCacheStringBuilder_V, |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 310 | kProtoCacheLast |
| 311 | }; |
| 312 | |
Ian Rogers | b48b9eb | 2014-02-28 16:20:21 -0800 | [diff] [blame] | 313 | private: |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 314 | /** |
| 315 | * The maximum number of method parameters we support in the ProtoDef. |
| 316 | */ |
| 317 | static constexpr uint32_t kProtoMaxParams = 6; |
| 318 | |
| 319 | /** |
| 320 | * The method signature (proto) definition using cached class indexes. |
| 321 | * The return_type and params are used with the IndexCache to look up |
| 322 | * appropriate class indexes to be passed to DexFile::FindProtoId(). |
| 323 | */ |
| 324 | struct ProtoDef { |
| 325 | ClassCacheIndex return_type; |
| 326 | uint8_t param_count; |
| 327 | ClassCacheIndex params[kProtoMaxParams]; |
| 328 | }; |
| 329 | |
| 330 | /** |
| 331 | * The method definition using cached class, name and proto indexes. |
| 332 | * The class index, method name index and proto index are used with |
| 333 | * IndexCache to look up appropriate parameters for DexFile::FindMethodId(). |
| 334 | */ |
| 335 | struct MethodDef { |
| 336 | ClassCacheIndex declaring_class; |
| 337 | NameCacheIndex name; |
| 338 | ProtoCacheIndex proto; |
| 339 | }; |
| 340 | |
| 341 | /** |
| 342 | * The definition of an intrinsic function binds the method definition |
| 343 | * to an Intrinsic. |
| 344 | */ |
| 345 | struct IntrinsicDef { |
| 346 | MethodDef method_def; |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 347 | InlineMethod intrinsic; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 348 | }; |
| 349 | |
| 350 | /** |
| 351 | * Cache for class, method name and method signature indexes used during |
| 352 | * intrinsic function lookup to avoid multiple lookups of the same items. |
| 353 | * |
| 354 | * Many classes have multiple intrinsics and/or they are used in multiple |
| 355 | * method signatures and we want to avoid repeated lookups since they are |
| 356 | * not exactly cheap. The method names and method signatures are sometimes |
| 357 | * reused and therefore cached as well. |
| 358 | */ |
| 359 | struct IndexCache { |
| 360 | IndexCache(); |
| 361 | |
| 362 | uint32_t class_indexes[kClassCacheLast - kClassCacheFirst]; |
| 363 | uint32_t name_indexes[kNameCacheLast - kNameCacheFirst]; |
| 364 | uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst]; |
| 365 | }; |
| 366 | |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 367 | static const char* const kClassCacheNames[]; |
| 368 | static const char* const kNameCacheNames[]; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 369 | static const ProtoDef kProtoCacheDefs[]; |
Vladimir Marko | 867a2b3 | 2013-12-10 13:01:13 +0000 | [diff] [blame] | 370 | static const IntrinsicDef kIntrinsicMethods[]; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 371 | |
| 372 | static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1); |
| 373 | static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2); |
| 374 | |
| 375 | static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache, |
| 376 | ClassCacheIndex index); |
| 377 | static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache, |
| 378 | NameCacheIndex index); |
| 379 | static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache, |
| 380 | ProtoCacheIndex index); |
| 381 | static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache, |
| 382 | const MethodDef& method_def); |
| 383 | |
Vladimir Marko | 867a2b3 | 2013-12-10 13:01:13 +0000 | [diff] [blame] | 384 | /** |
| 385 | * Find all known intrinsic methods in the dex_file and cache their indices. |
| 386 | * |
| 387 | * Only DexFileToMethodInlinerMap may call this function to initialize the inliner. |
| 388 | */ |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 389 | void FindIntrinsics(const DexFile* dex_file) REQUIRES(lock_); |
Vladimir Marko | 867a2b3 | 2013-12-10 13:01:13 +0000 | [diff] [blame] | 390 | |
| 391 | friend class DexFileToMethodInlinerMap; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 392 | |
Mathieu Chartier | 9044347 | 2015-07-16 20:32:27 -0700 | [diff] [blame] | 393 | bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) REQUIRES(!lock_); |
Vladimir Marko | 5816ed4 | 2013-11-27 17:04:20 +0000 | [diff] [blame] | 394 | |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 395 | static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, |
| 396 | MIR* move_result, const InlineMethod& method); |
| 397 | static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, |
| 398 | MIR* move_result, const InlineMethod& method); |
| 399 | static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, |
Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 400 | MIR* move_result, const InlineMethod& method); |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 401 | static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, |
Ian Rogers | 6a3c1fc | 2014-10-31 00:33:20 -0700 | [diff] [blame] | 402 | MIR* move_result, const InlineMethod& method); |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 403 | |
Vladimir Marko | e13717e | 2013-11-20 12:44:55 +0000 | [diff] [blame] | 404 | ReaderWriterMutex lock_; |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 405 | /* |
| 406 | * Maps method indexes (for the particular DexFile) to Intrinsic defintions. |
| 407 | */ |
Ian Rogers | dce164a | 2014-01-02 17:00:38 -0800 | [diff] [blame] | 408 | SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_); |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 409 | const DexFile* dex_file_; |
Vladimir Marko | 867a2b3 | 2013-12-10 13:01:13 +0000 | [diff] [blame] | 410 | |
| 411 | DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner); |
Vladimir Marko | 5c96e6b | 2013-11-14 15:34:17 +0000 | [diff] [blame] | 412 | }; |
| 413 | |
| 414 | } // namespace art |
| 415 | |
| 416 | #endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_ |