blob: 59b8a533ae6ff8fc16e7546ac4cc8b3f75781945 [file] [log] [blame]
Vladimir Marko5c96e6b2013-11-14 15:34:17 +00001/*
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 Markoe13717e2013-11-20 12:44:55 +000021#include "base/mutex.h"
22#include "base/macros.h"
Ian Rogersdce164a2014-01-02 17:00:38 -080023#include "safe_map.h"
Vladimir Marko5816ed42013-11-27 17:04:20 +000024#include "dex/compiler_enums.h"
25#include "dex_file.h"
Vladimir Markoe3e02602014-03-12 15:42:41 +000026#include "quick/inline_method_analyser.h"
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000027
28namespace art {
29
Vladimir Marko2bc47802014-02-10 09:43:07 +000030namespace verifier {
31class MethodVerifier;
32} // namespace verifier
33
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070034class BasicBlock;
Ian Rogersb48b9eb2014-02-28 16:20:21 -080035struct CallInfo;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070036class MIR;
Vladimir Marko9820b7c2014-01-02 16:40:37 +000037class MIRGraph;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000038class Mir2Lir;
39
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000040/**
41 * Handles inlining of methods from a particular DexFile.
42 *
43 * Intrinsics are a special case of inline methods. The DexFile indices for
44 * all the supported intrinsic methods are looked up once by the FindIntrinsics
45 * function and cached by this class for quick lookup by the method index.
46 *
47 * TODO: Detect short methods (at least getters, setters and empty functions)
48 * from the verifier and mark them for inlining. Inline these methods early
49 * during compilation to allow further optimizations. Similarly, provide
50 * additional information about intrinsics to the early phases of compilation.
51 */
52class DexFileMethodInliner {
53 public:
Vladimir Marko867a2b32013-12-10 13:01:13 +000054 DexFileMethodInliner();
55 ~DexFileMethodInliner();
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000056
57 /**
Vladimir Marko5816ed42013-11-27 17:04:20 +000058 * Analyse method code to determine if the method is a candidate for inlining.
59 * If it is, record its data for later.
60 *
Vladimir Marko84c072c2014-02-17 15:07:04 +000061 * @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 Marko5816ed42013-11-27 17:04:20 +000063 */
Vladimir Marko2bc47802014-02-10 09:43:07 +000064 bool AnalyseMethodCode(verifier::MethodVerifier* verifier)
Mathieu Chartier90443472015-07-16 20:32:27 -070065 SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +000066
67 /**
Vladimir Marko87b7c522015-04-08 10:01:01 +010068 * Check whether a particular method index corresponds to an intrinsic or special function.
69 */
Mathieu Chartier90443472015-07-16 20:32:27 -070070 InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) REQUIRES(!lock_);
Vladimir Marko87b7c522015-04-08 10:01:01 +010071
72 /**
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000073 * Check whether a particular method index corresponds to an intrinsic function.
74 */
Mathieu Chartier90443472015-07-16 20:32:27 -070075 bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) REQUIRES(!lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000076
77 /**
78 * Generate code for an intrinsic function invocation.
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000079 */
Mathieu Chartier90443472015-07-16 20:32:27 -070080 bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) REQUIRES(!lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000081
Vladimir Marko5816ed42013-11-27 17:04:20 +000082 /**
83 * Check whether a particular method index corresponds to a special function.
84 */
Mathieu Chartier90443472015-07-16 20:32:27 -070085 bool IsSpecial(uint32_t method_index) REQUIRES(!lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +000086
87 /**
88 * Generate code for a special function.
89 */
Mathieu Chartier90443472015-07-16 20:32:27 -070090 bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) REQUIRES(!lock_);
Vladimir Marko9820b7c2014-01-02 16:40:37 +000091
92 /**
93 * Try to inline an invoke.
94 */
95 bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx)
Mathieu Chartier90443472015-07-16 20:32:27 -070096 REQUIRES(!lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +000097
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000098 /**
Jeff Hao848f70a2014-01-15 13:49:50 -080099 * 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 Chartier90443472015-07-16 20:32:27 -0700102 REQUIRES(!lock_);
Jeff Hao848f70a2014-01-15 13:49:50 -0800103
104 /**
105 * Check whether a particular method index is a string init.
106 */
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 bool IsStringInitMethodIndex(uint32_t method_index) REQUIRES(!lock_);
Jeff Hao848f70a2014-01-15 13:49:50 -0800108
109 /**
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000110 * 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 Hao848f70a2014-01-15 13:49:50 -0800125 kClassCacheJavaLangByteArray,
126 kClassCacheJavaLangCharArray,
127 kClassCacheJavaLangIntArray,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000128 kClassCacheJavaLangObject,
Fred Shih4ee7a662014-07-11 09:59:27 -0700129 kClassCacheJavaLangRefReference,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000130 kClassCacheJavaLangString,
Jeff Hao848f70a2014-01-15 13:49:50 -0800131 kClassCacheJavaLangStringBuffer,
132 kClassCacheJavaLangStringBuilder,
133 kClassCacheJavaLangStringFactory,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000134 kClassCacheJavaLangDouble,
135 kClassCacheJavaLangFloat,
136 kClassCacheJavaLangInteger,
137 kClassCacheJavaLangLong,
138 kClassCacheJavaLangShort,
139 kClassCacheJavaLangMath,
140 kClassCacheJavaLangStrictMath,
141 kClassCacheJavaLangThread,
Jeff Hao848f70a2014-01-15 13:49:50 -0800142 kClassCacheJavaNioCharsetCharset,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000143 kClassCacheLibcoreIoMemory,
144 kClassCacheSunMiscUnsafe,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700145 kClassCacheJavaLangSystem,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000146 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 Constantinescu23abec92014-07-02 16:13:38 +0100156 kNameCacheReverse = kNameCacheFirst,
157 kNameCacheReverseBytes,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000158 kNameCacheDoubleToRawLongBits,
159 kNameCacheLongBitsToDouble,
160 kNameCacheFloatToRawIntBits,
161 kNameCacheIntBitsToFloat,
162 kNameCacheAbs,
163 kNameCacheMax,
164 kNameCacheMin,
Mark Mendella4f12202015-08-06 15:23:34 -0400165 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 Marko5c96e6b2013-11-14 15:34:17 +0000182 kNameCacheSqrt,
Serban Constantinescu2eba1fa2014-07-31 19:07:17 +0100183 kNameCacheCeil,
184 kNameCacheFloor,
185 kNameCacheRint,
186 kNameCacheRound,
Mathieu Chartiercd48f2d2014-09-09 13:51:09 -0700187 kNameCacheReferenceGetReferent,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000188 kNameCacheCharAt,
189 kNameCacheCompareTo,
agicsaki7da072f2015-08-12 20:30:17 -0700190 kNameCacheEquals,
Jeff Hao848f70a2014-01-15 13:49:50 -0800191 kNameCacheGetCharsNoCheck,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000192 kNameCacheIsEmpty,
Aart Bik59c94542016-01-25 14:20:58 -0800193 kNameCacheIsInfinite,
194 kNameCacheIsNaN,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000195 kNameCacheIndexOf,
196 kNameCacheLength,
Jeff Hao848f70a2014-01-15 13:49:50 -0800197 kNameCacheInit,
198 kNameCacheNewStringFromBytes,
199 kNameCacheNewStringFromChars,
200 kNameCacheNewStringFromString,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000201 kNameCacheCurrentThread,
202 kNameCachePeekByte,
203 kNameCachePeekIntNative,
204 kNameCachePeekLongNative,
205 kNameCachePeekShortNative,
206 kNameCachePokeByte,
207 kNameCachePokeIntNative,
208 kNameCachePokeLongNative,
209 kNameCachePokeShortNative,
210 kNameCacheCompareAndSwapInt,
Vladimir Marko1c282e22013-11-21 14:49:47 +0000211 kNameCacheCompareAndSwapLong,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000212 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,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700228 kNameCacheArrayCopy,
Aart Bik3f67e692016-01-15 14:35:12 -0800229 kNameCacheBitCount,
Aart Bik59c94542016-01-25 14:20:58 -0800230 kNameCacheCompare,
231 kNameCacheHighestOneBit,
232 kNameCacheLowestOneBit,
Scott Wakeling611d3392015-07-10 11:42:06 +0100233 kNameCacheNumberOfLeadingZeros,
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100234 kNameCacheNumberOfTrailingZeros,
235 kNameCacheRotateRight,
236 kNameCacheRotateLeft,
Aart Bik59c94542016-01-25 14:20:58 -0800237 kNameCacheSignum,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000238 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 Constantinescu23abec92014-07-02 16:13:38 +0100252 kProtoCacheDD_D,
Yixin Shoudbb17e32014-02-07 05:09:30 -0800253 kProtoCacheF_F,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100254 kProtoCacheFF_F,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000255 kProtoCacheD_J,
Aart Bik59c94542016-01-25 14:20:58 -0800256 kProtoCacheD_Z,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000257 kProtoCacheJ_D,
258 kProtoCacheF_I,
Aart Bik59c94542016-01-25 14:20:58 -0800259 kProtoCacheF_Z,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000260 kProtoCacheI_F,
261 kProtoCacheII_I,
262 kProtoCacheI_C,
263 kProtoCacheString_I,
264 kProtoCache_Z,
265 kProtoCache_I,
Fred Shih4ee7a662014-07-11 09:59:27 -0700266 kProtoCache_Object,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000267 kProtoCache_Thread,
268 kProtoCacheJ_B,
269 kProtoCacheJ_I,
270 kProtoCacheJ_S,
271 kProtoCacheJB_V,
272 kProtoCacheJI_V,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100273 kProtoCacheJJ_J,
Aart Bik59c94542016-01-25 14:20:58 -0800274 kProtoCacheJJ_I,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000275 kProtoCacheJJ_V,
276 kProtoCacheJS_V,
agicsaki7da072f2015-08-12 20:30:17 -0700277 kProtoCacheObject_Z,
Scott Wakeling9ee23f42015-07-23 10:44:35 +0100278 kProtoCacheJI_J,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000279 kProtoCacheObjectJII_Z,
Vladimir Marko1c282e22013-11-21 14:49:47 +0000280 kProtoCacheObjectJJJ_Z,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000281 kProtoCacheObjectJObjectObject_Z,
282 kProtoCacheObjectJ_I,
283 kProtoCacheObjectJI_V,
284 kProtoCacheObjectJ_J,
285 kProtoCacheObjectJJ_V,
286 kProtoCacheObjectJ_Object,
287 kProtoCacheObjectJObject_V,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700288 kProtoCacheCharArrayICharArrayII_V,
Nicolas Geoffrayee3cf072015-10-06 11:45:02 +0100289 kProtoCacheObjectIObjectII_V,
Jeff Hao848f70a2014-01-15 13:49:50 -0800290 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 Marko5c96e6b2013-11-14 15:34:17 +0000310 kProtoCacheLast
311 };
312
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800313 private:
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000314 /**
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 Marko5816ed42013-11-27 17:04:20 +0000347 InlineMethod intrinsic;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000348 };
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 Marko5816ed42013-11-27 17:04:20 +0000367 static const char* const kClassCacheNames[];
368 static const char* const kNameCacheNames[];
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000369 static const ProtoDef kProtoCacheDefs[];
Vladimir Marko867a2b32013-12-10 13:01:13 +0000370 static const IntrinsicDef kIntrinsicMethods[];
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000371
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 Marko867a2b32013-12-10 13:01:13 +0000384 /**
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 Chartier90443472015-07-16 20:32:27 -0700389 void FindIntrinsics(const DexFile* dex_file) REQUIRES(lock_);
Vladimir Marko867a2b32013-12-10 13:01:13 +0000390
391 friend class DexFileToMethodInlinerMap;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000392
Mathieu Chartier90443472015-07-16 20:32:27 -0700393 bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) REQUIRES(!lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +0000394
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000395 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 Rogers6a3c1fc2014-10-31 00:33:20 -0700400 MIR* move_result, const InlineMethod& method);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000401 static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700402 MIR* move_result, const InlineMethod& method);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000403
Vladimir Markoe13717e2013-11-20 12:44:55 +0000404 ReaderWriterMutex lock_;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000405 /*
406 * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
407 */
Ian Rogersdce164a2014-01-02 17:00:38 -0800408 SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000409 const DexFile* dex_file_;
Vladimir Marko867a2b32013-12-10 13:01:13 +0000410
411 DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000412};
413
414} // namespace art
415
416#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_