blob: aae57ec1407f000b62cd07c3226608cf83bb2453 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 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
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +000017#include "compiler.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070018#include "compiler_internals.h"
19#include "driver/compiler_driver.h"
Dave Allison39c3bfb2014-01-28 18:33:52 -080020#include "driver/compiler_options.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070021#include "dataflow_iterator-inl.h"
22#include "leb128.h"
23#include "mirror/object.h"
Jean Christophe Beyler2469e602014-05-06 20:36:55 -070024#include "pass_driver_me_opts.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070025#include "runtime.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070026#include "base/logging.h"
buzbeea61f4952013-08-23 14:27:06 -070027#include "base/timing_logger.h"
Dave Allison39c3bfb2014-01-28 18:33:52 -080028#include "driver/compiler_options.h"
Vladimir Marko5c96e6b2013-11-14 15:34:17 +000029#include "dex/quick/dex_file_to_method_inliner_map.h"
30
Brian Carlstrom7940e442013-07-12 13:46:57 -070031namespace art {
Brian Carlstrom7940e442013-07-12 13:46:57 -070032
Ian Rogers72d32622014-05-06 16:20:11 -070033extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver* driver) {
34 CHECK(driver->GetCompilerContext() == nullptr);
Brian Carlstrom7940e442013-07-12 13:46:57 -070035}
36
Ian Rogers72d32622014-05-06 16:20:11 -070037extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver* driver) {
38 CHECK(driver->GetCompilerContext() == nullptr);
Brian Carlstrom7940e442013-07-12 13:46:57 -070039}
40
41/* Default optimizer/debug setting for the compiler. */
Brian Carlstrom7934ac22013-07-26 10:54:15 -070042static uint32_t kCompilerOptimizerDisableFlags = 0 | // Disable specific optimizations
buzbee091cc402014-03-31 10:14:40 -070043 (1 << kLoadStoreElimination) | // TODO: this pass has been broken for awhile - fix or delete.
Brian Carlstrom7934ac22013-07-26 10:54:15 -070044 // (1 << kLoadHoisting) |
45 // (1 << kSuppressLoads) |
46 // (1 << kNullCheckElimination) |
Vladimir Markobfea9c22014-01-17 17:49:33 +000047 // (1 << kClassInitCheckElimination) |
Brian Carlstrom7934ac22013-07-26 10:54:15 -070048 // (1 << kPromoteRegs) |
buzbee30adc732014-05-09 15:10:18 -070049 // (1 << kTrackLiveTemps) |
Brian Carlstrom7934ac22013-07-26 10:54:15 -070050 // (1 << kSafeOptimizations) |
51 // (1 << kBBOpt) |
52 // (1 << kMatch) |
53 // (1 << kPromoteCompilerTemps) |
buzbee17189ac2013-11-08 11:07:02 -080054 // (1 << kSuppressExceptionEdges) |
Vladimir Marko9820b7c2014-01-02 16:40:37 +000055 // (1 << kSuppressMethodInlining) |
Brian Carlstrom7940e442013-07-12 13:46:57 -070056 0;
57
58static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Brian Carlstrom7934ac22013-07-26 10:54:15 -070059 // (1 << kDebugDisplayMissingTargets) |
60 // (1 << kDebugVerbose) |
61 // (1 << kDebugDumpCFG) |
62 // (1 << kDebugSlowFieldPath) |
63 // (1 << kDebugSlowInvokePath) |
64 // (1 << kDebugSlowStringPath) |
65 // (1 << kDebugSlowestFieldPath) |
66 // (1 << kDebugSlowestStringPath) |
67 // (1 << kDebugExerciseResolveMethod) |
68 // (1 << kDebugVerifyDataflow) |
69 // (1 << kDebugShowMemoryUsage) |
70 // (1 << kDebugShowNops) |
71 // (1 << kDebugCountOpcodes) |
72 // (1 << kDebugDumpCheckStats) |
73 // (1 << kDebugDumpBitcodeFile) |
74 // (1 << kDebugVerifyBitcode) |
75 // (1 << kDebugShowSummaryMemoryUsage) |
buzbeeee17e0a2013-07-31 10:47:37 -070076 // (1 << kDebugShowFilterStats) |
buzbeea61f4952013-08-23 14:27:06 -070077 // (1 << kDebugTimings) |
buzbeeb01bf152014-05-13 15:59:07 -070078 // (1 << kDebugCodegenDump) |
Brian Carlstrom7940e442013-07-12 13:46:57 -070079 0;
80
Andreas Gampe00caeed2014-07-10 01:43:08 -070081COMPILE_ASSERT(0U == static_cast<size_t>(kNone), kNone_not_0);
82COMPILE_ASSERT(1U == static_cast<size_t>(kArm), kArm_not_1);
83COMPILE_ASSERT(2U == static_cast<size_t>(kArm64), kArm64_not_2);
84COMPILE_ASSERT(3U == static_cast<size_t>(kThumb2), kThumb2_not_3);
85COMPILE_ASSERT(4U == static_cast<size_t>(kX86), kX86_not_4);
86COMPILE_ASSERT(5U == static_cast<size_t>(kX86_64), kX86_64_not_5);
87COMPILE_ASSERT(6U == static_cast<size_t>(kMips), kMips_not_6);
88COMPILE_ASSERT(7U == static_cast<size_t>(kMips64), kMips64_not_7);
Vladimir Marko25724ef2013-11-12 15:09:20 +000089
Andreas Gampe00caeed2014-07-10 01:43:08 -070090// Additional disabled optimizations (over generally disabled) per instruction set.
91static constexpr uint32_t kDisabledOptimizationsPerISA[] = {
92 // 0 = kNone.
93 ~0U,
94 // 1 = kArm, unused (will use kThumb2).
95 ~0U,
96 // 2 = kArm64. TODO(Arm64): enable optimizations once backend is mature enough.
97 (1 << kLoadStoreElimination) |
98 (1 << kLoadHoisting) |
99 (1 << kSuppressLoads) |
100 (1 << kClassInitCheckElimination) |
101 (1 << kTrackLiveTemps) |
102 (1 << kSafeOptimizations) |
103 (1 << kBBOpt) |
104 (1 << kMatch) |
105 (1 << kPromoteCompilerTemps) |
106 (1 << kSuppressExceptionEdges) |
107 0,
108 // 3 = kThumb2.
109 0,
110 // 4 = kX86.
111 0,
112 // 5 = kX86_64.
113 (1 << kLoadStoreElimination) |
114 0,
115 // 6 = kMips.
116 (1 << kLoadStoreElimination) |
117 (1 << kLoadHoisting) |
118 (1 << kSuppressLoads) |
119 (1 << kNullCheckElimination) |
120 (1 << kPromoteRegs) |
121 (1 << kTrackLiveTemps) |
122 (1 << kSafeOptimizations) |
123 (1 << kBBOpt) |
124 (1 << kMatch) |
125 (1 << kPromoteCompilerTemps) |
126 0,
127 // 7 = kMips64.
128 ~0U
129};
130COMPILE_ASSERT(sizeof(kDisabledOptimizationsPerISA) == 8 * sizeof(uint32_t), kDisabledOpts_unexp);
Vladimir Marko25724ef2013-11-12 15:09:20 +0000131
Andreas Gampe00caeed2014-07-10 01:43:08 -0700132// Supported shorty types per instruction set. nullptr means that all are available.
133// Z : boolean
134// B : byte
135// S : short
136// C : char
137// I : int
138// J : long
139// F : float
140// D : double
141// L : reference(object, array)
142// V : void
143static const char* kSupportedTypes[] = {
144 // 0 = kNone.
145 "",
146 // 1 = kArm, unused (will use kThumb2).
147 "",
148 // 2 = kArm64.
149 nullptr,
150 // 3 = kThumb2.
151 nullptr,
152 // 4 = kX86.
153 nullptr,
154 // 5 = kX86_64.
155 nullptr,
156 // 6 = kMips.
157 nullptr,
158 // 7 = kMips64.
159 ""
160};
161COMPILE_ASSERT(sizeof(kSupportedTypes) == 8 * sizeof(char*), kSupportedTypes_unexp);
buzbeea61f4952013-08-23 14:27:06 -0700162
Andreas Gampe00caeed2014-07-10 01:43:08 -0700163static int kAllOpcodes[] = {
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100164 Instruction::NOP,
Serban Constantinescued65c5e2014-05-22 15:10:18 +0100165 Instruction::MOVE,
166 Instruction::MOVE_FROM16,
167 Instruction::MOVE_16,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800168 Instruction::MOVE_WIDE,
169 Instruction::MOVE_WIDE_FROM16,
170 Instruction::MOVE_WIDE_16,
171 Instruction::MOVE_OBJECT,
172 Instruction::MOVE_OBJECT_FROM16,
173 Instruction::MOVE_OBJECT_16,
buzbee54ee4442014-06-19 15:04:12 -0700174 Instruction::MOVE_RESULT,
175 Instruction::MOVE_RESULT_WIDE,
176 Instruction::MOVE_RESULT_OBJECT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100177 Instruction::MOVE_EXCEPTION,
178 Instruction::RETURN_VOID,
179 Instruction::RETURN,
180 Instruction::RETURN_WIDE,
Matteo Franchinfd2e2912014-06-06 10:09:56 +0100181 Instruction::RETURN_OBJECT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100182 Instruction::CONST_4,
183 Instruction::CONST_16,
184 Instruction::CONST,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800185 Instruction::CONST_HIGH16,
186 Instruction::CONST_WIDE_16,
187 Instruction::CONST_WIDE_32,
188 Instruction::CONST_WIDE,
189 Instruction::CONST_WIDE_HIGH16,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100190 Instruction::CONST_STRING,
buzbee54ee4442014-06-19 15:04:12 -0700191 Instruction::CONST_STRING_JUMBO,
192 Instruction::CONST_CLASS,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100193 Instruction::MONITOR_ENTER,
194 Instruction::MONITOR_EXIT,
buzbee54ee4442014-06-19 15:04:12 -0700195 Instruction::CHECK_CAST,
196 Instruction::INSTANCE_OF,
197 Instruction::ARRAY_LENGTH,
198 Instruction::NEW_INSTANCE,
199 Instruction::NEW_ARRAY,
200 Instruction::FILLED_NEW_ARRAY,
201 Instruction::FILLED_NEW_ARRAY_RANGE,
202 Instruction::FILL_ARRAY_DATA,
203 Instruction::THROW,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100204 Instruction::GOTO,
205 Instruction::GOTO_16,
206 Instruction::GOTO_32,
Matteo Franchin5acc8b02014-06-05 15:10:35 +0100207 Instruction::PACKED_SWITCH,
208 Instruction::SPARSE_SWITCH,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800209 Instruction::CMPL_FLOAT,
210 Instruction::CMPG_FLOAT,
211 Instruction::CMPL_DOUBLE,
212 Instruction::CMPG_DOUBLE,
213 Instruction::CMP_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100214 Instruction::IF_EQ,
215 Instruction::IF_NE,
216 Instruction::IF_LT,
217 Instruction::IF_GE,
218 Instruction::IF_GT,
219 Instruction::IF_LE,
220 Instruction::IF_EQZ,
221 Instruction::IF_NEZ,
222 Instruction::IF_LTZ,
223 Instruction::IF_GEZ,
224 Instruction::IF_GTZ,
225 Instruction::IF_LEZ,
buzbee54ee4442014-06-19 15:04:12 -0700226 Instruction::UNUSED_3E,
227 Instruction::UNUSED_3F,
228 Instruction::UNUSED_40,
229 Instruction::UNUSED_41,
230 Instruction::UNUSED_42,
231 Instruction::UNUSED_43,
232 Instruction::AGET,
233 Instruction::AGET_WIDE,
234 Instruction::AGET_OBJECT,
235 Instruction::AGET_BOOLEAN,
236 Instruction::AGET_BYTE,
237 Instruction::AGET_CHAR,
238 Instruction::AGET_SHORT,
239 Instruction::APUT,
240 Instruction::APUT_WIDE,
241 Instruction::APUT_OBJECT,
242 Instruction::APUT_BOOLEAN,
243 Instruction::APUT_BYTE,
244 Instruction::APUT_CHAR,
245 Instruction::APUT_SHORT,
246 Instruction::IGET,
247 Instruction::IGET_WIDE,
248 Instruction::IGET_OBJECT,
249 Instruction::IGET_BOOLEAN,
250 Instruction::IGET_BYTE,
251 Instruction::IGET_CHAR,
252 Instruction::IGET_SHORT,
253 Instruction::IPUT,
254 Instruction::IPUT_WIDE,
255 Instruction::IPUT_OBJECT,
256 Instruction::IPUT_BOOLEAN,
257 Instruction::IPUT_BYTE,
258 Instruction::IPUT_CHAR,
259 Instruction::IPUT_SHORT,
260 Instruction::SGET,
261 Instruction::SGET_WIDE,
262 Instruction::SGET_OBJECT,
263 Instruction::SGET_BOOLEAN,
264 Instruction::SGET_BYTE,
265 Instruction::SGET_CHAR,
266 Instruction::SGET_SHORT,
267 Instruction::SPUT,
268 Instruction::SPUT_WIDE,
269 Instruction::SPUT_OBJECT,
270 Instruction::SPUT_BOOLEAN,
271 Instruction::SPUT_BYTE,
272 Instruction::SPUT_CHAR,
273 Instruction::SPUT_SHORT,
274 Instruction::INVOKE_VIRTUAL,
275 Instruction::INVOKE_SUPER,
276 Instruction::INVOKE_DIRECT,
277 Instruction::INVOKE_STATIC,
278 Instruction::INVOKE_INTERFACE,
279 Instruction::RETURN_VOID_BARRIER,
280 Instruction::INVOKE_VIRTUAL_RANGE,
281 Instruction::INVOKE_SUPER_RANGE,
282 Instruction::INVOKE_DIRECT_RANGE,
283 Instruction::INVOKE_STATIC_RANGE,
284 Instruction::INVOKE_INTERFACE_RANGE,
285 Instruction::UNUSED_79,
286 Instruction::UNUSED_7A,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100287 Instruction::NEG_INT,
288 Instruction::NOT_INT,
buzbee54ee4442014-06-19 15:04:12 -0700289 Instruction::NEG_LONG,
290 Instruction::NOT_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100291 Instruction::NEG_FLOAT,
buzbee54ee4442014-06-19 15:04:12 -0700292 Instruction::NEG_DOUBLE,
293 Instruction::INT_TO_LONG,
294 Instruction::INT_TO_FLOAT,
295 Instruction::INT_TO_DOUBLE,
296 Instruction::LONG_TO_INT,
297 Instruction::LONG_TO_FLOAT,
298 Instruction::LONG_TO_DOUBLE,
299 Instruction::FLOAT_TO_INT,
300 Instruction::FLOAT_TO_LONG,
301 Instruction::FLOAT_TO_DOUBLE,
302 Instruction::DOUBLE_TO_INT,
303 Instruction::DOUBLE_TO_LONG,
304 Instruction::DOUBLE_TO_FLOAT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100305 Instruction::INT_TO_BYTE,
306 Instruction::INT_TO_CHAR,
307 Instruction::INT_TO_SHORT,
308 Instruction::ADD_INT,
309 Instruction::SUB_INT,
310 Instruction::MUL_INT,
311 Instruction::DIV_INT,
312 Instruction::REM_INT,
313 Instruction::AND_INT,
314 Instruction::OR_INT,
315 Instruction::XOR_INT,
316 Instruction::SHL_INT,
317 Instruction::SHR_INT,
318 Instruction::USHR_INT,
buzbee54ee4442014-06-19 15:04:12 -0700319 Instruction::ADD_LONG,
320 Instruction::SUB_LONG,
321 Instruction::MUL_LONG,
322 Instruction::DIV_LONG,
323 Instruction::REM_LONG,
324 Instruction::AND_LONG,
325 Instruction::OR_LONG,
326 Instruction::XOR_LONG,
327 Instruction::SHL_LONG,
328 Instruction::SHR_LONG,
329 Instruction::USHR_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100330 Instruction::ADD_FLOAT,
331 Instruction::SUB_FLOAT,
332 Instruction::MUL_FLOAT,
333 Instruction::DIV_FLOAT,
buzbee54ee4442014-06-19 15:04:12 -0700334 Instruction::REM_FLOAT,
335 Instruction::ADD_DOUBLE,
336 Instruction::SUB_DOUBLE,
337 Instruction::MUL_DOUBLE,
338 Instruction::DIV_DOUBLE,
339 Instruction::REM_DOUBLE,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100340 Instruction::ADD_INT_2ADDR,
341 Instruction::SUB_INT_2ADDR,
342 Instruction::MUL_INT_2ADDR,
343 Instruction::DIV_INT_2ADDR,
344 Instruction::REM_INT_2ADDR,
345 Instruction::AND_INT_2ADDR,
346 Instruction::OR_INT_2ADDR,
347 Instruction::XOR_INT_2ADDR,
348 Instruction::SHL_INT_2ADDR,
349 Instruction::SHR_INT_2ADDR,
350 Instruction::USHR_INT_2ADDR,
buzbee54ee4442014-06-19 15:04:12 -0700351 Instruction::ADD_LONG_2ADDR,
352 Instruction::SUB_LONG_2ADDR,
353 Instruction::MUL_LONG_2ADDR,
354 Instruction::DIV_LONG_2ADDR,
355 Instruction::REM_LONG_2ADDR,
356 Instruction::AND_LONG_2ADDR,
357 Instruction::OR_LONG_2ADDR,
358 Instruction::XOR_LONG_2ADDR,
359 Instruction::SHL_LONG_2ADDR,
360 Instruction::SHR_LONG_2ADDR,
361 Instruction::USHR_LONG_2ADDR,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100362 Instruction::ADD_FLOAT_2ADDR,
363 Instruction::SUB_FLOAT_2ADDR,
364 Instruction::MUL_FLOAT_2ADDR,
365 Instruction::DIV_FLOAT_2ADDR,
buzbee54ee4442014-06-19 15:04:12 -0700366 Instruction::REM_FLOAT_2ADDR,
367 Instruction::ADD_DOUBLE_2ADDR,
368 Instruction::SUB_DOUBLE_2ADDR,
369 Instruction::MUL_DOUBLE_2ADDR,
370 Instruction::DIV_DOUBLE_2ADDR,
371 Instruction::REM_DOUBLE_2ADDR,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100372 Instruction::ADD_INT_LIT16,
373 Instruction::RSUB_INT,
374 Instruction::MUL_INT_LIT16,
375 Instruction::DIV_INT_LIT16,
376 Instruction::REM_INT_LIT16,
377 Instruction::AND_INT_LIT16,
378 Instruction::OR_INT_LIT16,
379 Instruction::XOR_INT_LIT16,
380 Instruction::ADD_INT_LIT8,
381 Instruction::RSUB_INT_LIT8,
382 Instruction::MUL_INT_LIT8,
383 Instruction::DIV_INT_LIT8,
384 Instruction::REM_INT_LIT8,
385 Instruction::AND_INT_LIT8,
386 Instruction::OR_INT_LIT8,
387 Instruction::XOR_INT_LIT8,
388 Instruction::SHL_INT_LIT8,
389 Instruction::SHR_INT_LIT8,
390 Instruction::USHR_INT_LIT8,
buzbee54ee4442014-06-19 15:04:12 -0700391 Instruction::IGET_QUICK,
392 Instruction::IGET_WIDE_QUICK,
393 Instruction::IGET_OBJECT_QUICK,
394 Instruction::IPUT_QUICK,
395 Instruction::IPUT_WIDE_QUICK,
396 Instruction::IPUT_OBJECT_QUICK,
397 Instruction::INVOKE_VIRTUAL_QUICK,
398 Instruction::INVOKE_VIRTUAL_RANGE_QUICK,
399 Instruction::UNUSED_EB,
400 Instruction::UNUSED_EC,
401 Instruction::UNUSED_ED,
402 Instruction::UNUSED_EE,
403 Instruction::UNUSED_EF,
404 Instruction::UNUSED_F0,
405 Instruction::UNUSED_F1,
406 Instruction::UNUSED_F2,
407 Instruction::UNUSED_F3,
408 Instruction::UNUSED_F4,
409 Instruction::UNUSED_F5,
410 Instruction::UNUSED_F6,
411 Instruction::UNUSED_F7,
412 Instruction::UNUSED_F8,
413 Instruction::UNUSED_F9,
414 Instruction::UNUSED_FA,
415 Instruction::UNUSED_FB,
416 Instruction::UNUSED_FC,
417 Instruction::UNUSED_FD,
418 Instruction::UNUSED_FE,
419 Instruction::UNUSED_FF,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100420 // ----- ExtendedMIROpcode -----
421 kMirOpPhi,
422 kMirOpCopy,
423 kMirOpFusedCmplFloat,
424 kMirOpFusedCmpgFloat,
425 kMirOpFusedCmplDouble,
426 kMirOpFusedCmpgDouble,
427 kMirOpFusedCmpLong,
428 kMirOpNop,
429 kMirOpNullCheck,
430 kMirOpRangeCheck,
431 kMirOpDivZeroCheck,
432 kMirOpCheck,
433 kMirOpCheckPart2,
434 kMirOpSelect,
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100435};
436
Andreas Gampe00caeed2014-07-10 01:43:08 -0700437// Unsupported opcodes. nullptr can be used when everything is supported. Size of the lists is
438// recorded below.
439static const int* kUnsupportedOpcodes[] = {
440 // 0 = kNone.
441 kAllOpcodes,
442 // 1 = kArm, unused (will use kThumb2).
443 kAllOpcodes,
444 // 2 = kArm64.
445 nullptr,
446 // 3 = kThumb2.
447 nullptr,
448 // 4 = kX86.
449 nullptr,
450 // 5 = kX86_64.
451 nullptr,
452 // 6 = kMips.
453 nullptr,
454 // 7 = kMips64.
455 kAllOpcodes
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700456};
Andreas Gampe00caeed2014-07-10 01:43:08 -0700457COMPILE_ASSERT(sizeof(kUnsupportedOpcodes) == 8 * sizeof(int*), kUnsupportedOpcodes_unexp);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700458
Andreas Gampe00caeed2014-07-10 01:43:08 -0700459// Size of the arrays stored above.
460static const size_t kUnsupportedOpcodesSize[] = {
461 // 0 = kNone.
462 arraysize(kAllOpcodes),
463 // 1 = kArm, unused (will use kThumb2).
464 arraysize(kAllOpcodes),
465 // 2 = kArm64.
466 0,
467 // 3 = kThumb2.
468 0,
469 // 4 = kX86.
470 0,
471 // 5 = kX86_64.
472 0,
473 // 6 = kMips.
474 0,
475 // 7 = kMips64.
476 arraysize(kAllOpcodes),
477};
478COMPILE_ASSERT(sizeof(kUnsupportedOpcodesSize) == 8 * sizeof(size_t),
479 kUnsupportedOpcodesSize_unexp);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700480
Andreas Gampe00caeed2014-07-10 01:43:08 -0700481CompilationUnit::CompilationUnit(ArenaPool* pool)
482 : compiler_driver(nullptr),
483 class_linker(nullptr),
484 dex_file(nullptr),
485 class_loader(nullptr),
486 class_def_idx(0),
487 method_idx(0),
488 code_item(nullptr),
489 access_flags(0),
490 invoke_type(kDirect),
491 shorty(nullptr),
492 disable_opt(0),
493 enable_debug(0),
494 verbose(false),
495 compiler(nullptr),
496 instruction_set(kNone),
497 target64(false),
498 num_dalvik_registers(0),
499 insns(nullptr),
500 num_ins(0),
501 num_outs(0),
502 num_regs(0),
503 compiler_flip_match(false),
504 arena(pool),
505 arena_stack(pool),
506 mir_graph(nullptr),
507 cg(nullptr),
508 timings("QuickCompiler", true, false),
509 print_pass(false) {
510}
511
512CompilationUnit::~CompilationUnit() {
513}
514
515void CompilationUnit::StartTimingSplit(const char* label) {
516 if (compiler_driver->GetDumpPasses()) {
517 timings.StartTiming(label);
518 }
519}
520
521void CompilationUnit::NewTimingSplit(const char* label) {
522 if (compiler_driver->GetDumpPasses()) {
523 timings.EndTiming();
524 timings.StartTiming(label);
525 }
526}
527
528void CompilationUnit::EndTiming() {
529 if (compiler_driver->GetDumpPasses()) {
530 timings.EndTiming();
531 if (enable_debug & (1 << kDebugTimings)) {
532 LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file);
533 LOG(INFO) << Dumpable<TimingLogger>(timings);
534 }
535 }
536}
537
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700538static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700539 const char* supported_types = kSupportedTypes[instruction_set];
540 if (supported_types == nullptr) {
541 // Everything available.
542 return true;
543 }
544
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100545 uint32_t shorty_size = strlen(shorty);
546 CHECK_GE(shorty_size, 1u);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700547
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100548 for (uint32_t i = 0; i < shorty_size; i++) {
549 if (strchr(supported_types, shorty[i]) == nullptr) {
550 return false;
551 }
552 }
553 return true;
554};
555
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100556// Skip the method that we do not support currently.
557static bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
558 CompilationUnit& cu) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700559 // Check whether we do have limitations at all.
560 if (kSupportedTypes[cu.instruction_set] == nullptr &&
561 kUnsupportedOpcodesSize[cu.instruction_set] == 0U) {
562 return true;
563 }
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100564
Andreas Gampe00caeed2014-07-10 01:43:08 -0700565 // Check if we can compile the prototype.
566 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
567 if (!CanCompileShorty(shorty, cu.instruction_set)) {
568 VLOG(compiler) << "Unsupported shorty : " << shorty;
569 return false;
570 }
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700571
Andreas Gampe00caeed2014-07-10 01:43:08 -0700572 const int *unsupport_list = kUnsupportedOpcodes[cu.instruction_set];
573 int unsupport_list_size = kUnsupportedOpcodesSize[cu.instruction_set];
574
575 for (unsigned int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) {
576 BasicBlock* bb = cu.mir_graph->GetBasicBlock(idx);
577 if (bb == NULL) continue;
578 if (bb->block_type == kDead) continue;
579 for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
580 int opcode = mir->dalvikInsn.opcode;
581 // Check if we support the byte code.
582 if (std::find(unsupport_list, unsupport_list + unsupport_list_size,
583 opcode) != unsupport_list + unsupport_list_size) {
584 if (!cu.mir_graph->IsPseudoMirOp(opcode)) {
585 VLOG(compiler) << "Unsupported dalvik byte code : "
586 << mir->dalvikInsn.opcode;
587 } else {
588 VLOG(compiler) << "Unsupported extended MIR opcode : "
589 << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst];
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100590 }
Andreas Gampe00caeed2014-07-10 01:43:08 -0700591 return false;
592 }
593 // Check if it invokes a prototype that we cannot support.
594 if (Instruction::INVOKE_VIRTUAL == opcode ||
595 Instruction::INVOKE_SUPER == opcode ||
596 Instruction::INVOKE_DIRECT == opcode ||
597 Instruction::INVOKE_STATIC == opcode ||
598 Instruction::INVOKE_INTERFACE == opcode) {
599 uint32_t invoke_method_idx = mir->dalvikInsn.vB;
600 const char* invoke_method_shorty = dex_file.GetMethodShorty(
601 dex_file.GetMethodId(invoke_method_idx));
602 if (!CanCompileShorty(invoke_method_shorty, cu.instruction_set)) {
603 VLOG(compiler) << "Unsupported to invoke '"
604 << PrettyMethod(invoke_method_idx, dex_file)
605 << "' with shorty : " << invoke_method_shorty;
606 return false;
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100607 }
608 }
609 }
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100610 }
611 return true;
612}
613
Ian Rogers3d504072014-03-01 09:16:49 -0800614static CompiledMethod* CompileMethod(CompilerDriver& driver,
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000615 Compiler* compiler,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700616 const DexFile::CodeItem* code_item,
617 uint32_t access_flags, InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700618 uint16_t class_def_idx, uint32_t method_idx,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000619 jobject class_loader, const DexFile& dex_file,
620 void* llvm_compilation_unit) {
Calin Juravle38a09042014-06-23 14:40:31 +0100621 std::string method_name = PrettyMethod(method_idx, dex_file);
622 VLOG(compiler) << "Compiling " << method_name << "...";
buzbeeb48819d2013-09-14 16:15:25 -0700623 if (code_item->insns_size_in_code_units_ >= 0x10000) {
624 LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_
Calin Juravle38a09042014-06-23 14:40:31 +0100625 << " in " << method_name;
buzbeeb48819d2013-09-14 16:15:25 -0700626 return NULL;
627 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700628
Jeff Hao4a200f52014-04-01 14:58:49 -0700629 if (!driver.GetCompilerOptions().IsCompilationEnabled()) {
Ian Rogersa03de6d2014-03-08 23:37:07 +0000630 return nullptr;
631 }
632
Brian Carlstrom7940e442013-07-12 13:46:57 -0700633 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers3d504072014-03-01 09:16:49 -0800634 CompilationUnit cu(driver.GetArenaPool());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700635
Ian Rogers3d504072014-03-01 09:16:49 -0800636 cu.compiler_driver = &driver;
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700637 cu.class_linker = class_linker;
Ian Rogers3d504072014-03-01 09:16:49 -0800638 cu.instruction_set = driver.GetInstructionSet();
Mathieu Chartier53bee422014-04-04 16:10:05 -0700639 if (cu.instruction_set == kArm) {
640 cu.instruction_set = kThumb2;
641 }
Andreas Gampeaf13ad92014-04-11 12:07:48 -0700642 cu.target64 = Is64BitInstructionSet(cu.instruction_set);
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000643 cu.compiler = compiler;
Andreas Gampe00caeed2014-07-10 01:43:08 -0700644 // TODO: Mips64 is not yet implemented.
Mathieu Chartier53bee422014-04-04 16:10:05 -0700645 CHECK((cu.instruction_set == kThumb2) ||
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100646 (cu.instruction_set == kArm64) ||
Mathieu Chartier53bee422014-04-04 16:10:05 -0700647 (cu.instruction_set == kX86) ||
648 (cu.instruction_set == kX86_64) ||
649 (cu.instruction_set == kMips));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700650
Brian Carlstrom7940e442013-07-12 13:46:57 -0700651 /* Adjust this value accordingly once inlining is performed */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700652 cu.num_dalvik_registers = code_item->registers_size_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700653 // TODO: set this from command line
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700654 cu.compiler_flip_match = false;
655 bool use_match = !cu.compiler_method_match.empty();
656 bool match = use_match && (cu.compiler_flip_match ^
Calin Juravle38a09042014-06-23 14:40:31 +0100657 (method_name.find(cu.compiler_method_match) != std::string::npos));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700658 if (!use_match || match) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700659 cu.disable_opt = kCompilerOptimizerDisableFlags;
660 cu.enable_debug = kCompilerDebugFlags;
661 cu.verbose = VLOG_IS_ON(compiler) ||
662 (cu.enable_debug & (1 << kDebugVerbose));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700663 }
664
Mingyao Yang42d65c52014-04-18 16:49:39 -0700665 if (gVerboseMethods.size() != 0) {
666 cu.verbose = false;
667 for (size_t i = 0; i < gVerboseMethods.size(); ++i) {
Calin Juravle38a09042014-06-23 14:40:31 +0100668 if (method_name.find(gVerboseMethods[i])
Mingyao Yang42d65c52014-04-18 16:49:39 -0700669 != std::string::npos) {
670 cu.verbose = true;
671 break;
672 }
673 }
674 }
675
buzbeeb01bf152014-05-13 15:59:07 -0700676 if (cu.verbose) {
677 cu.enable_debug |= (1 << kDebugCodegenDump);
678 }
679
Brian Carlstrom7940e442013-07-12 13:46:57 -0700680 /*
681 * TODO: rework handling of optimization and debug flags. Should we split out
682 * MIR and backend flags? Need command-line setting as well.
683 */
684
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000685 compiler->InitCompilationUnit(cu);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700686
Andreas Gampe00caeed2014-07-10 01:43:08 -0700687 // Disable optimizations according to instruction set.
688 cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100689
buzbeea61f4952013-08-23 14:27:06 -0700690 cu.StartTimingSplit("BuildMIRGraph");
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700691 cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700692
Razvan A Lupusoruda7a69b2014-01-08 15:09:50 -0800693 /*
694 * After creation of the MIR graph, also create the code generator.
695 * The reason we do this is that optimizations on the MIR graph may need to get information
696 * that is only available if a CG exists.
697 */
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000698 cu.cg.reset(compiler->GetCodeGenerator(&cu, llvm_compilation_unit));
Razvan A Lupusoruda7a69b2014-01-08 15:09:50 -0800699
Brian Carlstrom7940e442013-07-12 13:46:57 -0700700 /* Gathering opcode stats? */
701 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700702 cu.mir_graph->EnableOpcodeCounting();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700703 }
704
705 /* Build the raw MIR graph */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700706 cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700707 class_loader, dex_file);
708
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100709 if (!CanCompileMethod(method_idx, dex_file, cu)) {
Calin Juravle38a09042014-06-23 14:40:31 +0100710 VLOG(compiler) << cu.instruction_set << ": Cannot compile method : " << method_name;
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100711 return nullptr;
712 }
713
buzbee1da1e2f2013-11-15 13:37:01 -0800714 cu.NewTimingSplit("MIROpt:CheckFilters");
Andreas Gampe060e6fe2014-06-19 11:34:06 -0700715 std::string skip_message;
716 if (cu.mir_graph->SkipCompilation(&skip_message)) {
717 VLOG(compiler) << cu.instruction_set << ": Skipping method : "
Calin Juravle38a09042014-06-23 14:40:31 +0100718 << method_name << " Reason = " << skip_message;
buzbee33ae5582014-06-12 14:56:32 -0700719 return nullptr;
buzbeeee17e0a2013-07-31 10:47:37 -0700720 }
721
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800722 /* Create the pass driver and launch it */
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700723 PassDriverMEOpts pass_driver(&cu);
Ian Rogers3d504072014-03-01 09:16:49 -0800724 pass_driver.Launch();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700725
Calin Juravle38a09042014-06-23 14:40:31 +0100726 /* For non-leaf methods check if we should skip compilation when the profiler is enabled. */
727 if (cu.compiler_driver->ProfilePresent()
728 && !cu.mir_graph->MethodIsLeaf()
729 && cu.mir_graph->SkipCompilationByName(method_name)) {
730 return nullptr;
731 }
732
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700733 if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
734 cu.mir_graph->DumpCheckStats();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700735 }
736
737 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700738 cu.mir_graph->ShowOpcodeStats();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700739 }
740
buzbee1da1e2f2013-11-15 13:37:01 -0800741 /* Reassociate sreg names with original Dalvik vreg names. */
742 cu.mir_graph->RemapRegLocations();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700743
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000744 /* Free Arenas from the cu.arena_stack for reuse by the cu.arena in the codegen. */
745 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
746 if (cu.arena_stack.PeakBytesAllocated() > 256 * 1024) {
747 MemStats stack_stats(cu.arena_stack.GetPeakStats());
Calin Juravle38a09042014-06-23 14:40:31 +0100748 LOG(INFO) << method_name << " " << Dumpable<MemStats>(stack_stats);
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000749 }
750 }
751 cu.arena_stack.Reset();
752
Brian Carlstrom7940e442013-07-12 13:46:57 -0700753 CompiledMethod* result = NULL;
754
buzbee8c7a02a2014-06-14 12:33:09 -0700755 if (cu.mir_graph->PuntToInterpreter()) {
Calin Juravle38a09042014-06-23 14:40:31 +0100756 VLOG(compiler) << cu.instruction_set << ": Punted method to interpreter: " << method_name;
Andreas Gampe060e6fe2014-06-19 11:34:06 -0700757 return nullptr;
buzbee8c7a02a2014-06-14 12:33:09 -0700758 }
759
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700760 cu.cg->Materialize();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700761
buzbee1da1e2f2013-11-15 13:37:01 -0800762 cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700763 result = cu.cg->GetCompiledMethod();
buzbee1da1e2f2013-11-15 13:37:01 -0800764 cu.NewTimingSplit("Cleanup");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700765
766 if (result) {
Calin Juravle38a09042014-06-23 14:40:31 +0100767 VLOG(compiler) << cu.instruction_set << ": Compiled " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700768 } else {
Calin Juravle38a09042014-06-23 14:40:31 +0100769 VLOG(compiler) << cu.instruction_set << ": Deferred " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700770 }
771
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700772 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000773 if (cu.arena.BytesAllocated() > (1 * 1024 *1024)) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000774 MemStats mem_stats(cu.arena.GetMemStats());
Calin Juravle38a09042014-06-23 14:40:31 +0100775 LOG(INFO) << method_name << " " << Dumpable<MemStats>(mem_stats);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700776 }
777 }
778
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700779 if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) {
780 LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks()
Calin Juravle38a09042014-06-23 14:40:31 +0100781 << " " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700782 }
783
buzbeea61f4952013-08-23 14:27:06 -0700784 cu.EndTiming();
Ian Rogers3d504072014-03-01 09:16:49 -0800785 driver.GetTimingsLogger()->AddLogger(cu.timings);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700786 return result;
787}
788
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000789CompiledMethod* CompileOneMethod(CompilerDriver& driver,
790 Compiler* compiler,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700791 const DexFile::CodeItem* code_item,
792 uint32_t access_flags,
793 InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700794 uint16_t class_def_idx,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700795 uint32_t method_idx,
796 jobject class_loader,
797 const DexFile& dex_file,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000798 void* compilation_unit) {
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000799 return CompileMethod(driver, compiler, code_item, access_flags, invoke_type, class_def_idx,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000800 method_idx, class_loader, dex_file, compilation_unit);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700801}
802
803} // namespace art
804
805extern "C" art::CompiledMethod*
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000806 ArtQuickCompileMethod(art::CompilerDriver& driver,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700807 const art::DexFile::CodeItem* code_item,
808 uint32_t access_flags, art::InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700809 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700810 const art::DexFile& dex_file) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700811 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use
812 // build default.
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000813 art::Compiler* compiler = driver.GetCompiler();
814 return art::CompileOneMethod(driver, compiler, code_item, access_flags, invoke_type,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700815 class_def_idx, method_idx, class_loader, dex_file,
816 NULL /* use thread llvm_info */);
817}