blob: 30a2d9081a6939e7fe61555d3da459b1b3f7f8ae [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
Vladimir Marko9820b7c2014-01-02 16:40:37 +000034struct BasicBlock;
Ian Rogersb48b9eb2014-02-28 16:20:21 -080035struct CallInfo;
Vladimir Marko9820b7c2014-01-02 16:40:37 +000036struct MIR;
37class 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)
65 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +000066
67 /**
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000068 * Check whether a particular method index corresponds to an intrinsic function.
69 */
Yixin Shou7071c8d2014-03-05 06:07:48 -050070 bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000071
72 /**
73 * Generate code for an intrinsic function invocation.
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000074 */
Vladimir Markoe13717e2013-11-20 12:44:55 +000075 bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000076
Vladimir Marko5816ed42013-11-27 17:04:20 +000077 /**
78 * Check whether a particular method index corresponds to a special function.
79 */
80 bool IsSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_);
81
82 /**
83 * Generate code for a special function.
84 */
Vladimir Marko9820b7c2014-01-02 16:40:37 +000085 bool GenSpecial(Mir2Lir* backend, uint32_t method_idx) LOCKS_EXCLUDED(lock_);
86
87 /**
88 * Try to inline an invoke.
89 */
90 bool GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke, uint32_t method_idx)
91 LOCKS_EXCLUDED(lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +000092
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000093 /**
94 * To avoid multiple lookups of a class by its descriptor, we cache its
95 * type index in the IndexCache. These are the indexes into the IndexCache
96 * class_indexes array.
97 */
98 enum ClassCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
99 kClassCacheFirst = 0,
100 kClassCacheBoolean = kClassCacheFirst,
101 kClassCacheByte,
102 kClassCacheChar,
103 kClassCacheShort,
104 kClassCacheInt,
105 kClassCacheLong,
106 kClassCacheFloat,
107 kClassCacheDouble,
108 kClassCacheVoid,
109 kClassCacheJavaLangObject,
Fred Shih4ee7a662014-07-11 09:59:27 -0700110 kClassCacheJavaLangRefReference,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000111 kClassCacheJavaLangString,
112 kClassCacheJavaLangDouble,
113 kClassCacheJavaLangFloat,
114 kClassCacheJavaLangInteger,
115 kClassCacheJavaLangLong,
116 kClassCacheJavaLangShort,
117 kClassCacheJavaLangMath,
118 kClassCacheJavaLangStrictMath,
119 kClassCacheJavaLangThread,
120 kClassCacheLibcoreIoMemory,
121 kClassCacheSunMiscUnsafe,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700122 kClassCacheJavaLangSystem,
123 kClassCacheJavaLangCharArray,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000124 kClassCacheLast
125 };
126
127 /**
128 * To avoid multiple lookups of a method name string, we cache its string
129 * index in the IndexCache. These are the indexes into the IndexCache
130 * name_indexes array.
131 */
132 enum NameCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
133 kNameCacheFirst = 0,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100134 kNameCacheReverse = kNameCacheFirst,
135 kNameCacheReverseBytes,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000136 kNameCacheDoubleToRawLongBits,
137 kNameCacheLongBitsToDouble,
138 kNameCacheFloatToRawIntBits,
139 kNameCacheIntBitsToFloat,
140 kNameCacheAbs,
141 kNameCacheMax,
142 kNameCacheMin,
143 kNameCacheSqrt,
Serban Constantinescu2eba1fa2014-07-31 19:07:17 +0100144 kNameCacheCeil,
145 kNameCacheFloor,
146 kNameCacheRint,
147 kNameCacheRound,
Mathieu Chartiercd48f2d2014-09-09 13:51:09 -0700148 kNameCacheReferenceGetReferent,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000149 kNameCacheCharAt,
150 kNameCacheCompareTo,
151 kNameCacheIsEmpty,
152 kNameCacheIndexOf,
153 kNameCacheLength,
154 kNameCacheCurrentThread,
155 kNameCachePeekByte,
156 kNameCachePeekIntNative,
157 kNameCachePeekLongNative,
158 kNameCachePeekShortNative,
159 kNameCachePokeByte,
160 kNameCachePokeIntNative,
161 kNameCachePokeLongNative,
162 kNameCachePokeShortNative,
163 kNameCacheCompareAndSwapInt,
Vladimir Marko1c282e22013-11-21 14:49:47 +0000164 kNameCacheCompareAndSwapLong,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000165 kNameCacheCompareAndSwapObject,
166 kNameCacheGetInt,
167 kNameCacheGetIntVolatile,
168 kNameCachePutInt,
169 kNameCachePutIntVolatile,
170 kNameCachePutOrderedInt,
171 kNameCacheGetLong,
172 kNameCacheGetLongVolatile,
173 kNameCachePutLong,
174 kNameCachePutLongVolatile,
175 kNameCachePutOrderedLong,
176 kNameCacheGetObject,
177 kNameCacheGetObjectVolatile,
178 kNameCachePutObject,
179 kNameCachePutObjectVolatile,
180 kNameCachePutOrderedObject,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700181 kNameCacheArrayCopy,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000182 kNameCacheLast
183 };
184
185 /**
186 * To avoid multiple lookups of a method signature, we cache its proto
187 * index in the IndexCache. These are the indexes into the IndexCache
188 * proto_indexes array.
189 */
190 enum ProtoCacheIndex : uint8_t { // unit8_t to save space, make larger if needed
191 kProtoCacheFirst = 0,
192 kProtoCacheI_I = kProtoCacheFirst,
193 kProtoCacheJ_J,
194 kProtoCacheS_S,
195 kProtoCacheD_D,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100196 kProtoCacheDD_D,
Yixin Shoudbb17e32014-02-07 05:09:30 -0800197 kProtoCacheF_F,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100198 kProtoCacheFF_F,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000199 kProtoCacheD_J,
200 kProtoCacheJ_D,
201 kProtoCacheF_I,
202 kProtoCacheI_F,
203 kProtoCacheII_I,
204 kProtoCacheI_C,
205 kProtoCacheString_I,
206 kProtoCache_Z,
207 kProtoCache_I,
Fred Shih4ee7a662014-07-11 09:59:27 -0700208 kProtoCache_Object,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000209 kProtoCache_Thread,
210 kProtoCacheJ_B,
211 kProtoCacheJ_I,
212 kProtoCacheJ_S,
213 kProtoCacheJB_V,
214 kProtoCacheJI_V,
Serban Constantinescu23abec92014-07-02 16:13:38 +0100215 kProtoCacheJJ_J,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000216 kProtoCacheJJ_V,
217 kProtoCacheJS_V,
218 kProtoCacheObjectJII_Z,
Vladimir Marko1c282e22013-11-21 14:49:47 +0000219 kProtoCacheObjectJJJ_Z,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000220 kProtoCacheObjectJObjectObject_Z,
221 kProtoCacheObjectJ_I,
222 kProtoCacheObjectJI_V,
223 kProtoCacheObjectJ_J,
224 kProtoCacheObjectJJ_V,
225 kProtoCacheObjectJ_Object,
226 kProtoCacheObjectJObject_V,
DaniilSokolov70c4f062014-06-24 17:34:00 -0700227 kProtoCacheCharArrayICharArrayII_V,
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000228 kProtoCacheLast
229 };
230
Ian Rogersb48b9eb2014-02-28 16:20:21 -0800231 private:
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000232 /**
233 * The maximum number of method parameters we support in the ProtoDef.
234 */
235 static constexpr uint32_t kProtoMaxParams = 6;
236
237 /**
238 * The method signature (proto) definition using cached class indexes.
239 * The return_type and params are used with the IndexCache to look up
240 * appropriate class indexes to be passed to DexFile::FindProtoId().
241 */
242 struct ProtoDef {
243 ClassCacheIndex return_type;
244 uint8_t param_count;
245 ClassCacheIndex params[kProtoMaxParams];
246 };
247
248 /**
249 * The method definition using cached class, name and proto indexes.
250 * The class index, method name index and proto index are used with
251 * IndexCache to look up appropriate parameters for DexFile::FindMethodId().
252 */
253 struct MethodDef {
254 ClassCacheIndex declaring_class;
255 NameCacheIndex name;
256 ProtoCacheIndex proto;
257 };
258
259 /**
260 * The definition of an intrinsic function binds the method definition
261 * to an Intrinsic.
262 */
263 struct IntrinsicDef {
264 MethodDef method_def;
Vladimir Marko5816ed42013-11-27 17:04:20 +0000265 InlineMethod intrinsic;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000266 };
267
268 /**
269 * Cache for class, method name and method signature indexes used during
270 * intrinsic function lookup to avoid multiple lookups of the same items.
271 *
272 * Many classes have multiple intrinsics and/or they are used in multiple
273 * method signatures and we want to avoid repeated lookups since they are
274 * not exactly cheap. The method names and method signatures are sometimes
275 * reused and therefore cached as well.
276 */
277 struct IndexCache {
278 IndexCache();
279
280 uint32_t class_indexes[kClassCacheLast - kClassCacheFirst];
281 uint32_t name_indexes[kNameCacheLast - kNameCacheFirst];
282 uint32_t proto_indexes[kProtoCacheLast - kProtoCacheFirst];
283 };
284
Vladimir Marko5816ed42013-11-27 17:04:20 +0000285 static const char* const kClassCacheNames[];
286 static const char* const kNameCacheNames[];
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000287 static const ProtoDef kProtoCacheDefs[];
Vladimir Marko867a2b32013-12-10 13:01:13 +0000288 static const IntrinsicDef kIntrinsicMethods[];
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000289
290 static const uint32_t kIndexNotFound = static_cast<uint32_t>(-1);
291 static const uint32_t kIndexUnresolved = static_cast<uint32_t>(-2);
292
293 static uint32_t FindClassIndex(const DexFile* dex_file, IndexCache* cache,
294 ClassCacheIndex index);
295 static uint32_t FindNameIndex(const DexFile* dex_file, IndexCache* cache,
296 NameCacheIndex index);
297 static uint32_t FindProtoIndex(const DexFile* dex_file, IndexCache* cache,
298 ProtoCacheIndex index);
299 static uint32_t FindMethodIndex(const DexFile* dex_file, IndexCache* cache,
300 const MethodDef& method_def);
301
Vladimir Marko867a2b32013-12-10 13:01:13 +0000302 /**
303 * Find all known intrinsic methods in the dex_file and cache their indices.
304 *
305 * Only DexFileToMethodInlinerMap may call this function to initialize the inliner.
306 */
Vladimir Markoe13717e2013-11-20 12:44:55 +0000307 void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_);
Vladimir Marko867a2b32013-12-10 13:01:13 +0000308
309 friend class DexFileToMethodInlinerMap;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000310
Vladimir Marko2bc47802014-02-10 09:43:07 +0000311 bool AddInlineMethod(int32_t method_idx, const InlineMethod& method) LOCKS_EXCLUDED(lock_);
Vladimir Marko5816ed42013-11-27 17:04:20 +0000312
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000313 static bool GenInlineConst(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke,
314 MIR* move_result, const InlineMethod& method);
315 static bool GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke,
316 MIR* move_result, const InlineMethod& method);
317 static bool GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke,
318 MIR* move_result, const InlineMethod& method, uint32_t method_idx);
319 static bool GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MIR* invoke,
Vladimir Markoe1fced12014-04-04 14:52:53 +0100320 MIR* move_result, const InlineMethod& method, uint32_t method_idx);
Vladimir Marko9820b7c2014-01-02 16:40:37 +0000321
Vladimir Markoe13717e2013-11-20 12:44:55 +0000322 ReaderWriterMutex lock_;
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000323 /*
324 * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
325 */
Ian Rogersdce164a2014-01-02 17:00:38 -0800326 SafeMap<uint32_t, InlineMethod> inline_methods_ GUARDED_BY(lock_);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000327 const DexFile* dex_file_;
Vladimir Marko867a2b32013-12-10 13:01:13 +0000328
329 DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
Vladimir Marko5c96e6b2013-11-14 15:34:17 +0000330};
331
332} // namespace art
333
334#endif // ART_COMPILER_DEX_QUICK_DEX_FILE_METHOD_INLINER_H_