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 #include "dex_file_method_inliner.h"
18
19 #include <algorithm>
20
21 #include "base/logging.h"
22 #include "base/macros.h"
23 #include "base/mutex-inl.h"
24 #include "driver/compiler_driver.h"
25 #include "thread-inl.h"
26 #include "dex_instruction-inl.h"
27 #include "driver/dex_compilation_unit.h"
28 #include "verifier/method_verifier-inl.h"
29
30 namespace art {
31
32 namespace { // anonymous namespace
33
34 static constexpr bool kIntrinsicIsStatic[] = {
35 true, // kIntrinsicDoubleCvt
36 true, // kIntrinsicFloatCvt
37 true, // kIntrinsicFloat2Int
38 true, // kIntrinsicDouble2Long
39 true, // kIntrinsicFloatIsInfinite
40 true, // kIntrinsicDoubleIsInfinite
41 true, // kIntrinsicFloatIsNaN
42 true, // kIntrinsicDoubleIsNaN
43 true, // kIntrinsicReverseBits
44 true, // kIntrinsicReverseBytes
45 true, // kIntrinsicBitCount
46 true, // kIntrinsicCompare,
47 true, // kIntrinsicHighestOneBit
48 true, // kIntrinsicLowestOneBit
49 true, // kIntrinsicNumberOfLeadingZeros
50 true, // kIntrinsicNumberOfTrailingZeros
51 true, // kIntrinsicRotateRight
52 true, // kIntrinsicRotateLeft
53 true, // kIntrinsicSignum
54 true, // kIntrinsicAbsInt
55 true, // kIntrinsicAbsLong
56 true, // kIntrinsicAbsFloat
57 true, // kIntrinsicAbsDouble
58 true, // kIntrinsicMinMaxInt
59 true, // kIntrinsicMinMaxLong
60 true, // kIntrinsicMinMaxFloat
61 true, // kIntrinsicMinMaxDouble
62 true, // kIntrinsicCos
63 true, // kIntrinsicSin
64 true, // kIntrinsicAcos
65 true, // kIntrinsicAsin
66 true, // kIntrinsicAtan
67 true, // kIntrinsicAtan2
68 true, // kIntrinsicCbrt
69 true, // kIntrinsicCosh
70 true, // kIntrinsicExp
71 true, // kIntrinsicExpm1
72 true, // kIntrinsicHypot
73 true, // kIntrinsicLog
74 true, // kIntrinsicLog10
75 true, // kIntrinsicNextAfter
76 true, // kIntrinsicSinh
77 true, // kIntrinsicTan
78 true, // kIntrinsicTanh
79 true, // kIntrinsicSqrt
80 true, // kIntrinsicCeil
81 true, // kIntrinsicFloor
82 true, // kIntrinsicRint
83 true, // kIntrinsicRoundFloat
84 true, // kIntrinsicRoundDouble
85 false, // kIntrinsicReferenceGetReferent
86 false, // kIntrinsicCharAt
87 false, // kIntrinsicCompareTo
88 false, // kIntrinsicEquals
89 false, // kIntrinsicGetCharsNoCheck
90 false, // kIntrinsicIsEmptyOrLength
91 false, // kIntrinsicIndexOf
92 true, // kIntrinsicNewStringFromBytes
93 true, // kIntrinsicNewStringFromChars
94 true, // kIntrinsicNewStringFromString
95 true, // kIntrinsicCurrentThread
96 true, // kIntrinsicPeek
97 true, // kIntrinsicPoke
98 false, // kIntrinsicCas
99 false, // kIntrinsicUnsafeGet
100 false, // kIntrinsicUnsafePut
101 false, // kIntrinsicUnsafeGetAndAddInt,
102 false, // kIntrinsicUnsafeGetAndAddLong,
103 false, // kIntrinsicUnsafeGetAndSetInt,
104 false, // kIntrinsicUnsafeGetAndSetLong,
105 false, // kIntrinsicUnsafeGetAndSetObject,
106 false, // kIntrinsicUnsafeLoadFence,
107 false, // kIntrinsicUnsafeStoreFence,
108 false, // kIntrinsicUnsafeFullFence,
109 true, // kIntrinsicSystemArrayCopyCharArray
110 true, // kIntrinsicSystemArrayCopy
111 };
112 static_assert(arraysize(kIntrinsicIsStatic) == kInlineOpNop,
113 "arraysize of kIntrinsicIsStatic unexpected");
114 static_assert(kIntrinsicIsStatic[kIntrinsicDoubleCvt], "DoubleCvt must be static");
115 static_assert(kIntrinsicIsStatic[kIntrinsicFloatCvt], "FloatCvt must be static");
116 static_assert(kIntrinsicIsStatic[kIntrinsicFloat2Int], "Float2Int must be static");
117 static_assert(kIntrinsicIsStatic[kIntrinsicDouble2Long], "Double2Long must be static");
118 static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsInfinite], "FloatIsInfinite must be static");
119 static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsInfinite], "DoubleIsInfinite must be static");
120 static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsNaN], "FloatIsNaN must be static");
121 static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsNaN], "DoubleIsNaN must be static");
122 static_assert(kIntrinsicIsStatic[kIntrinsicReverseBits], "ReverseBits must be static");
123 static_assert(kIntrinsicIsStatic[kIntrinsicReverseBytes], "ReverseBytes must be static");
124 static_assert(kIntrinsicIsStatic[kIntrinsicBitCount], "BitCount must be static");
125 static_assert(kIntrinsicIsStatic[kIntrinsicCompare], "Compare must be static");
126 static_assert(kIntrinsicIsStatic[kIntrinsicHighestOneBit], "HighestOneBit must be static");
127 static_assert(kIntrinsicIsStatic[kIntrinsicLowestOneBit], "LowestOneBit must be static");
128 static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfLeadingZeros],
129 "NumberOfLeadingZeros must be static");
130 static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfTrailingZeros],
131 "NumberOfTrailingZeros must be static");
132 static_assert(kIntrinsicIsStatic[kIntrinsicRotateRight], "RotateRight must be static");
133 static_assert(kIntrinsicIsStatic[kIntrinsicRotateLeft], "RotateLeft must be static");
134 static_assert(kIntrinsicIsStatic[kIntrinsicSignum], "Signum must be static");
135 static_assert(kIntrinsicIsStatic[kIntrinsicAbsInt], "AbsInt must be static");
136 static_assert(kIntrinsicIsStatic[kIntrinsicAbsLong], "AbsLong must be static");
137 static_assert(kIntrinsicIsStatic[kIntrinsicAbsFloat], "AbsFloat must be static");
138 static_assert(kIntrinsicIsStatic[kIntrinsicAbsDouble], "AbsDouble must be static");
139 static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxInt], "MinMaxInt must be static");
140 static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxLong], "MinMaxLong must be static");
141 static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], "MinMaxFloat must be static");
142 static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], "MinMaxDouble must be static");
143 static_assert(kIntrinsicIsStatic[kIntrinsicCos], "Cos must be static");
144 static_assert(kIntrinsicIsStatic[kIntrinsicSin], "Sin must be static");
145 static_assert(kIntrinsicIsStatic[kIntrinsicAcos], "Acos must be static");
146 static_assert(kIntrinsicIsStatic[kIntrinsicAsin], "Asin must be static");
147 static_assert(kIntrinsicIsStatic[kIntrinsicAtan], "Atan must be static");
148 static_assert(kIntrinsicIsStatic[kIntrinsicAtan2], "Atan2 must be static");
149 static_assert(kIntrinsicIsStatic[kIntrinsicCbrt], "Cbrt must be static");
150 static_assert(kIntrinsicIsStatic[kIntrinsicCosh], "Cosh must be static");
151 static_assert(kIntrinsicIsStatic[kIntrinsicExp], "Exp must be static");
152 static_assert(kIntrinsicIsStatic[kIntrinsicExpm1], "Expm1 must be static");
153 static_assert(kIntrinsicIsStatic[kIntrinsicHypot], "Hypot must be static");
154 static_assert(kIntrinsicIsStatic[kIntrinsicLog], "Log must be static");
155 static_assert(kIntrinsicIsStatic[kIntrinsicLog10], "Log10 must be static");
156 static_assert(kIntrinsicIsStatic[kIntrinsicNextAfter], "NextAfter must be static");
157 static_assert(kIntrinsicIsStatic[kIntrinsicSinh], "Sinh must be static");
158 static_assert(kIntrinsicIsStatic[kIntrinsicTan], "Tan must be static");
159 static_assert(kIntrinsicIsStatic[kIntrinsicTanh], "Tanh must be static");
160 static_assert(kIntrinsicIsStatic[kIntrinsicSqrt], "Sqrt must be static");
161 static_assert(kIntrinsicIsStatic[kIntrinsicCeil], "Ceil must be static");
162 static_assert(kIntrinsicIsStatic[kIntrinsicFloor], "Floor must be static");
163 static_assert(kIntrinsicIsStatic[kIntrinsicRint], "Rint must be static");
164 static_assert(kIntrinsicIsStatic[kIntrinsicRoundFloat], "RoundFloat must be static");
165 static_assert(kIntrinsicIsStatic[kIntrinsicRoundDouble], "RoundDouble must be static");
166 static_assert(!kIntrinsicIsStatic[kIntrinsicReferenceGetReferent], "Get must not be static");
167 static_assert(!kIntrinsicIsStatic[kIntrinsicCharAt], "CharAt must not be static");
168 static_assert(!kIntrinsicIsStatic[kIntrinsicCompareTo], "CompareTo must not be static");
169 static_assert(!kIntrinsicIsStatic[kIntrinsicEquals], "String equals must not be static");
170 static_assert(!kIntrinsicIsStatic[kIntrinsicGetCharsNoCheck], "GetCharsNoCheck must not be static");
171 static_assert(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], "IsEmptyOrLength must not be static");
172 static_assert(!kIntrinsicIsStatic[kIntrinsicIndexOf], "IndexOf must not be static");
173 static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromBytes],
174 "NewStringFromBytes must be static");
175 static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromChars],
176 "NewStringFromChars must be static");
177 static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromString],
178 "NewStringFromString must be static");
179 static_assert(kIntrinsicIsStatic[kIntrinsicCurrentThread], "CurrentThread must be static");
180 static_assert(kIntrinsicIsStatic[kIntrinsicPeek], "Peek must be static");
181 static_assert(kIntrinsicIsStatic[kIntrinsicPoke], "Poke must be static");
182 static_assert(!kIntrinsicIsStatic[kIntrinsicCas], "Cas must not be static");
183 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGet], "UnsafeGet must not be static");
184 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafePut], "UnsafePut must not be static");
185 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddInt], "UnsafeGetAndAddInt must not be static");
186 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddLong], "UnsafeGetAndAddLong must not be static");
187 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetInt], "UnsafeGetAndSetInt must not be static");
188 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetLong], "UnsafeGetAndSetLong must not be static");
189 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetObject], "UnsafeGetAndSetObject must not be static");
190 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeLoadFence], "UnsafeLoadFence must not be static");
191 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeStoreFence], "UnsafeStoreFence must not be static");
192 static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeFullFence], "UnsafeFullFence must not be static");
193 static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopyCharArray],
194 "SystemArrayCopyCharArray must be static");
195 static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopy],
196 "SystemArrayCopy must be static");
197
198 } // anonymous namespace
199
200 const uint32_t DexFileMethodInliner::kIndexUnresolved;
201 const char* const DexFileMethodInliner::kClassCacheNames[] = {
202 "Z", // kClassCacheBoolean
203 "B", // kClassCacheByte
204 "C", // kClassCacheChar
205 "S", // kClassCacheShort
206 "I", // kClassCacheInt
207 "J", // kClassCacheLong
208 "F", // kClassCacheFloat
209 "D", // kClassCacheDouble
210 "V", // kClassCacheVoid
211 "[B", // kClassCacheJavaLangByteArray
212 "[C", // kClassCacheJavaLangCharArray
213 "[I", // kClassCacheJavaLangIntArray
214 "Ljava/lang/Object;", // kClassCacheJavaLangObject
215 "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference
216 "Ljava/lang/String;", // kClassCacheJavaLangString
217 "Ljava/lang/StringBuffer;", // kClassCacheJavaLangStringBuffer
218 "Ljava/lang/StringBuilder;", // kClassCacheJavaLangStringBuilder
219 "Ljava/lang/StringFactory;", // kClassCacheJavaLangStringFactory
220 "Ljava/lang/Double;", // kClassCacheJavaLangDouble
221 "Ljava/lang/Float;", // kClassCacheJavaLangFloat
222 "Ljava/lang/Integer;", // kClassCacheJavaLangInteger
223 "Ljava/lang/Long;", // kClassCacheJavaLangLong
224 "Ljava/lang/Short;", // kClassCacheJavaLangShort
225 "Ljava/lang/Math;", // kClassCacheJavaLangMath
226 "Ljava/lang/StrictMath;", // kClassCacheJavaLangStrictMath
227 "Ljava/lang/Thread;", // kClassCacheJavaLangThread
228 "Ljava/nio/charset/Charset;", // kClassCacheJavaNioCharsetCharset
229 "Llibcore/io/Memory;", // kClassCacheLibcoreIoMemory
230 "Lsun/misc/Unsafe;", // kClassCacheSunMiscUnsafe
231 "Ljava/lang/System;", // kClassCacheJavaLangSystem
232 };
233
234 const char* const DexFileMethodInliner::kNameCacheNames[] = {
235 "reverse", // kNameCacheReverse
236 "reverseBytes", // kNameCacheReverseBytes
237 "doubleToRawLongBits", // kNameCacheDoubleToRawLongBits
238 "longBitsToDouble", // kNameCacheLongBitsToDouble
239 "floatToRawIntBits", // kNameCacheFloatToRawIntBits
240 "intBitsToFloat", // kNameCacheIntBitsToFloat
241 "abs", // kNameCacheAbs
242 "max", // kNameCacheMax
243 "min", // kNameCacheMin
244 "cos", // kNameCacheCos
245 "sin", // kNameCacheSin
246 "acos", // kNameCacheAcos
247 "asin", // kNameCacheAsin
248 "atan", // kNameCacheAtan
249 "atan2", // kNameCacheAtan2
250 "cbrt", // kNameCacheCbrt
251 "cosh", // kNameCacheCosh
252 "exp", // kNameCacheExp
253 "expm1", // kNameCacheExpm1
254 "hypot", // kNameCacheHypot
255 "log", // kNameCacheLog
256 "log10", // kNameCacheLog10
257 "nextAfter", // kNameCacheNextAfter
258 "sinh", // kNameCacheSinh
259 "tan", // kNameCacheTan
260 "tanh", // kNameCacheTanh
261 "sqrt", // kNameCacheSqrt
262 "ceil", // kNameCacheCeil
263 "floor", // kNameCacheFloor
264 "rint", // kNameCacheRint
265 "round", // kNameCacheRound
266 "getReferent", // kNameCacheReferenceGet
267 "charAt", // kNameCacheCharAt
268 "compareTo", // kNameCacheCompareTo
269 "equals", // kNameCacheEquals
270 "getCharsNoCheck", // kNameCacheGetCharsNoCheck
271 "isEmpty", // kNameCacheIsEmpty
272 "floatToIntBits", // kNameCacheFloatToIntBits
273 "doubleToLongBits", // kNameCacheDoubleToLongBits
274 "isInfinite", // kNameCacheIsInfinite
275 "isNaN", // kNameCacheIsNaN
276 "indexOf", // kNameCacheIndexOf
277 "length", // kNameCacheLength
278 "<init>", // kNameCacheInit
279 "newStringFromBytes", // kNameCacheNewStringFromBytes
280 "newStringFromChars", // kNameCacheNewStringFromChars
281 "newStringFromString", // kNameCacheNewStringFromString
282 "currentThread", // kNameCacheCurrentThread
283 "peekByte", // kNameCachePeekByte
284 "peekIntNative", // kNameCachePeekIntNative
285 "peekLongNative", // kNameCachePeekLongNative
286 "peekShortNative", // kNameCachePeekShortNative
287 "pokeByte", // kNameCachePokeByte
288 "pokeIntNative", // kNameCachePokeIntNative
289 "pokeLongNative", // kNameCachePokeLongNative
290 "pokeShortNative", // kNameCachePokeShortNative
291 "compareAndSwapInt", // kNameCacheCompareAndSwapInt
292 "compareAndSwapLong", // kNameCacheCompareAndSwapLong
293 "compareAndSwapObject", // kNameCacheCompareAndSwapObject
294 "getInt", // kNameCacheGetInt
295 "getIntVolatile", // kNameCacheGetIntVolatile
296 "putInt", // kNameCachePutInt
297 "putIntVolatile", // kNameCachePutIntVolatile
298 "putOrderedInt", // kNameCachePutOrderedInt
299 "getLong", // kNameCacheGetLong
300 "getLongVolatile", // kNameCacheGetLongVolatile
301 "putLong", // kNameCachePutLong
302 "putLongVolatile", // kNameCachePutLongVolatile
303 "putOrderedLong", // kNameCachePutOrderedLong
304 "getObject", // kNameCacheGetObject
305 "getObjectVolatile", // kNameCacheGetObjectVolatile
306 "putObject", // kNameCachePutObject
307 "putObjectVolatile", // kNameCachePutObjectVolatile
308 "putOrderedObject", // kNameCachePutOrderedObject
309 "getAndAddInt", // kNameCacheGetAndAddInt,
310 "getAndAddLong", // kNameCacheGetAndAddLong,
311 "getAndSetInt", // kNameCacheGetAndSetInt,
312 "getAndSetLong", // kNameCacheGetAndSetLong,
313 "getAndSetObject", // kNameCacheGetAndSetObject,
314 "loadFence", // kNameCacheLoadFence,
315 "storeFence", // kNameCacheStoreFence,
316 "fullFence", // kNameCacheFullFence,
317 "arraycopy", // kNameCacheArrayCopy
318 "bitCount", // kNameCacheBitCount
319 "compare", // kNameCacheCompare
320 "highestOneBit", // kNameCacheHighestOneBit
321 "lowestOneBit", // kNameCacheLowestOneBit
322 "numberOfLeadingZeros", // kNameCacheNumberOfLeadingZeros
323 "numberOfTrailingZeros", // kNameCacheNumberOfTrailingZeros
324 "rotateRight", // kNameCacheRotateRight
325 "rotateLeft", // kNameCacheRotateLeft
326 "signum", // kNameCacheSignum
327 };
328
329 const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = {
330 // kProtoCacheI_I
331 { kClassCacheInt, 1, { kClassCacheInt } },
332 // kProtoCacheJ_J
333 { kClassCacheLong, 1, { kClassCacheLong } },
334 // kProtoCacheS_S
335 { kClassCacheShort, 1, { kClassCacheShort } },
336 // kProtoCacheD_D
337 { kClassCacheDouble, 1, { kClassCacheDouble } },
338 // kProtoCacheDD_D
339 { kClassCacheDouble, 2, { kClassCacheDouble, kClassCacheDouble } },
340 // kProtoCacheF_F
341 { kClassCacheFloat, 1, { kClassCacheFloat } },
342 // kProtoCacheFF_F
343 { kClassCacheFloat, 2, { kClassCacheFloat, kClassCacheFloat } },
344 // kProtoCacheD_J
345 { kClassCacheLong, 1, { kClassCacheDouble } },
346 // kProtoCacheD_Z
347 { kClassCacheBoolean, 1, { kClassCacheDouble } },
348 // kProtoCacheJ_D
349 { kClassCacheDouble, 1, { kClassCacheLong } },
350 // kProtoCacheF_I
351 { kClassCacheInt, 1, { kClassCacheFloat } },
352 // kProtoCacheF_Z
353 { kClassCacheBoolean, 1, { kClassCacheFloat } },
354 // kProtoCacheI_F
355 { kClassCacheFloat, 1, { kClassCacheInt } },
356 // kProtoCacheII_I
357 { kClassCacheInt, 2, { kClassCacheInt, kClassCacheInt } },
358 // kProtoCacheI_C
359 { kClassCacheChar, 1, { kClassCacheInt } },
360 // kProtoCacheString_I
361 { kClassCacheInt, 1, { kClassCacheJavaLangString } },
362 // kProtoCache_Z
363 { kClassCacheBoolean, 0, { } },
364 // kProtoCache_I
365 { kClassCacheInt, 0, { } },
366 // kProtoCache_Object
367 { kClassCacheJavaLangObject, 0, { } },
368 // kProtoCache_Thread
369 { kClassCacheJavaLangThread, 0, { } },
370 // kProtoCacheJ_B
371 { kClassCacheByte, 1, { kClassCacheLong } },
372 // kProtoCacheJ_I
373 { kClassCacheInt, 1, { kClassCacheLong } },
374 // kProtoCacheJ_S
375 { kClassCacheShort, 1, { kClassCacheLong } },
376 // kProtoCacheJB_V
377 { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheByte } },
378 // kProtoCacheJI_V
379 { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheInt } },
380 // kProtoCacheJJ_J
381 { kClassCacheLong, 2, { kClassCacheLong, kClassCacheLong } },
382 // kProtoCacheJJ_I
383 { kClassCacheInt, 2, { kClassCacheLong, kClassCacheLong } },
384 // kProtoCacheJJ_V
385 { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheLong } },
386 // kProtoCacheJS_V
387 { kClassCacheVoid, 2, { kClassCacheLong, kClassCacheShort } },
388 // kProtoCacheObject_Z
389 { kClassCacheBoolean, 1, { kClassCacheJavaLangObject } },
390 // kProtoCacheJI_J
391 { kClassCacheLong, 2, { kClassCacheLong, kClassCacheInt } },
392 // kProtoCacheObjectJII_Z
393 { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
394 kClassCacheInt, kClassCacheInt } },
395 // kProtoCacheObjectJJJ_Z
396 { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
397 kClassCacheLong, kClassCacheLong } },
398 // kProtoCacheObjectJObjectObject_Z
399 { kClassCacheBoolean, 4, { kClassCacheJavaLangObject, kClassCacheLong,
400 kClassCacheJavaLangObject, kClassCacheJavaLangObject } },
401 // kProtoCacheObjectJ_I
402 { kClassCacheInt, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
403 // kProtoCacheObjectJI_I
404 { kClassCacheInt, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
405 // kProtoCacheObjectJI_V
406 { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheInt } },
407 // kProtoCacheObjectJ_J
408 { kClassCacheLong, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
409 // kProtoCacheObjectJJ_J
410 { kClassCacheLong, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
411 // kProtoCacheObjectJJ_V
412 { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong, kClassCacheLong } },
413 // kProtoCacheObjectJ_Object
414 { kClassCacheJavaLangObject, 2, { kClassCacheJavaLangObject, kClassCacheLong } },
415 // kProtoCacheObjectJObject_V
416 { kClassCacheVoid, 3, { kClassCacheJavaLangObject, kClassCacheLong,
417 kClassCacheJavaLangObject } },
418 // kProtoCacheObjectJObject_Object
419 { kClassCacheJavaLangObject, 3, { kClassCacheJavaLangObject, kClassCacheLong,
420 kClassCacheJavaLangObject } },
421 // kProtoCacheCharArrayICharArrayII_V
422 { kClassCacheVoid, 5, {kClassCacheJavaLangCharArray, kClassCacheInt,
423 kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt} },
424 // kProtoCacheObjectIObjectII_V
425 { kClassCacheVoid, 5, {kClassCacheJavaLangObject, kClassCacheInt,
426 kClassCacheJavaLangObject, kClassCacheInt, kClassCacheInt} },
427 // kProtoCacheIICharArrayI_V
428 { kClassCacheVoid, 4, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray,
429 kClassCacheInt } },
430 // kProtoCacheByteArrayIII_String
431 { kClassCacheJavaLangString, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
432 kClassCacheInt } },
433 // kProtoCacheIICharArray_String
434 { kClassCacheJavaLangString, 3, { kClassCacheInt, kClassCacheInt,
435 kClassCacheJavaLangCharArray } },
436 // kProtoCacheString_String
437 { kClassCacheJavaLangString, 1, { kClassCacheJavaLangString } },
438 // kProtoCache_V
439 { kClassCacheVoid, 0, { } },
440 // kProtoCacheByteArray_V
441 { kClassCacheVoid, 1, { kClassCacheJavaLangByteArray } },
442 // kProtoCacheByteArrayI_V
443 { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheInt } },
444 // kProtoCacheByteArrayII_V
445 { kClassCacheVoid, 3, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt } },
446 // kProtoCacheByteArrayIII_V
447 { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
448 kClassCacheInt } },
449 // kProtoCacheByteArrayIIString_V
450 { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
451 kClassCacheJavaLangString } },
452 // kProtoCacheByteArrayString_V
453 { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaLangString } },
454 // kProtoCacheByteArrayIICharset_V
455 { kClassCacheVoid, 4, { kClassCacheJavaLangByteArray, kClassCacheInt, kClassCacheInt,
456 kClassCacheJavaNioCharsetCharset } },
457 // kProtoCacheByteArrayCharset_V
458 { kClassCacheVoid, 2, { kClassCacheJavaLangByteArray, kClassCacheJavaNioCharsetCharset } },
459 // kProtoCacheCharArray_V
460 { kClassCacheVoid, 1, { kClassCacheJavaLangCharArray } },
461 // kProtoCacheCharArrayII_V
462 { kClassCacheVoid, 3, { kClassCacheJavaLangCharArray, kClassCacheInt, kClassCacheInt } },
463 // kProtoCacheIICharArray_V
464 { kClassCacheVoid, 3, { kClassCacheInt, kClassCacheInt, kClassCacheJavaLangCharArray } },
465 // kProtoCacheIntArrayII_V
466 { kClassCacheVoid, 3, { kClassCacheJavaLangIntArray, kClassCacheInt, kClassCacheInt } },
467 // kProtoCacheString_V
468 { kClassCacheVoid, 1, { kClassCacheJavaLangString } },
469 // kProtoCacheStringBuffer_V
470 { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuffer } },
471 // kProtoCacheStringBuilder_V
472 { kClassCacheVoid, 1, { kClassCacheJavaLangStringBuilder } },
473 };
474
475 const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods[] = {
476 #define INTRINSIC(c, n, p, o, d) \
477 { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineIntrinsic, { d } } }
478
479 INTRINSIC(JavaLangDouble, DoubleToRawLongBits, D_J, kIntrinsicDoubleCvt, 0),
480 INTRINSIC(JavaLangDouble, LongBitsToDouble, J_D, kIntrinsicDoubleCvt, kIntrinsicFlagToFloatingPoint),
481 INTRINSIC(JavaLangFloat, FloatToRawIntBits, F_I, kIntrinsicFloatCvt, 0),
482 INTRINSIC(JavaLangFloat, IntBitsToFloat, I_F, kIntrinsicFloatCvt, kIntrinsicFlagToFloatingPoint),
483
484 INTRINSIC(JavaLangFloat, FloatToIntBits, F_I, kIntrinsicFloat2Int, 0),
485 INTRINSIC(JavaLangDouble, DoubleToLongBits, D_J, kIntrinsicDouble2Long, 0),
486
487 INTRINSIC(JavaLangFloat, IsInfinite, F_Z, kIntrinsicFloatIsInfinite, 0),
488 INTRINSIC(JavaLangDouble, IsInfinite, D_Z, kIntrinsicDoubleIsInfinite, 0),
489 INTRINSIC(JavaLangFloat, IsNaN, F_Z, kIntrinsicFloatIsNaN, 0),
490 INTRINSIC(JavaLangDouble, IsNaN, D_Z, kIntrinsicDoubleIsNaN, 0),
491
492 INTRINSIC(JavaLangInteger, ReverseBytes, I_I, kIntrinsicReverseBytes, k32),
493 INTRINSIC(JavaLangLong, ReverseBytes, J_J, kIntrinsicReverseBytes, k64),
494 INTRINSIC(JavaLangShort, ReverseBytes, S_S, kIntrinsicReverseBytes, kSignedHalf),
495 INTRINSIC(JavaLangInteger, Reverse, I_I, kIntrinsicReverseBits, k32),
496 INTRINSIC(JavaLangLong, Reverse, J_J, kIntrinsicReverseBits, k64),
497
498 INTRINSIC(JavaLangInteger, BitCount, I_I, kIntrinsicBitCount, k32),
499 INTRINSIC(JavaLangLong, BitCount, J_I, kIntrinsicBitCount, k64),
500 INTRINSIC(JavaLangInteger, Compare, II_I, kIntrinsicCompare, k32),
501 INTRINSIC(JavaLangLong, Compare, JJ_I, kIntrinsicCompare, k64),
502 INTRINSIC(JavaLangInteger, HighestOneBit, I_I, kIntrinsicHighestOneBit, k32),
503 INTRINSIC(JavaLangLong, HighestOneBit, J_J, kIntrinsicHighestOneBit, k64),
504 INTRINSIC(JavaLangInteger, LowestOneBit, I_I, kIntrinsicLowestOneBit, k32),
505 INTRINSIC(JavaLangLong, LowestOneBit, J_J, kIntrinsicLowestOneBit, k64),
506 INTRINSIC(JavaLangInteger, NumberOfLeadingZeros, I_I, kIntrinsicNumberOfLeadingZeros, k32),
507 INTRINSIC(JavaLangLong, NumberOfLeadingZeros, J_I, kIntrinsicNumberOfLeadingZeros, k64),
508 INTRINSIC(JavaLangInteger, NumberOfTrailingZeros, I_I, kIntrinsicNumberOfTrailingZeros, k32),
509 INTRINSIC(JavaLangLong, NumberOfTrailingZeros, J_I, kIntrinsicNumberOfTrailingZeros, k64),
510 INTRINSIC(JavaLangInteger, Signum, I_I, kIntrinsicSignum, k32),
511 INTRINSIC(JavaLangLong, Signum, J_I, kIntrinsicSignum, k64),
512
513 INTRINSIC(JavaLangMath, Abs, I_I, kIntrinsicAbsInt, 0),
514 INTRINSIC(JavaLangStrictMath, Abs, I_I, kIntrinsicAbsInt, 0),
515 INTRINSIC(JavaLangMath, Abs, J_J, kIntrinsicAbsLong, 0),
516 INTRINSIC(JavaLangStrictMath, Abs, J_J, kIntrinsicAbsLong, 0),
517 INTRINSIC(JavaLangMath, Abs, F_F, kIntrinsicAbsFloat, 0),
518 INTRINSIC(JavaLangStrictMath, Abs, F_F, kIntrinsicAbsFloat, 0),
519 INTRINSIC(JavaLangMath, Abs, D_D, kIntrinsicAbsDouble, 0),
520 INTRINSIC(JavaLangStrictMath, Abs, D_D, kIntrinsicAbsDouble, 0),
521 INTRINSIC(JavaLangMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
522 INTRINSIC(JavaLangStrictMath, Min, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMin),
523 INTRINSIC(JavaLangMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
524 INTRINSIC(JavaLangStrictMath, Max, II_I, kIntrinsicMinMaxInt, kIntrinsicFlagMax),
525 INTRINSIC(JavaLangMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
526 INTRINSIC(JavaLangStrictMath, Min, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMin),
527 INTRINSIC(JavaLangMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
528 INTRINSIC(JavaLangStrictMath, Max, JJ_J, kIntrinsicMinMaxLong, kIntrinsicFlagMax),
529 INTRINSIC(JavaLangMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
530 INTRINSIC(JavaLangStrictMath, Min, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMin),
531 INTRINSIC(JavaLangMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
532 INTRINSIC(JavaLangStrictMath, Max, FF_F, kIntrinsicMinMaxFloat, kIntrinsicFlagMax),
533 INTRINSIC(JavaLangMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
534 INTRINSIC(JavaLangStrictMath, Min, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMin),
535 INTRINSIC(JavaLangMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
536 INTRINSIC(JavaLangStrictMath, Max, DD_D, kIntrinsicMinMaxDouble, kIntrinsicFlagMax),
537
538 INTRINSIC(JavaLangMath, Cos, D_D, kIntrinsicCos, 0),
539 INTRINSIC(JavaLangMath, Sin, D_D, kIntrinsicSin, 0),
540 INTRINSIC(JavaLangMath, Acos, D_D, kIntrinsicAcos, 0),
541 INTRINSIC(JavaLangMath, Asin, D_D, kIntrinsicAsin, 0),
542 INTRINSIC(JavaLangMath, Atan, D_D, kIntrinsicAtan, 0),
543 INTRINSIC(JavaLangMath, Atan2, DD_D, kIntrinsicAtan2, 0),
544 INTRINSIC(JavaLangMath, Cbrt, D_D, kIntrinsicCbrt, 0),
545 INTRINSIC(JavaLangMath, Cosh, D_D, kIntrinsicCosh, 0),
546 INTRINSIC(JavaLangMath, Exp, D_D, kIntrinsicExp, 0),
547 INTRINSIC(JavaLangMath, Expm1, D_D, kIntrinsicExpm1, 0),
548 INTRINSIC(JavaLangMath, Hypot, DD_D, kIntrinsicHypot, 0),
549 INTRINSIC(JavaLangMath, Log, D_D, kIntrinsicLog, 0),
550 INTRINSIC(JavaLangMath, Log10, D_D, kIntrinsicLog10, 0),
551 INTRINSIC(JavaLangMath, NextAfter, DD_D, kIntrinsicNextAfter, 0),
552 INTRINSIC(JavaLangMath, Sinh, D_D, kIntrinsicSinh, 0),
553 INTRINSIC(JavaLangMath, Tan, D_D, kIntrinsicTan, 0),
554 INTRINSIC(JavaLangMath, Tanh, D_D, kIntrinsicTanh, 0),
555 INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0),
556 INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0),
557
558 INTRINSIC(JavaLangMath, Ceil, D_D, kIntrinsicCeil, 0),
559 INTRINSIC(JavaLangStrictMath, Ceil, D_D, kIntrinsicCeil, 0),
560 INTRINSIC(JavaLangMath, Floor, D_D, kIntrinsicFloor, 0),
561 INTRINSIC(JavaLangStrictMath, Floor, D_D, kIntrinsicFloor, 0),
562 INTRINSIC(JavaLangMath, Rint, D_D, kIntrinsicRint, 0),
563 INTRINSIC(JavaLangStrictMath, Rint, D_D, kIntrinsicRint, 0),
564 INTRINSIC(JavaLangMath, Round, F_I, kIntrinsicRoundFloat, 0),
565 INTRINSIC(JavaLangStrictMath, Round, F_I, kIntrinsicRoundFloat, 0),
566 INTRINSIC(JavaLangMath, Round, D_J, kIntrinsicRoundDouble, 0),
567 INTRINSIC(JavaLangStrictMath, Round, D_J, kIntrinsicRoundDouble, 0),
568
569 INTRINSIC(JavaLangRefReference, ReferenceGetReferent, _Object, kIntrinsicReferenceGetReferent, 0),
570
571 INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0),
572 INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0),
573 INTRINSIC(JavaLangString, Equals, Object_Z, kIntrinsicEquals, 0),
574 INTRINSIC(JavaLangString, GetCharsNoCheck, IICharArrayI_V, kIntrinsicGetCharsNoCheck, 0),
575 INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty),
576 INTRINSIC(JavaLangString, IndexOf, II_I, kIntrinsicIndexOf, kIntrinsicFlagNone),
577 INTRINSIC(JavaLangString, IndexOf, I_I, kIntrinsicIndexOf, kIntrinsicFlagBase0),
578 INTRINSIC(JavaLangString, Length, _I, kIntrinsicIsEmptyOrLength, kIntrinsicFlagLength),
579
580 INTRINSIC(JavaLangStringFactory, NewStringFromBytes, ByteArrayIII_String,
581 kIntrinsicNewStringFromBytes, kIntrinsicFlagNone),
582 INTRINSIC(JavaLangStringFactory, NewStringFromChars, IICharArray_String,
583 kIntrinsicNewStringFromChars, kIntrinsicFlagNone),
584 INTRINSIC(JavaLangStringFactory, NewStringFromString, String_String,
585 kIntrinsicNewStringFromString, kIntrinsicFlagNone),
586
587 INTRINSIC(JavaLangThread, CurrentThread, _Thread, kIntrinsicCurrentThread, 0),
588
589 INTRINSIC(LibcoreIoMemory, PeekByte, J_B, kIntrinsicPeek, kSignedByte),
590 INTRINSIC(LibcoreIoMemory, PeekIntNative, J_I, kIntrinsicPeek, k32),
591 INTRINSIC(LibcoreIoMemory, PeekLongNative, J_J, kIntrinsicPeek, k64),
592 INTRINSIC(LibcoreIoMemory, PeekShortNative, J_S, kIntrinsicPeek, kSignedHalf),
593 INTRINSIC(LibcoreIoMemory, PokeByte, JB_V, kIntrinsicPoke, kSignedByte),
594 INTRINSIC(LibcoreIoMemory, PokeIntNative, JI_V, kIntrinsicPoke, k32),
595 INTRINSIC(LibcoreIoMemory, PokeLongNative, JJ_V, kIntrinsicPoke, k64),
596 INTRINSIC(LibcoreIoMemory, PokeShortNative, JS_V, kIntrinsicPoke, kSignedHalf),
597
598 INTRINSIC(SunMiscUnsafe, CompareAndSwapInt, ObjectJII_Z, kIntrinsicCas,
599 kIntrinsicFlagNone),
600 INTRINSIC(SunMiscUnsafe, CompareAndSwapLong, ObjectJJJ_Z, kIntrinsicCas,
601 kIntrinsicFlagIsLong),
602 INTRINSIC(SunMiscUnsafe, CompareAndSwapObject, ObjectJObjectObject_Z, kIntrinsicCas,
603 kIntrinsicFlagIsObject),
604
605 #define UNSAFE_GET_PUT(type, code, type_flags) \
606 INTRINSIC(SunMiscUnsafe, Get ## type, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
607 type_flags), \
608 INTRINSIC(SunMiscUnsafe, Get ## type ## Volatile, ObjectJ_ ## code, kIntrinsicUnsafeGet, \
609 type_flags | kIntrinsicFlagIsVolatile), \
610 INTRINSIC(SunMiscUnsafe, Put ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
611 type_flags), \
612 INTRINSIC(SunMiscUnsafe, Put ## type ## Volatile, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
613 type_flags | kIntrinsicFlagIsVolatile), \
614 INTRINSIC(SunMiscUnsafe, PutOrdered ## type, ObjectJ ## code ## _V, kIntrinsicUnsafePut, \
615 type_flags | kIntrinsicFlagIsOrdered)
616
617 UNSAFE_GET_PUT(Int, I, kIntrinsicFlagNone),
618 UNSAFE_GET_PUT(Long, J, kIntrinsicFlagIsLong),
619 UNSAFE_GET_PUT(Object, Object, kIntrinsicFlagIsObject),
620 #undef UNSAFE_GET_PUT
621
622 // 1.8
623 INTRINSIC(SunMiscUnsafe, GetAndAddInt, ObjectJI_I, kIntrinsicUnsafeGetAndAddInt, 0),
624 INTRINSIC(SunMiscUnsafe, GetAndAddLong, ObjectJJ_J, kIntrinsicUnsafeGetAndAddLong, 0),
625 INTRINSIC(SunMiscUnsafe, GetAndSetInt, ObjectJI_I, kIntrinsicUnsafeGetAndSetInt, 0),
626 INTRINSIC(SunMiscUnsafe, GetAndSetLong, ObjectJJ_J, kIntrinsicUnsafeGetAndSetLong, 0),
627 INTRINSIC(SunMiscUnsafe, GetAndSetObject, ObjectJObject_Object, kIntrinsicUnsafeGetAndSetObject, 0),
628 INTRINSIC(SunMiscUnsafe, LoadFence, _V, kIntrinsicUnsafeLoadFence, 0),
629 INTRINSIC(SunMiscUnsafe, StoreFence, _V, kIntrinsicUnsafeStoreFence, 0),
630 INTRINSIC(SunMiscUnsafe, FullFence, _V, kIntrinsicUnsafeFullFence, 0),
631
632 INTRINSIC(JavaLangSystem, ArrayCopy, CharArrayICharArrayII_V , kIntrinsicSystemArrayCopyCharArray,
633 0),
634 INTRINSIC(JavaLangSystem, ArrayCopy, ObjectIObjectII_V , kIntrinsicSystemArrayCopy,
635 0),
636
637 INTRINSIC(JavaLangInteger, RotateRight, II_I, kIntrinsicRotateRight, k32),
638 INTRINSIC(JavaLangLong, RotateRight, JI_J, kIntrinsicRotateRight, k64),
639 INTRINSIC(JavaLangInteger, RotateLeft, II_I, kIntrinsicRotateLeft, k32),
640 INTRINSIC(JavaLangLong, RotateLeft, JI_J, kIntrinsicRotateLeft, k64),
641
642 #undef INTRINSIC
643
644 #define SPECIAL(c, n, p, o, d) \
645 { { kClassCache ## c, kNameCache ## n, kProtoCache ## p }, { o, kInlineSpecial, { d } } }
646
647 SPECIAL(JavaLangString, Init, _V, kInlineStringInit, 0),
648 SPECIAL(JavaLangString, Init, ByteArray_V, kInlineStringInit, 1),
649 SPECIAL(JavaLangString, Init, ByteArrayI_V, kInlineStringInit, 2),
650 SPECIAL(JavaLangString, Init, ByteArrayII_V, kInlineStringInit, 3),
651 SPECIAL(JavaLangString, Init, ByteArrayIII_V, kInlineStringInit, 4),
652 SPECIAL(JavaLangString, Init, ByteArrayIIString_V, kInlineStringInit, 5),
653 SPECIAL(JavaLangString, Init, ByteArrayString_V, kInlineStringInit, 6),
654 SPECIAL(JavaLangString, Init, ByteArrayIICharset_V, kInlineStringInit, 7),
655 SPECIAL(JavaLangString, Init, ByteArrayCharset_V, kInlineStringInit, 8),
656 SPECIAL(JavaLangString, Init, CharArray_V, kInlineStringInit, 9),
657 SPECIAL(JavaLangString, Init, CharArrayII_V, kInlineStringInit, 10),
658 SPECIAL(JavaLangString, Init, IICharArray_V, kInlineStringInit, 11),
659 SPECIAL(JavaLangString, Init, IntArrayII_V, kInlineStringInit, 12),
660 SPECIAL(JavaLangString, Init, String_V, kInlineStringInit, 13),
661 SPECIAL(JavaLangString, Init, StringBuffer_V, kInlineStringInit, 14),
662 SPECIAL(JavaLangString, Init, StringBuilder_V, kInlineStringInit, 15),
663
664 #undef SPECIAL
665 };
666
DexFileMethodInliner()667 DexFileMethodInliner::DexFileMethodInliner()
668 : lock_("DexFileMethodInliner lock", kDexFileMethodInlinerLock),
669 dex_file_(nullptr) {
670 static_assert(kClassCacheFirst == 0, "kClassCacheFirst not 0");
671 static_assert(arraysize(kClassCacheNames) == kClassCacheLast,
672 "bad arraysize for kClassCacheNames");
673 static_assert(kNameCacheFirst == 0, "kNameCacheFirst not 0");
674 static_assert(arraysize(kNameCacheNames) == kNameCacheLast,
675 "bad arraysize for kNameCacheNames");
676 static_assert(kProtoCacheFirst == 0, "kProtoCacheFirst not 0");
677 static_assert(arraysize(kProtoCacheDefs) == kProtoCacheLast,
678 "bad arraysize kProtoCacheNames");
679 }
680
~DexFileMethodInliner()681 DexFileMethodInliner::~DexFileMethodInliner() {
682 }
683
AnalyseMethodCode(verifier::MethodVerifier * verifier)684 bool DexFileMethodInliner::AnalyseMethodCode(verifier::MethodVerifier* verifier) {
685 InlineMethod method;
686 bool success = InlineMethodAnalyser::AnalyseMethodCode(verifier, &method);
687 return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method);
688 }
689
IsIntrinsicOrSpecial(uint32_t method_index)690 InlineMethodFlags DexFileMethodInliner::IsIntrinsicOrSpecial(uint32_t method_index) {
691 ReaderMutexLock mu(Thread::Current(), lock_);
692 auto it = inline_methods_.find(method_index);
693 if (it != inline_methods_.end()) {
694 DCHECK_NE(it->second.flags & (kInlineIntrinsic | kInlineSpecial), 0);
695 return it->second.flags;
696 } else {
697 return kNoInlineMethodFlags;
698 }
699 }
700
IsIntrinsic(uint32_t method_index,InlineMethod * intrinsic)701 bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) {
702 ReaderMutexLock mu(Thread::Current(), lock_);
703 auto it = inline_methods_.find(method_index);
704 bool res = (it != inline_methods_.end() && (it->second.flags & kInlineIntrinsic) != 0);
705 if (res && intrinsic != nullptr) {
706 *intrinsic = it->second;
707 }
708 return res;
709 }
710
IsSpecial(uint32_t method_index)711 bool DexFileMethodInliner::IsSpecial(uint32_t method_index) {
712 ReaderMutexLock mu(Thread::Current(), lock_);
713 auto it = inline_methods_.find(method_index);
714 return it != inline_methods_.end() && (it->second.flags & kInlineSpecial) != 0;
715 }
716
FindClassIndex(const DexFile * dex_file,IndexCache * cache,ClassCacheIndex index)717 uint32_t DexFileMethodInliner::FindClassIndex(const DexFile* dex_file, IndexCache* cache,
718 ClassCacheIndex index) {
719 uint32_t* class_index = &cache->class_indexes[index];
720 if (*class_index != kIndexUnresolved) {
721 return *class_index;
722 }
723
724 const DexFile::TypeId* type_id = dex_file->FindTypeId(kClassCacheNames[index]);
725 if (type_id == nullptr) {
726 *class_index = kIndexNotFound;
727 return *class_index;
728 }
729 *class_index = dex_file->GetIndexForTypeId(*type_id);
730 return *class_index;
731 }
732
FindNameIndex(const DexFile * dex_file,IndexCache * cache,NameCacheIndex index)733 uint32_t DexFileMethodInliner::FindNameIndex(const DexFile* dex_file, IndexCache* cache,
734 NameCacheIndex index) {
735 uint32_t* name_index = &cache->name_indexes[index];
736 if (*name_index != kIndexUnresolved) {
737 return *name_index;
738 }
739
740 const DexFile::StringId* string_id = dex_file->FindStringId(kNameCacheNames[index]);
741 if (string_id == nullptr) {
742 *name_index = kIndexNotFound;
743 return *name_index;
744 }
745 *name_index = dex_file->GetIndexForStringId(*string_id);
746 return *name_index;
747 }
748
FindProtoIndex(const DexFile * dex_file,IndexCache * cache,ProtoCacheIndex index)749 uint32_t DexFileMethodInliner::FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
750 ProtoCacheIndex index) {
751 uint32_t* proto_index = &cache->proto_indexes[index];
752 if (*proto_index != kIndexUnresolved) {
753 return *proto_index;
754 }
755
756 const ProtoDef& proto_def = kProtoCacheDefs[index];
757 uint32_t return_index = FindClassIndex(dex_file, cache, proto_def.return_type);
758 if (return_index == kIndexNotFound) {
759 *proto_index = kIndexNotFound;
760 return *proto_index;
761 }
762 uint16_t return_type = static_cast<uint16_t>(return_index);
763 DCHECK_EQ(static_cast<uint32_t>(return_type), return_index);
764
765 uint32_t signature_length = proto_def.param_count;
766 uint16_t signature_type_idxs[kProtoMaxParams];
767 for (uint32_t i = 0; i != signature_length; ++i) {
768 uint32_t param_index = FindClassIndex(dex_file, cache, proto_def.params[i]);
769 if (param_index == kIndexNotFound) {
770 *proto_index = kIndexNotFound;
771 return *proto_index;
772 }
773 signature_type_idxs[i] = static_cast<uint16_t>(param_index);
774 DCHECK_EQ(static_cast<uint32_t>(signature_type_idxs[i]), param_index);
775 }
776
777 const DexFile::ProtoId* proto_id = dex_file->FindProtoId(return_type, signature_type_idxs,
778 signature_length);
779 if (proto_id == nullptr) {
780 *proto_index = kIndexNotFound;
781 return *proto_index;
782 }
783 *proto_index = dex_file->GetIndexForProtoId(*proto_id);
784 return *proto_index;
785 }
786
FindMethodIndex(const DexFile * dex_file,IndexCache * cache,const MethodDef & method_def)787 uint32_t DexFileMethodInliner::FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
788 const MethodDef& method_def) {
789 uint32_t declaring_class_index = FindClassIndex(dex_file, cache, method_def.declaring_class);
790 if (declaring_class_index == kIndexNotFound) {
791 return kIndexNotFound;
792 }
793 uint32_t name_index = FindNameIndex(dex_file, cache, method_def.name);
794 if (name_index == kIndexNotFound) {
795 return kIndexNotFound;
796 }
797 uint32_t proto_index = FindProtoIndex(dex_file, cache, method_def.proto);
798 if (proto_index == kIndexNotFound) {
799 return kIndexNotFound;
800 }
801 const DexFile::MethodId* method_id =
802 dex_file->FindMethodId(dex_file->GetTypeId(declaring_class_index),
803 dex_file->GetStringId(name_index),
804 dex_file->GetProtoId(proto_index));
805 if (method_id == nullptr) {
806 return kIndexNotFound;
807 }
808 return dex_file->GetIndexForMethodId(*method_id);
809 }
810
IndexCache()811 DexFileMethodInliner::IndexCache::IndexCache() {
812 std::fill_n(class_indexes, arraysize(class_indexes), kIndexUnresolved);
813 std::fill_n(name_indexes, arraysize(name_indexes), kIndexUnresolved);
814 std::fill_n(proto_indexes, arraysize(proto_indexes), kIndexUnresolved);
815 }
816
FindIntrinsics(const DexFile * dex_file)817 void DexFileMethodInliner::FindIntrinsics(const DexFile* dex_file) {
818 DCHECK(dex_file != nullptr);
819 DCHECK(dex_file_ == nullptr);
820 IndexCache cache;
821 for (const IntrinsicDef& def : kIntrinsicMethods) {
822 uint32_t method_idx = FindMethodIndex(dex_file, &cache, def.method_def);
823 if (method_idx != kIndexNotFound) {
824 DCHECK(inline_methods_.find(method_idx) == inline_methods_.end());
825 inline_methods_.Put(method_idx, def.intrinsic);
826 }
827 }
828 dex_file_ = dex_file;
829 }
830
AddInlineMethod(int32_t method_idx,const InlineMethod & method)831 bool DexFileMethodInliner::AddInlineMethod(int32_t method_idx, const InlineMethod& method) {
832 WriterMutexLock mu(Thread::Current(), lock_);
833 if (LIKELY(inline_methods_.find(method_idx) == inline_methods_.end())) {
834 inline_methods_.Put(method_idx, method);
835 return true;
836 } else {
837 if (PrettyMethod(method_idx, *dex_file_) == "int java.lang.String.length()") {
838 // TODO: String.length is both kIntrinsicIsEmptyOrLength and kInlineOpIGet.
839 } else {
840 LOG(WARNING) << "Inliner: " << PrettyMethod(method_idx, *dex_file_) << " already inline";
841 }
842 return false;
843 }
844 }
845
GetOffsetForStringInit(uint32_t method_index,size_t pointer_size)846 uint32_t DexFileMethodInliner::GetOffsetForStringInit(uint32_t method_index, size_t pointer_size) {
847 ReaderMutexLock mu(Thread::Current(), lock_);
848 auto it = inline_methods_.find(method_index);
849 if (it != inline_methods_.end() && (it->second.opcode == kInlineStringInit)) {
850 uint32_t string_init_base_offset = Thread::QuickEntryPointOffsetWithSize(
851 OFFSETOF_MEMBER(QuickEntryPoints, pNewEmptyString), pointer_size);
852 return string_init_base_offset + it->second.d.data * pointer_size;
853 }
854 return 0;
855 }
856
IsStringInitMethodIndex(uint32_t method_index)857 bool DexFileMethodInliner::IsStringInitMethodIndex(uint32_t method_index) {
858 ReaderMutexLock mu(Thread::Current(), lock_);
859 auto it = inline_methods_.find(method_index);
860 return (it != inline_methods_.end()) && (it->second.opcode == kInlineStringInit);
861 }
862
863 } // namespace art
864