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
30namespace art {
31
32namespace {  // anonymous namespace
33
34static 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};
112static_assert(arraysize(kIntrinsicIsStatic) == kInlineOpNop,
113              "arraysize of kIntrinsicIsStatic unexpected");
114static_assert(kIntrinsicIsStatic[kIntrinsicDoubleCvt], "DoubleCvt must be static");
115static_assert(kIntrinsicIsStatic[kIntrinsicFloatCvt], "FloatCvt must be static");
116static_assert(kIntrinsicIsStatic[kIntrinsicFloat2Int], "Float2Int must be static");
117static_assert(kIntrinsicIsStatic[kIntrinsicDouble2Long], "Double2Long must be static");
118static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsInfinite], "FloatIsInfinite must be static");
119static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsInfinite], "DoubleIsInfinite must be static");
120static_assert(kIntrinsicIsStatic[kIntrinsicFloatIsNaN], "FloatIsNaN must be static");
121static_assert(kIntrinsicIsStatic[kIntrinsicDoubleIsNaN], "DoubleIsNaN must be static");
122static_assert(kIntrinsicIsStatic[kIntrinsicReverseBits], "ReverseBits must be static");
123static_assert(kIntrinsicIsStatic[kIntrinsicReverseBytes], "ReverseBytes must be static");
124static_assert(kIntrinsicIsStatic[kIntrinsicBitCount], "BitCount must be static");
125static_assert(kIntrinsicIsStatic[kIntrinsicCompare], "Compare must be static");
126static_assert(kIntrinsicIsStatic[kIntrinsicHighestOneBit], "HighestOneBit must be static");
127static_assert(kIntrinsicIsStatic[kIntrinsicLowestOneBit], "LowestOneBit  must be static");
128static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfLeadingZeros],
129              "NumberOfLeadingZeros must be static");
130static_assert(kIntrinsicIsStatic[kIntrinsicNumberOfTrailingZeros],
131              "NumberOfTrailingZeros must be static");
132static_assert(kIntrinsicIsStatic[kIntrinsicRotateRight], "RotateRight must be static");
133static_assert(kIntrinsicIsStatic[kIntrinsicRotateLeft], "RotateLeft must be static");
134static_assert(kIntrinsicIsStatic[kIntrinsicSignum], "Signum must be static");
135static_assert(kIntrinsicIsStatic[kIntrinsicAbsInt], "AbsInt must be static");
136static_assert(kIntrinsicIsStatic[kIntrinsicAbsLong], "AbsLong must be static");
137static_assert(kIntrinsicIsStatic[kIntrinsicAbsFloat], "AbsFloat must be static");
138static_assert(kIntrinsicIsStatic[kIntrinsicAbsDouble], "AbsDouble must be static");
139static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxInt], "MinMaxInt must be static");
140static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxLong], "MinMaxLong must be static");
141static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], "MinMaxFloat must be static");
142static_assert(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], "MinMaxDouble must be static");
143static_assert(kIntrinsicIsStatic[kIntrinsicCos], "Cos must be static");
144static_assert(kIntrinsicIsStatic[kIntrinsicSin], "Sin must be static");
145static_assert(kIntrinsicIsStatic[kIntrinsicAcos], "Acos must be static");
146static_assert(kIntrinsicIsStatic[kIntrinsicAsin], "Asin must be static");
147static_assert(kIntrinsicIsStatic[kIntrinsicAtan], "Atan must be static");
148static_assert(kIntrinsicIsStatic[kIntrinsicAtan2], "Atan2 must be static");
149static_assert(kIntrinsicIsStatic[kIntrinsicCbrt], "Cbrt must be static");
150static_assert(kIntrinsicIsStatic[kIntrinsicCosh], "Cosh must be static");
151static_assert(kIntrinsicIsStatic[kIntrinsicExp], "Exp must be static");
152static_assert(kIntrinsicIsStatic[kIntrinsicExpm1], "Expm1 must be static");
153static_assert(kIntrinsicIsStatic[kIntrinsicHypot], "Hypot must be static");
154static_assert(kIntrinsicIsStatic[kIntrinsicLog], "Log must be static");
155static_assert(kIntrinsicIsStatic[kIntrinsicLog10], "Log10 must be static");
156static_assert(kIntrinsicIsStatic[kIntrinsicNextAfter], "NextAfter must be static");
157static_assert(kIntrinsicIsStatic[kIntrinsicSinh], "Sinh must be static");
158static_assert(kIntrinsicIsStatic[kIntrinsicTan], "Tan must be static");
159static_assert(kIntrinsicIsStatic[kIntrinsicTanh], "Tanh must be static");
160static_assert(kIntrinsicIsStatic[kIntrinsicSqrt], "Sqrt must be static");
161static_assert(kIntrinsicIsStatic[kIntrinsicCeil], "Ceil must be static");
162static_assert(kIntrinsicIsStatic[kIntrinsicFloor], "Floor must be static");
163static_assert(kIntrinsicIsStatic[kIntrinsicRint], "Rint must be static");
164static_assert(kIntrinsicIsStatic[kIntrinsicRoundFloat], "RoundFloat must be static");
165static_assert(kIntrinsicIsStatic[kIntrinsicRoundDouble], "RoundDouble must be static");
166static_assert(!kIntrinsicIsStatic[kIntrinsicReferenceGetReferent], "Get must not be static");
167static_assert(!kIntrinsicIsStatic[kIntrinsicCharAt], "CharAt must not be static");
168static_assert(!kIntrinsicIsStatic[kIntrinsicCompareTo], "CompareTo must not be static");
169static_assert(!kIntrinsicIsStatic[kIntrinsicEquals], "String equals must not be static");
170static_assert(!kIntrinsicIsStatic[kIntrinsicGetCharsNoCheck], "GetCharsNoCheck must not be static");
171static_assert(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], "IsEmptyOrLength must not be static");
172static_assert(!kIntrinsicIsStatic[kIntrinsicIndexOf], "IndexOf must not be static");
173static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromBytes],
174              "NewStringFromBytes must be static");
175static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromChars],
176              "NewStringFromChars must be static");
177static_assert(kIntrinsicIsStatic[kIntrinsicNewStringFromString],
178              "NewStringFromString must be static");
179static_assert(kIntrinsicIsStatic[kIntrinsicCurrentThread], "CurrentThread must be static");
180static_assert(kIntrinsicIsStatic[kIntrinsicPeek], "Peek must be static");
181static_assert(kIntrinsicIsStatic[kIntrinsicPoke], "Poke must be static");
182static_assert(!kIntrinsicIsStatic[kIntrinsicCas], "Cas must not be static");
183static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGet], "UnsafeGet must not be static");
184static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafePut], "UnsafePut must not be static");
185static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddInt], "UnsafeGetAndAddInt must not be static");
186static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndAddLong], "UnsafeGetAndAddLong must not be static");
187static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetInt], "UnsafeGetAndSetInt must not be static");
188static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetLong], "UnsafeGetAndSetLong must not be static");
189static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeGetAndSetObject], "UnsafeGetAndSetObject must not be static");
190static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeLoadFence], "UnsafeLoadFence must not be static");
191static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeStoreFence], "UnsafeStoreFence must not be static");
192static_assert(!kIntrinsicIsStatic[kIntrinsicUnsafeFullFence], "UnsafeFullFence must not be static");
193static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopyCharArray],
194              "SystemArrayCopyCharArray must be static");
195static_assert(kIntrinsicIsStatic[kIntrinsicSystemArrayCopy],
196              "SystemArrayCopy must be static");
197
198}  // anonymous namespace
199
200const uint32_t DexFileMethodInliner::kIndexUnresolved;
201const 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
234const 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
329const 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
475const 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
667DexFileMethodInliner::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
681DexFileMethodInliner::~DexFileMethodInliner() {
682}
683
684bool 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
690InlineMethodFlags 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
701bool 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
711bool 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
717uint32_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
733uint32_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
749uint32_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
787uint32_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
811DexFileMethodInliner::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
817void 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
831bool 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
846uint32_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
857bool 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