blob: 711743d69b999e02a53ba54126e39679284da781 [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) |
Vladimir Marko95a05972014-05-30 10:01:32 +010048 // (1 << kGlobalValueNumbering) |
Brian Carlstrom7934ac22013-07-26 10:54:15 -070049 // (1 << kPromoteRegs) |
buzbee30adc732014-05-09 15:10:18 -070050 // (1 << kTrackLiveTemps) |
Brian Carlstrom7934ac22013-07-26 10:54:15 -070051 // (1 << kSafeOptimizations) |
52 // (1 << kBBOpt) |
53 // (1 << kMatch) |
54 // (1 << kPromoteCompilerTemps) |
buzbee17189ac2013-11-08 11:07:02 -080055 // (1 << kSuppressExceptionEdges) |
Vladimir Marko9820b7c2014-01-02 16:40:37 +000056 // (1 << kSuppressMethodInlining) |
Brian Carlstrom7940e442013-07-12 13:46:57 -070057 0;
58
59static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes
Brian Carlstrom7934ac22013-07-26 10:54:15 -070060 // (1 << kDebugDisplayMissingTargets) |
61 // (1 << kDebugVerbose) |
62 // (1 << kDebugDumpCFG) |
63 // (1 << kDebugSlowFieldPath) |
64 // (1 << kDebugSlowInvokePath) |
65 // (1 << kDebugSlowStringPath) |
66 // (1 << kDebugSlowestFieldPath) |
67 // (1 << kDebugSlowestStringPath) |
68 // (1 << kDebugExerciseResolveMethod) |
69 // (1 << kDebugVerifyDataflow) |
70 // (1 << kDebugShowMemoryUsage) |
71 // (1 << kDebugShowNops) |
72 // (1 << kDebugCountOpcodes) |
73 // (1 << kDebugDumpCheckStats) |
74 // (1 << kDebugDumpBitcodeFile) |
75 // (1 << kDebugVerifyBitcode) |
76 // (1 << kDebugShowSummaryMemoryUsage) |
buzbeeee17e0a2013-07-31 10:47:37 -070077 // (1 << kDebugShowFilterStats) |
buzbeea61f4952013-08-23 14:27:06 -070078 // (1 << kDebugTimings) |
buzbeeb01bf152014-05-13 15:59:07 -070079 // (1 << kDebugCodegenDump) |
Brian Carlstrom7940e442013-07-12 13:46:57 -070080 0;
81
Andreas Gampe00caeed2014-07-10 01:43:08 -070082COMPILE_ASSERT(0U == static_cast<size_t>(kNone), kNone_not_0);
83COMPILE_ASSERT(1U == static_cast<size_t>(kArm), kArm_not_1);
84COMPILE_ASSERT(2U == static_cast<size_t>(kArm64), kArm64_not_2);
85COMPILE_ASSERT(3U == static_cast<size_t>(kThumb2), kThumb2_not_3);
86COMPILE_ASSERT(4U == static_cast<size_t>(kX86), kX86_not_4);
87COMPILE_ASSERT(5U == static_cast<size_t>(kX86_64), kX86_64_not_5);
88COMPILE_ASSERT(6U == static_cast<size_t>(kMips), kMips_not_6);
89COMPILE_ASSERT(7U == static_cast<size_t>(kMips64), kMips64_not_7);
Vladimir Marko25724ef2013-11-12 15:09:20 +000090
Andreas Gampe00caeed2014-07-10 01:43:08 -070091// Additional disabled optimizations (over generally disabled) per instruction set.
92static constexpr uint32_t kDisabledOptimizationsPerISA[] = {
93 // 0 = kNone.
94 ~0U,
95 // 1 = kArm, unused (will use kThumb2).
96 ~0U,
97 // 2 = kArm64. TODO(Arm64): enable optimizations once backend is mature enough.
98 (1 << kLoadStoreElimination) |
99 (1 << kLoadHoisting) |
Andreas Gampe00caeed2014-07-10 01:43:08 -0700100 0,
101 // 3 = kThumb2.
102 0,
103 // 4 = kX86.
104 0,
105 // 5 = kX86_64.
106 (1 << kLoadStoreElimination) |
107 0,
108 // 6 = kMips.
109 (1 << kLoadStoreElimination) |
110 (1 << kLoadHoisting) |
111 (1 << kSuppressLoads) |
112 (1 << kNullCheckElimination) |
113 (1 << kPromoteRegs) |
114 (1 << kTrackLiveTemps) |
115 (1 << kSafeOptimizations) |
116 (1 << kBBOpt) |
117 (1 << kMatch) |
118 (1 << kPromoteCompilerTemps) |
119 0,
120 // 7 = kMips64.
121 ~0U
122};
123COMPILE_ASSERT(sizeof(kDisabledOptimizationsPerISA) == 8 * sizeof(uint32_t), kDisabledOpts_unexp);
Vladimir Marko25724ef2013-11-12 15:09:20 +0000124
Andreas Gampe00caeed2014-07-10 01:43:08 -0700125// Supported shorty types per instruction set. nullptr means that all are available.
126// Z : boolean
127// B : byte
128// S : short
129// C : char
130// I : int
131// J : long
132// F : float
133// D : double
134// L : reference(object, array)
135// V : void
136static const char* kSupportedTypes[] = {
137 // 0 = kNone.
138 "",
139 // 1 = kArm, unused (will use kThumb2).
140 "",
141 // 2 = kArm64.
142 nullptr,
143 // 3 = kThumb2.
144 nullptr,
145 // 4 = kX86.
146 nullptr,
147 // 5 = kX86_64.
148 nullptr,
149 // 6 = kMips.
150 nullptr,
151 // 7 = kMips64.
152 ""
153};
154COMPILE_ASSERT(sizeof(kSupportedTypes) == 8 * sizeof(char*), kSupportedTypes_unexp);
buzbeea61f4952013-08-23 14:27:06 -0700155
Andreas Gampe00caeed2014-07-10 01:43:08 -0700156static int kAllOpcodes[] = {
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100157 Instruction::NOP,
Serban Constantinescued65c5e2014-05-22 15:10:18 +0100158 Instruction::MOVE,
159 Instruction::MOVE_FROM16,
160 Instruction::MOVE_16,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800161 Instruction::MOVE_WIDE,
162 Instruction::MOVE_WIDE_FROM16,
163 Instruction::MOVE_WIDE_16,
164 Instruction::MOVE_OBJECT,
165 Instruction::MOVE_OBJECT_FROM16,
166 Instruction::MOVE_OBJECT_16,
buzbee54ee4442014-06-19 15:04:12 -0700167 Instruction::MOVE_RESULT,
168 Instruction::MOVE_RESULT_WIDE,
169 Instruction::MOVE_RESULT_OBJECT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100170 Instruction::MOVE_EXCEPTION,
171 Instruction::RETURN_VOID,
172 Instruction::RETURN,
173 Instruction::RETURN_WIDE,
Matteo Franchinfd2e2912014-06-06 10:09:56 +0100174 Instruction::RETURN_OBJECT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100175 Instruction::CONST_4,
176 Instruction::CONST_16,
177 Instruction::CONST,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800178 Instruction::CONST_HIGH16,
179 Instruction::CONST_WIDE_16,
180 Instruction::CONST_WIDE_32,
181 Instruction::CONST_WIDE,
182 Instruction::CONST_WIDE_HIGH16,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100183 Instruction::CONST_STRING,
buzbee54ee4442014-06-19 15:04:12 -0700184 Instruction::CONST_STRING_JUMBO,
185 Instruction::CONST_CLASS,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100186 Instruction::MONITOR_ENTER,
187 Instruction::MONITOR_EXIT,
buzbee54ee4442014-06-19 15:04:12 -0700188 Instruction::CHECK_CAST,
189 Instruction::INSTANCE_OF,
190 Instruction::ARRAY_LENGTH,
191 Instruction::NEW_INSTANCE,
192 Instruction::NEW_ARRAY,
193 Instruction::FILLED_NEW_ARRAY,
194 Instruction::FILLED_NEW_ARRAY_RANGE,
195 Instruction::FILL_ARRAY_DATA,
196 Instruction::THROW,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100197 Instruction::GOTO,
198 Instruction::GOTO_16,
199 Instruction::GOTO_32,
Matteo Franchin5acc8b02014-06-05 15:10:35 +0100200 Instruction::PACKED_SWITCH,
201 Instruction::SPARSE_SWITCH,
Zheng Xue2eb29e2014-06-12 10:22:33 +0800202 Instruction::CMPL_FLOAT,
203 Instruction::CMPG_FLOAT,
204 Instruction::CMPL_DOUBLE,
205 Instruction::CMPG_DOUBLE,
206 Instruction::CMP_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100207 Instruction::IF_EQ,
208 Instruction::IF_NE,
209 Instruction::IF_LT,
210 Instruction::IF_GE,
211 Instruction::IF_GT,
212 Instruction::IF_LE,
213 Instruction::IF_EQZ,
214 Instruction::IF_NEZ,
215 Instruction::IF_LTZ,
216 Instruction::IF_GEZ,
217 Instruction::IF_GTZ,
218 Instruction::IF_LEZ,
buzbee54ee4442014-06-19 15:04:12 -0700219 Instruction::UNUSED_3E,
220 Instruction::UNUSED_3F,
221 Instruction::UNUSED_40,
222 Instruction::UNUSED_41,
223 Instruction::UNUSED_42,
224 Instruction::UNUSED_43,
225 Instruction::AGET,
226 Instruction::AGET_WIDE,
227 Instruction::AGET_OBJECT,
228 Instruction::AGET_BOOLEAN,
229 Instruction::AGET_BYTE,
230 Instruction::AGET_CHAR,
231 Instruction::AGET_SHORT,
232 Instruction::APUT,
233 Instruction::APUT_WIDE,
234 Instruction::APUT_OBJECT,
235 Instruction::APUT_BOOLEAN,
236 Instruction::APUT_BYTE,
237 Instruction::APUT_CHAR,
238 Instruction::APUT_SHORT,
239 Instruction::IGET,
240 Instruction::IGET_WIDE,
241 Instruction::IGET_OBJECT,
242 Instruction::IGET_BOOLEAN,
243 Instruction::IGET_BYTE,
244 Instruction::IGET_CHAR,
245 Instruction::IGET_SHORT,
246 Instruction::IPUT,
247 Instruction::IPUT_WIDE,
248 Instruction::IPUT_OBJECT,
249 Instruction::IPUT_BOOLEAN,
250 Instruction::IPUT_BYTE,
251 Instruction::IPUT_CHAR,
252 Instruction::IPUT_SHORT,
253 Instruction::SGET,
254 Instruction::SGET_WIDE,
255 Instruction::SGET_OBJECT,
256 Instruction::SGET_BOOLEAN,
257 Instruction::SGET_BYTE,
258 Instruction::SGET_CHAR,
259 Instruction::SGET_SHORT,
260 Instruction::SPUT,
261 Instruction::SPUT_WIDE,
262 Instruction::SPUT_OBJECT,
263 Instruction::SPUT_BOOLEAN,
264 Instruction::SPUT_BYTE,
265 Instruction::SPUT_CHAR,
266 Instruction::SPUT_SHORT,
267 Instruction::INVOKE_VIRTUAL,
268 Instruction::INVOKE_SUPER,
269 Instruction::INVOKE_DIRECT,
270 Instruction::INVOKE_STATIC,
271 Instruction::INVOKE_INTERFACE,
272 Instruction::RETURN_VOID_BARRIER,
273 Instruction::INVOKE_VIRTUAL_RANGE,
274 Instruction::INVOKE_SUPER_RANGE,
275 Instruction::INVOKE_DIRECT_RANGE,
276 Instruction::INVOKE_STATIC_RANGE,
277 Instruction::INVOKE_INTERFACE_RANGE,
278 Instruction::UNUSED_79,
279 Instruction::UNUSED_7A,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100280 Instruction::NEG_INT,
281 Instruction::NOT_INT,
buzbee54ee4442014-06-19 15:04:12 -0700282 Instruction::NEG_LONG,
283 Instruction::NOT_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100284 Instruction::NEG_FLOAT,
buzbee54ee4442014-06-19 15:04:12 -0700285 Instruction::NEG_DOUBLE,
286 Instruction::INT_TO_LONG,
287 Instruction::INT_TO_FLOAT,
288 Instruction::INT_TO_DOUBLE,
289 Instruction::LONG_TO_INT,
290 Instruction::LONG_TO_FLOAT,
291 Instruction::LONG_TO_DOUBLE,
292 Instruction::FLOAT_TO_INT,
293 Instruction::FLOAT_TO_LONG,
294 Instruction::FLOAT_TO_DOUBLE,
295 Instruction::DOUBLE_TO_INT,
296 Instruction::DOUBLE_TO_LONG,
297 Instruction::DOUBLE_TO_FLOAT,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100298 Instruction::INT_TO_BYTE,
299 Instruction::INT_TO_CHAR,
300 Instruction::INT_TO_SHORT,
301 Instruction::ADD_INT,
302 Instruction::SUB_INT,
303 Instruction::MUL_INT,
304 Instruction::DIV_INT,
305 Instruction::REM_INT,
306 Instruction::AND_INT,
307 Instruction::OR_INT,
308 Instruction::XOR_INT,
309 Instruction::SHL_INT,
310 Instruction::SHR_INT,
311 Instruction::USHR_INT,
buzbee54ee4442014-06-19 15:04:12 -0700312 Instruction::ADD_LONG,
313 Instruction::SUB_LONG,
314 Instruction::MUL_LONG,
315 Instruction::DIV_LONG,
316 Instruction::REM_LONG,
317 Instruction::AND_LONG,
318 Instruction::OR_LONG,
319 Instruction::XOR_LONG,
320 Instruction::SHL_LONG,
321 Instruction::SHR_LONG,
322 Instruction::USHR_LONG,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100323 Instruction::ADD_FLOAT,
324 Instruction::SUB_FLOAT,
325 Instruction::MUL_FLOAT,
326 Instruction::DIV_FLOAT,
buzbee54ee4442014-06-19 15:04:12 -0700327 Instruction::REM_FLOAT,
328 Instruction::ADD_DOUBLE,
329 Instruction::SUB_DOUBLE,
330 Instruction::MUL_DOUBLE,
331 Instruction::DIV_DOUBLE,
332 Instruction::REM_DOUBLE,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100333 Instruction::ADD_INT_2ADDR,
334 Instruction::SUB_INT_2ADDR,
335 Instruction::MUL_INT_2ADDR,
336 Instruction::DIV_INT_2ADDR,
337 Instruction::REM_INT_2ADDR,
338 Instruction::AND_INT_2ADDR,
339 Instruction::OR_INT_2ADDR,
340 Instruction::XOR_INT_2ADDR,
341 Instruction::SHL_INT_2ADDR,
342 Instruction::SHR_INT_2ADDR,
343 Instruction::USHR_INT_2ADDR,
buzbee54ee4442014-06-19 15:04:12 -0700344 Instruction::ADD_LONG_2ADDR,
345 Instruction::SUB_LONG_2ADDR,
346 Instruction::MUL_LONG_2ADDR,
347 Instruction::DIV_LONG_2ADDR,
348 Instruction::REM_LONG_2ADDR,
349 Instruction::AND_LONG_2ADDR,
350 Instruction::OR_LONG_2ADDR,
351 Instruction::XOR_LONG_2ADDR,
352 Instruction::SHL_LONG_2ADDR,
353 Instruction::SHR_LONG_2ADDR,
354 Instruction::USHR_LONG_2ADDR,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100355 Instruction::ADD_FLOAT_2ADDR,
356 Instruction::SUB_FLOAT_2ADDR,
357 Instruction::MUL_FLOAT_2ADDR,
358 Instruction::DIV_FLOAT_2ADDR,
buzbee54ee4442014-06-19 15:04:12 -0700359 Instruction::REM_FLOAT_2ADDR,
360 Instruction::ADD_DOUBLE_2ADDR,
361 Instruction::SUB_DOUBLE_2ADDR,
362 Instruction::MUL_DOUBLE_2ADDR,
363 Instruction::DIV_DOUBLE_2ADDR,
364 Instruction::REM_DOUBLE_2ADDR,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100365 Instruction::ADD_INT_LIT16,
366 Instruction::RSUB_INT,
367 Instruction::MUL_INT_LIT16,
368 Instruction::DIV_INT_LIT16,
369 Instruction::REM_INT_LIT16,
370 Instruction::AND_INT_LIT16,
371 Instruction::OR_INT_LIT16,
372 Instruction::XOR_INT_LIT16,
373 Instruction::ADD_INT_LIT8,
374 Instruction::RSUB_INT_LIT8,
375 Instruction::MUL_INT_LIT8,
376 Instruction::DIV_INT_LIT8,
377 Instruction::REM_INT_LIT8,
378 Instruction::AND_INT_LIT8,
379 Instruction::OR_INT_LIT8,
380 Instruction::XOR_INT_LIT8,
381 Instruction::SHL_INT_LIT8,
382 Instruction::SHR_INT_LIT8,
383 Instruction::USHR_INT_LIT8,
buzbee54ee4442014-06-19 15:04:12 -0700384 Instruction::IGET_QUICK,
385 Instruction::IGET_WIDE_QUICK,
386 Instruction::IGET_OBJECT_QUICK,
387 Instruction::IPUT_QUICK,
388 Instruction::IPUT_WIDE_QUICK,
389 Instruction::IPUT_OBJECT_QUICK,
390 Instruction::INVOKE_VIRTUAL_QUICK,
391 Instruction::INVOKE_VIRTUAL_RANGE_QUICK,
392 Instruction::UNUSED_EB,
393 Instruction::UNUSED_EC,
394 Instruction::UNUSED_ED,
395 Instruction::UNUSED_EE,
396 Instruction::UNUSED_EF,
397 Instruction::UNUSED_F0,
398 Instruction::UNUSED_F1,
399 Instruction::UNUSED_F2,
400 Instruction::UNUSED_F3,
401 Instruction::UNUSED_F4,
402 Instruction::UNUSED_F5,
403 Instruction::UNUSED_F6,
404 Instruction::UNUSED_F7,
405 Instruction::UNUSED_F8,
406 Instruction::UNUSED_F9,
407 Instruction::UNUSED_FA,
408 Instruction::UNUSED_FB,
409 Instruction::UNUSED_FC,
410 Instruction::UNUSED_FD,
411 Instruction::UNUSED_FE,
412 Instruction::UNUSED_FF,
Matteo Franchinec3f3d12014-05-29 14:24:10 +0100413 // ----- ExtendedMIROpcode -----
414 kMirOpPhi,
415 kMirOpCopy,
416 kMirOpFusedCmplFloat,
417 kMirOpFusedCmpgFloat,
418 kMirOpFusedCmplDouble,
419 kMirOpFusedCmpgDouble,
420 kMirOpFusedCmpLong,
421 kMirOpNop,
422 kMirOpNullCheck,
423 kMirOpRangeCheck,
424 kMirOpDivZeroCheck,
425 kMirOpCheck,
426 kMirOpCheckPart2,
427 kMirOpSelect,
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100428};
429
Andreas Gampe00caeed2014-07-10 01:43:08 -0700430// Unsupported opcodes. nullptr can be used when everything is supported. Size of the lists is
431// recorded below.
432static const int* kUnsupportedOpcodes[] = {
433 // 0 = kNone.
434 kAllOpcodes,
435 // 1 = kArm, unused (will use kThumb2).
436 kAllOpcodes,
437 // 2 = kArm64.
438 nullptr,
439 // 3 = kThumb2.
440 nullptr,
441 // 4 = kX86.
442 nullptr,
443 // 5 = kX86_64.
444 nullptr,
445 // 6 = kMips.
446 nullptr,
447 // 7 = kMips64.
448 kAllOpcodes
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700449};
Andreas Gampe00caeed2014-07-10 01:43:08 -0700450COMPILE_ASSERT(sizeof(kUnsupportedOpcodes) == 8 * sizeof(int*), kUnsupportedOpcodes_unexp);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700451
Andreas Gampe00caeed2014-07-10 01:43:08 -0700452// Size of the arrays stored above.
453static const size_t kUnsupportedOpcodesSize[] = {
454 // 0 = kNone.
455 arraysize(kAllOpcodes),
456 // 1 = kArm, unused (will use kThumb2).
457 arraysize(kAllOpcodes),
458 // 2 = kArm64.
459 0,
460 // 3 = kThumb2.
461 0,
462 // 4 = kX86.
463 0,
464 // 5 = kX86_64.
465 0,
466 // 6 = kMips.
467 0,
468 // 7 = kMips64.
469 arraysize(kAllOpcodes),
470};
471COMPILE_ASSERT(sizeof(kUnsupportedOpcodesSize) == 8 * sizeof(size_t),
472 kUnsupportedOpcodesSize_unexp);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700473
Andreas Gampe00caeed2014-07-10 01:43:08 -0700474CompilationUnit::CompilationUnit(ArenaPool* pool)
475 : compiler_driver(nullptr),
476 class_linker(nullptr),
477 dex_file(nullptr),
478 class_loader(nullptr),
479 class_def_idx(0),
480 method_idx(0),
481 code_item(nullptr),
482 access_flags(0),
483 invoke_type(kDirect),
484 shorty(nullptr),
485 disable_opt(0),
486 enable_debug(0),
487 verbose(false),
488 compiler(nullptr),
489 instruction_set(kNone),
490 target64(false),
491 num_dalvik_registers(0),
492 insns(nullptr),
493 num_ins(0),
494 num_outs(0),
495 num_regs(0),
496 compiler_flip_match(false),
497 arena(pool),
498 arena_stack(pool),
499 mir_graph(nullptr),
500 cg(nullptr),
501 timings("QuickCompiler", true, false),
502 print_pass(false) {
503}
504
505CompilationUnit::~CompilationUnit() {
506}
507
508void CompilationUnit::StartTimingSplit(const char* label) {
509 if (compiler_driver->GetDumpPasses()) {
510 timings.StartTiming(label);
511 }
512}
513
514void CompilationUnit::NewTimingSplit(const char* label) {
515 if (compiler_driver->GetDumpPasses()) {
516 timings.EndTiming();
517 timings.StartTiming(label);
518 }
519}
520
521void CompilationUnit::EndTiming() {
522 if (compiler_driver->GetDumpPasses()) {
523 timings.EndTiming();
524 if (enable_debug & (1 << kDebugTimings)) {
525 LOG(INFO) << "TIMINGS " << PrettyMethod(method_idx, *dex_file);
526 LOG(INFO) << Dumpable<TimingLogger>(timings);
527 }
528 }
529}
530
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700531static bool CanCompileShorty(const char* shorty, InstructionSet instruction_set) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700532 const char* supported_types = kSupportedTypes[instruction_set];
533 if (supported_types == nullptr) {
534 // Everything available.
535 return true;
536 }
537
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100538 uint32_t shorty_size = strlen(shorty);
539 CHECK_GE(shorty_size, 1u);
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700540
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100541 for (uint32_t i = 0; i < shorty_size; i++) {
542 if (strchr(supported_types, shorty[i]) == nullptr) {
543 return false;
544 }
545 }
546 return true;
547};
548
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100549// Skip the method that we do not support currently.
550static bool CanCompileMethod(uint32_t method_idx, const DexFile& dex_file,
551 CompilationUnit& cu) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700552 // Check whether we do have limitations at all.
553 if (kSupportedTypes[cu.instruction_set] == nullptr &&
554 kUnsupportedOpcodesSize[cu.instruction_set] == 0U) {
555 return true;
556 }
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100557
Andreas Gampe00caeed2014-07-10 01:43:08 -0700558 // Check if we can compile the prototype.
559 const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
560 if (!CanCompileShorty(shorty, cu.instruction_set)) {
561 VLOG(compiler) << "Unsupported shorty : " << shorty;
562 return false;
563 }
Vladimir Kostyukov56784552014-05-13 12:12:00 +0700564
Andreas Gampe00caeed2014-07-10 01:43:08 -0700565 const int *unsupport_list = kUnsupportedOpcodes[cu.instruction_set];
566 int unsupport_list_size = kUnsupportedOpcodesSize[cu.instruction_set];
567
568 for (unsigned int idx = 0; idx < cu.mir_graph->GetNumBlocks(); idx++) {
569 BasicBlock* bb = cu.mir_graph->GetBasicBlock(idx);
570 if (bb == NULL) continue;
571 if (bb->block_type == kDead) continue;
572 for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
573 int opcode = mir->dalvikInsn.opcode;
574 // Check if we support the byte code.
575 if (std::find(unsupport_list, unsupport_list + unsupport_list_size,
576 opcode) != unsupport_list + unsupport_list_size) {
Jean Christophe Beyler2ab40eb2014-06-02 09:03:14 -0700577 if (!MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700578 VLOG(compiler) << "Unsupported dalvik byte code : "
579 << mir->dalvikInsn.opcode;
580 } else {
581 VLOG(compiler) << "Unsupported extended MIR opcode : "
582 << MIRGraph::extended_mir_op_names_[opcode - kMirOpFirst];
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100583 }
Andreas Gampe00caeed2014-07-10 01:43:08 -0700584 return false;
585 }
586 // Check if it invokes a prototype that we cannot support.
587 if (Instruction::INVOKE_VIRTUAL == opcode ||
588 Instruction::INVOKE_SUPER == opcode ||
589 Instruction::INVOKE_DIRECT == opcode ||
590 Instruction::INVOKE_STATIC == opcode ||
591 Instruction::INVOKE_INTERFACE == opcode) {
592 uint32_t invoke_method_idx = mir->dalvikInsn.vB;
593 const char* invoke_method_shorty = dex_file.GetMethodShorty(
594 dex_file.GetMethodId(invoke_method_idx));
595 if (!CanCompileShorty(invoke_method_shorty, cu.instruction_set)) {
596 VLOG(compiler) << "Unsupported to invoke '"
597 << PrettyMethod(invoke_method_idx, dex_file)
598 << "' with shorty : " << invoke_method_shorty;
599 return false;
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100600 }
601 }
602 }
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100603 }
604 return true;
605}
606
Ian Rogers3d504072014-03-01 09:16:49 -0800607static CompiledMethod* CompileMethod(CompilerDriver& driver,
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000608 Compiler* compiler,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700609 const DexFile::CodeItem* code_item,
610 uint32_t access_flags, InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700611 uint16_t class_def_idx, uint32_t method_idx,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000612 jobject class_loader, const DexFile& dex_file,
613 void* llvm_compilation_unit) {
Calin Juravle38a09042014-06-23 14:40:31 +0100614 std::string method_name = PrettyMethod(method_idx, dex_file);
615 VLOG(compiler) << "Compiling " << method_name << "...";
buzbeeb48819d2013-09-14 16:15:25 -0700616 if (code_item->insns_size_in_code_units_ >= 0x10000) {
617 LOG(INFO) << "Method size exceeds compiler limits: " << code_item->insns_size_in_code_units_
Calin Juravle38a09042014-06-23 14:40:31 +0100618 << " in " << method_name;
buzbeeb48819d2013-09-14 16:15:25 -0700619 return NULL;
620 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700621
Jeff Hao4a200f52014-04-01 14:58:49 -0700622 if (!driver.GetCompilerOptions().IsCompilationEnabled()) {
Ian Rogersa03de6d2014-03-08 23:37:07 +0000623 return nullptr;
624 }
625
Brian Carlstrom7940e442013-07-12 13:46:57 -0700626 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers3d504072014-03-01 09:16:49 -0800627 CompilationUnit cu(driver.GetArenaPool());
Brian Carlstrom7940e442013-07-12 13:46:57 -0700628
Ian Rogers3d504072014-03-01 09:16:49 -0800629 cu.compiler_driver = &driver;
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700630 cu.class_linker = class_linker;
Ian Rogers3d504072014-03-01 09:16:49 -0800631 cu.instruction_set = driver.GetInstructionSet();
Mathieu Chartier53bee422014-04-04 16:10:05 -0700632 if (cu.instruction_set == kArm) {
633 cu.instruction_set = kThumb2;
634 }
Andreas Gampeaf13ad92014-04-11 12:07:48 -0700635 cu.target64 = Is64BitInstructionSet(cu.instruction_set);
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000636 cu.compiler = compiler;
Andreas Gampe00caeed2014-07-10 01:43:08 -0700637 // TODO: Mips64 is not yet implemented.
Mathieu Chartier53bee422014-04-04 16:10:05 -0700638 CHECK((cu.instruction_set == kThumb2) ||
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100639 (cu.instruction_set == kArm64) ||
Mathieu Chartier53bee422014-04-04 16:10:05 -0700640 (cu.instruction_set == kX86) ||
641 (cu.instruction_set == kX86_64) ||
642 (cu.instruction_set == kMips));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700643
Brian Carlstrom7940e442013-07-12 13:46:57 -0700644 /* Adjust this value accordingly once inlining is performed */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700645 cu.num_dalvik_registers = code_item->registers_size_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700646 // TODO: set this from command line
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700647 cu.compiler_flip_match = false;
648 bool use_match = !cu.compiler_method_match.empty();
649 bool match = use_match && (cu.compiler_flip_match ^
Calin Juravle38a09042014-06-23 14:40:31 +0100650 (method_name.find(cu.compiler_method_match) != std::string::npos));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700651 if (!use_match || match) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700652 cu.disable_opt = kCompilerOptimizerDisableFlags;
653 cu.enable_debug = kCompilerDebugFlags;
654 cu.verbose = VLOG_IS_ON(compiler) ||
655 (cu.enable_debug & (1 << kDebugVerbose));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700656 }
657
Mingyao Yang42d65c52014-04-18 16:49:39 -0700658 if (gVerboseMethods.size() != 0) {
659 cu.verbose = false;
660 for (size_t i = 0; i < gVerboseMethods.size(); ++i) {
Calin Juravle38a09042014-06-23 14:40:31 +0100661 if (method_name.find(gVerboseMethods[i])
Mingyao Yang42d65c52014-04-18 16:49:39 -0700662 != std::string::npos) {
663 cu.verbose = true;
664 break;
665 }
666 }
667 }
668
buzbeeb01bf152014-05-13 15:59:07 -0700669 if (cu.verbose) {
670 cu.enable_debug |= (1 << kDebugCodegenDump);
671 }
672
Brian Carlstrom7940e442013-07-12 13:46:57 -0700673 /*
674 * TODO: rework handling of optimization and debug flags. Should we split out
675 * MIR and backend flags? Need command-line setting as well.
676 */
677
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000678 compiler->InitCompilationUnit(cu);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700679
Andreas Gampe00caeed2014-07-10 01:43:08 -0700680 // Disable optimizations according to instruction set.
681 cu.disable_opt |= kDisabledOptimizationsPerISA[cu.instruction_set];
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100682
buzbeea61f4952013-08-23 14:27:06 -0700683 cu.StartTimingSplit("BuildMIRGraph");
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700684 cu.mir_graph.reset(new MIRGraph(&cu, &cu.arena));
Brian Carlstrom7940e442013-07-12 13:46:57 -0700685
Razvan A Lupusoruda7a69b2014-01-08 15:09:50 -0800686 /*
687 * After creation of the MIR graph, also create the code generator.
688 * The reason we do this is that optimizations on the MIR graph may need to get information
689 * that is only available if a CG exists.
690 */
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000691 cu.cg.reset(compiler->GetCodeGenerator(&cu, llvm_compilation_unit));
Razvan A Lupusoruda7a69b2014-01-08 15:09:50 -0800692
Brian Carlstrom7940e442013-07-12 13:46:57 -0700693 /* Gathering opcode stats? */
694 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700695 cu.mir_graph->EnableOpcodeCounting();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700696 }
697
698 /* Build the raw MIR graph */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700699 cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700700 class_loader, dex_file);
701
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100702 if (!CanCompileMethod(method_idx, dex_file, cu)) {
Calin Juravle38a09042014-06-23 14:40:31 +0100703 VLOG(compiler) << cu.instruction_set << ": Cannot compile method : " << method_name;
Zheng Xu9e06c8c2014-05-06 18:06:07 +0100704 return nullptr;
705 }
706
buzbee1da1e2f2013-11-15 13:37:01 -0800707 cu.NewTimingSplit("MIROpt:CheckFilters");
Andreas Gampe060e6fe2014-06-19 11:34:06 -0700708 std::string skip_message;
709 if (cu.mir_graph->SkipCompilation(&skip_message)) {
710 VLOG(compiler) << cu.instruction_set << ": Skipping method : "
Calin Juravle38a09042014-06-23 14:40:31 +0100711 << method_name << " Reason = " << skip_message;
buzbee33ae5582014-06-12 14:56:32 -0700712 return nullptr;
buzbeeee17e0a2013-07-31 10:47:37 -0700713 }
714
Jean Christophe Beyler4e97c532014-01-07 10:07:18 -0800715 /* Create the pass driver and launch it */
Jean Christophe Beyler2469e602014-05-06 20:36:55 -0700716 PassDriverMEOpts pass_driver(&cu);
Ian Rogers3d504072014-03-01 09:16:49 -0800717 pass_driver.Launch();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700718
Calin Juravle38a09042014-06-23 14:40:31 +0100719 /* For non-leaf methods check if we should skip compilation when the profiler is enabled. */
720 if (cu.compiler_driver->ProfilePresent()
721 && !cu.mir_graph->MethodIsLeaf()
722 && cu.mir_graph->SkipCompilationByName(method_name)) {
723 return nullptr;
724 }
725
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700726 if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
727 cu.mir_graph->DumpCheckStats();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700728 }
729
730 if (kCompilerDebugFlags & (1 << kDebugCountOpcodes)) {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700731 cu.mir_graph->ShowOpcodeStats();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700732 }
733
buzbee1da1e2f2013-11-15 13:37:01 -0800734 /* Reassociate sreg names with original Dalvik vreg names. */
735 cu.mir_graph->RemapRegLocations();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700736
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000737 /* Free Arenas from the cu.arena_stack for reuse by the cu.arena in the codegen. */
738 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
739 if (cu.arena_stack.PeakBytesAllocated() > 256 * 1024) {
740 MemStats stack_stats(cu.arena_stack.GetPeakStats());
Calin Juravle38a09042014-06-23 14:40:31 +0100741 LOG(INFO) << method_name << " " << Dumpable<MemStats>(stack_stats);
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000742 }
743 }
744 cu.arena_stack.Reset();
745
Brian Carlstrom7940e442013-07-12 13:46:57 -0700746 CompiledMethod* result = NULL;
747
buzbee8c7a02a2014-06-14 12:33:09 -0700748 if (cu.mir_graph->PuntToInterpreter()) {
Calin Juravle38a09042014-06-23 14:40:31 +0100749 VLOG(compiler) << cu.instruction_set << ": Punted method to interpreter: " << method_name;
Andreas Gampe060e6fe2014-06-19 11:34:06 -0700750 return nullptr;
buzbee8c7a02a2014-06-14 12:33:09 -0700751 }
752
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700753 cu.cg->Materialize();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700754
buzbee1da1e2f2013-11-15 13:37:01 -0800755 cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700756 result = cu.cg->GetCompiledMethod();
buzbee1da1e2f2013-11-15 13:37:01 -0800757 cu.NewTimingSplit("Cleanup");
Brian Carlstrom7940e442013-07-12 13:46:57 -0700758
759 if (result) {
Calin Juravle38a09042014-06-23 14:40:31 +0100760 VLOG(compiler) << cu.instruction_set << ": Compiled " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700761 } else {
Calin Juravle38a09042014-06-23 14:40:31 +0100762 VLOG(compiler) << cu.instruction_set << ": Deferred " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700763 }
764
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700765 if (cu.enable_debug & (1 << kDebugShowMemoryUsage)) {
Vladimir Marko53b6afc2014-03-21 14:21:20 +0000766 if (cu.arena.BytesAllocated() > (1 * 1024 *1024)) {
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000767 MemStats mem_stats(cu.arena.GetMemStats());
Calin Juravle38a09042014-06-23 14:40:31 +0100768 LOG(INFO) << method_name << " " << Dumpable<MemStats>(mem_stats);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700769 }
770 }
771
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700772 if (cu.enable_debug & (1 << kDebugShowSummaryMemoryUsage)) {
773 LOG(INFO) << "MEMINFO " << cu.arena.BytesAllocated() << " " << cu.mir_graph->GetNumBlocks()
Calin Juravle38a09042014-06-23 14:40:31 +0100774 << " " << method_name;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700775 }
776
buzbeea61f4952013-08-23 14:27:06 -0700777 cu.EndTiming();
Ian Rogers3d504072014-03-01 09:16:49 -0800778 driver.GetTimingsLogger()->AddLogger(cu.timings);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700779 return result;
780}
781
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000782CompiledMethod* CompileOneMethod(CompilerDriver& driver,
783 Compiler* compiler,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700784 const DexFile::CodeItem* code_item,
785 uint32_t access_flags,
786 InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700787 uint16_t class_def_idx,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700788 uint32_t method_idx,
789 jobject class_loader,
790 const DexFile& dex_file,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000791 void* compilation_unit) {
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000792 return CompileMethod(driver, compiler, code_item, access_flags, invoke_type, class_def_idx,
Nicolas Geoffrayf5df8972014-02-14 18:37:08 +0000793 method_idx, class_loader, dex_file, compilation_unit);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700794}
795
796} // namespace art
797
798extern "C" art::CompiledMethod*
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000799 ArtQuickCompileMethod(art::CompilerDriver& driver,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700800 const art::DexFile::CodeItem* code_item,
801 uint32_t access_flags, art::InvokeType invoke_type,
Ian Rogers8b2c0b92013-09-19 02:56:49 -0700802 uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700803 const art::DexFile& dex_file) {
Andreas Gampe00caeed2014-07-10 01:43:08 -0700804 // TODO: check method fingerprint here to determine appropriate backend type. Until then, use
805 // build default.
Nicolas Geoffrayb34f69a2014-03-07 15:28:39 +0000806 art::Compiler* compiler = driver.GetCompiler();
807 return art::CompileOneMethod(driver, compiler, code_item, access_flags, invoke_type,
Brian Carlstrom7940e442013-07-12 13:46:57 -0700808 class_def_idx, method_idx, class_loader, dex_file,
809 NULL /* use thread llvm_info */);
810}