diff options
author | buzbee <buzbee@google.com> | 2013-07-31 10:47:37 -0700 |
---|---|---|
committer | Bill Buzbee <buzbee@google.com> | 2013-08-08 20:33:11 +0000 |
commit | ee17e0aa4d24deb11c1766bfcc6a864519df1c1e (patch) | |
tree | 99b003e7524544156a4e94bcca7daa41ed4d4b77 /compiler/dex/mir_analysis.cc | |
parent | e0a53e99e2a01f8668d6616c3cec7e2f5a711286 (diff) | |
download | android_art-ee17e0aa4d24deb11c1766bfcc6a864519df1c1e.tar.gz android_art-ee17e0aa4d24deb11c1766bfcc6a864519df1c1e.tar.bz2 android_art-ee17e0aa4d24deb11c1766bfcc6a864519df1c1e.zip |
Compilation filter
This CL introduces a static compilation filter mechanism intended
to allow us to reduce compilation time and space requirements until
we have a profiling mechanism in place.
It supports 5 modes of filtering:
o interpret-only (compile nothing)
o deferred-compilation (compile only those methods believe to be
compute-intensive)
o space (optimized for space)
o balanced (best return on space investment)
o speed (compile everything)
A future CL will allow the default filtering mode to be set
via system property. For now, you can pass it in via command
line as follows:
dalvikvm -compiler-filter:[interpret-only|defer-compilation|
space|balanced|speed]
or dex2oat --runtime-arg -compiler-filter:[one of the above modes]
Creating a file named art/SMALL_ART will force the filter
default to interpret-only. Later on we'll move this capability
to a persistent system property.
or modify kDefaultCompilerFilter in runtime.h
It also changes the compiler driver to allow the compilers to
decline to compile a method by return NULL.
Change-Id: Ic73411818f8bb845a4a19a05b0395c50902c534f
(cherry picked from commit a024a0686c3b0fea13f362bff70d65981e5febc5)
Diffstat (limited to 'compiler/dex/mir_analysis.cc')
-rw-r--r-- | compiler/dex/mir_analysis.cc | 1056 |
1 files changed, 1056 insertions, 0 deletions
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc new file mode 100644 index 0000000000..8321ff63d3 --- /dev/null +++ b/compiler/dex/mir_analysis.cc @@ -0,0 +1,1056 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compiler_internals.h" +#include "dataflow_iterator-inl.h" + +namespace art { + + // Instruction characteristics used to statically identify computation-intensive methods. +const uint32_t MIRGraph::analysis_attributes_[kMirOpLast] = { + // 00 NOP + AN_NONE, + + // 01 MOVE vA, vB + AN_MOVE, + + // 02 MOVE_FROM16 vAA, vBBBB + AN_MOVE, + + // 03 MOVE_16 vAAAA, vBBBB + AN_MOVE, + + // 04 MOVE_WIDE vA, vB + AN_MOVE, + + // 05 MOVE_WIDE_FROM16 vAA, vBBBB + AN_MOVE, + + // 06 MOVE_WIDE_16 vAAAA, vBBBB + AN_MOVE, + + // 07 MOVE_OBJECT vA, vB + AN_MOVE, + + // 08 MOVE_OBJECT_FROM16 vAA, vBBBB + AN_MOVE, + + // 09 MOVE_OBJECT_16 vAAAA, vBBBB + AN_MOVE, + + // 0A MOVE_RESULT vAA + AN_MOVE, + + // 0B MOVE_RESULT_WIDE vAA + AN_MOVE, + + // 0C MOVE_RESULT_OBJECT vAA + AN_MOVE, + + // 0D MOVE_EXCEPTION vAA + AN_MOVE, + + // 0E RETURN_VOID + AN_BRANCH, + + // 0F RETURN vAA + AN_BRANCH, + + // 10 RETURN_WIDE vAA + AN_BRANCH, + + // 11 RETURN_OBJECT vAA + AN_BRANCH, + + // 12 CONST_4 vA, #+B + AN_SIMPLECONST, + + // 13 CONST_16 vAA, #+BBBB + AN_SIMPLECONST, + + // 14 CONST vAA, #+BBBBBBBB + AN_SIMPLECONST, + + // 15 CONST_HIGH16 VAA, #+BBBB0000 + AN_SIMPLECONST, + + // 16 CONST_WIDE_16 vAA, #+BBBB + AN_SIMPLECONST, + + // 17 CONST_WIDE_32 vAA, #+BBBBBBBB + AN_SIMPLECONST, + + // 18 CONST_WIDE vAA, #+BBBBBBBBBBBBBBBB + AN_SIMPLECONST, + + // 19 CONST_WIDE_HIGH16 vAA, #+BBBB000000000000 + AN_SIMPLECONST, + + // 1A CONST_STRING vAA, string@BBBB + AN_NONE, + + // 1B CONST_STRING_JUMBO vAA, string@BBBBBBBB + AN_NONE, + + // 1C CONST_CLASS vAA, type@BBBB + AN_NONE, + + // 1D MONITOR_ENTER vAA + AN_NONE, + + // 1E MONITOR_EXIT vAA + AN_NONE, + + // 1F CHK_CAST vAA, type@BBBB + AN_NONE, + + // 20 INSTANCE_OF vA, vB, type@CCCC + AN_NONE, + + // 21 ARRAY_LENGTH vA, vB + AN_ARRAYOP, + + // 22 NEW_INSTANCE vAA, type@BBBB + AN_HEAVYWEIGHT, + + // 23 NEW_ARRAY vA, vB, type@CCCC + AN_HEAVYWEIGHT, + + // 24 FILLED_NEW_ARRAY {vD, vE, vF, vG, vA} + AN_HEAVYWEIGHT, + + // 25 FILLED_NEW_ARRAY_RANGE {vCCCC .. vNNNN}, type@BBBB + AN_HEAVYWEIGHT, + + // 26 FILL_ARRAY_DATA vAA, +BBBBBBBB + AN_NONE, + + // 27 THROW vAA + AN_HEAVYWEIGHT | AN_BRANCH, + + // 28 GOTO + AN_BRANCH, + + // 29 GOTO_16 + AN_BRANCH, + + // 2A GOTO_32 + AN_BRANCH, + + // 2B PACKED_SWITCH vAA, +BBBBBBBB + AN_NONE, + + // 2C SPARSE_SWITCH vAA, +BBBBBBBB + AN_NONE, + + // 2D CMPL_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // 2E CMPG_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // 2F CMPL_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // 30 CMPG_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // 31 CMP_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // 32 IF_EQ vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 33 IF_NE vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 34 IF_LT vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 35 IF_GE vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 36 IF_GT vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 37 IF_LE vA, vB, +CCCC + AN_MATH | AN_BRANCH | AN_INT, + + // 38 IF_EQZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 39 IF_NEZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 3A IF_LTZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 3B IF_GEZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 3C IF_GTZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 3D IF_LEZ vAA, +BBBB + AN_MATH | AN_BRANCH | AN_INT, + + // 3E UNUSED_3E + AN_NONE, + + // 3F UNUSED_3F + AN_NONE, + + // 40 UNUSED_40 + AN_NONE, + + // 41 UNUSED_41 + AN_NONE, + + // 42 UNUSED_42 + AN_NONE, + + // 43 UNUSED_43 + AN_NONE, + + // 44 AGET vAA, vBB, vCC + AN_ARRAYOP, + + // 45 AGET_WIDE vAA, vBB, vCC + AN_ARRAYOP, + + // 46 AGET_OBJECT vAA, vBB, vCC + AN_ARRAYOP, + + // 47 AGET_BOOLEAN vAA, vBB, vCC + AN_ARRAYOP, + + // 48 AGET_BYTE vAA, vBB, vCC + AN_ARRAYOP, + + // 49 AGET_CHAR vAA, vBB, vCC + AN_ARRAYOP, + + // 4A AGET_SHORT vAA, vBB, vCC + AN_ARRAYOP, + + // 4B APUT vAA, vBB, vCC + AN_ARRAYOP, + + // 4C APUT_WIDE vAA, vBB, vCC + AN_ARRAYOP, + + // 4D APUT_OBJECT vAA, vBB, vCC + AN_ARRAYOP, + + // 4E APUT_BOOLEAN vAA, vBB, vCC + AN_ARRAYOP, + + // 4F APUT_BYTE vAA, vBB, vCC + AN_ARRAYOP, + + // 50 APUT_CHAR vAA, vBB, vCC + AN_ARRAYOP, + + // 51 APUT_SHORT vAA, vBB, vCC + AN_ARRAYOP, + + // 52 IGET vA, vB, field@CCCC + AN_NONE, + + // 53 IGET_WIDE vA, vB, field@CCCC + AN_NONE, + + // 54 IGET_OBJECT vA, vB, field@CCCC + AN_NONE, + + // 55 IGET_BOOLEAN vA, vB, field@CCCC + AN_NONE, + + // 56 IGET_BYTE vA, vB, field@CCCC + AN_NONE, + + // 57 IGET_CHAR vA, vB, field@CCCC + AN_NONE, + + // 58 IGET_SHORT vA, vB, field@CCCC + AN_NONE, + + // 59 IPUT vA, vB, field@CCCC + AN_NONE, + + // 5A IPUT_WIDE vA, vB, field@CCCC + AN_NONE, + + // 5B IPUT_OBJECT vA, vB, field@CCCC + AN_NONE, + + // 5C IPUT_BOOLEAN vA, vB, field@CCCC + AN_NONE, + + // 5D IPUT_BYTE vA, vB, field@CCCC + AN_NONE, + + // 5E IPUT_CHAR vA, vB, field@CCCC + AN_NONE, + + // 5F IPUT_SHORT vA, vB, field@CCCC + AN_NONE, + + // 60 SGET vAA, field@BBBB + AN_NONE, + + // 61 SGET_WIDE vAA, field@BBBB + AN_NONE, + + // 62 SGET_OBJECT vAA, field@BBBB + AN_NONE, + + // 63 SGET_BOOLEAN vAA, field@BBBB + AN_NONE, + + // 64 SGET_BYTE vAA, field@BBBB + AN_NONE, + + // 65 SGET_CHAR vAA, field@BBBB + AN_NONE, + + // 66 SGET_SHORT vAA, field@BBBB + AN_NONE, + + // 67 SPUT vAA, field@BBBB + AN_NONE, + + // 68 SPUT_WIDE vAA, field@BBBB + AN_NONE, + + // 69 SPUT_OBJECT vAA, field@BBBB + AN_NONE, + + // 6A SPUT_BOOLEAN vAA, field@BBBB + AN_NONE, + + // 6B SPUT_BYTE vAA, field@BBBB + AN_NONE, + + // 6C SPUT_CHAR vAA, field@BBBB + AN_NONE, + + // 6D SPUT_SHORT vAA, field@BBBB + AN_NONE, + + // 6E INVOKE_VIRTUAL {vD, vE, vF, vG, vA} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 6F INVOKE_SUPER {vD, vE, vF, vG, vA} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 70 INVOKE_DIRECT {vD, vE, vF, vG, vA} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 71 INVOKE_STATIC {vD, vE, vF, vG, vA} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 73 UNUSED_73 + AN_NONE, + + // 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 75 INVOKE_SUPER_RANGE {vCCCC .. vNNNN} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 76 INVOKE_DIRECT_RANGE {vCCCC .. vNNNN} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 77 INVOKE_STATIC_RANGE {vCCCC .. vNNNN} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 78 INVOKE_INTERFACE_RANGE {vCCCC .. vNNNN} + AN_INVOKE | AN_HEAVYWEIGHT, + + // 79 UNUSED_79 + AN_NONE, + + // 7A UNUSED_7A + AN_NONE, + + // 7B NEG_INT vA, vB + AN_MATH | AN_INT, + + // 7C NOT_INT vA, vB + AN_MATH | AN_INT, + + // 7D NEG_LONG vA, vB + AN_MATH | AN_LONG, + + // 7E NOT_LONG vA, vB + AN_MATH | AN_LONG, + + // 7F NEG_FLOAT vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // 80 NEG_DOUBLE vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // 81 INT_TO_LONG vA, vB + AN_MATH | AN_INT | AN_LONG, + + // 82 INT_TO_FLOAT vA, vB + AN_MATH | AN_FP | AN_INT | AN_SINGLE, + + // 83 INT_TO_DOUBLE vA, vB + AN_MATH | AN_FP | AN_INT | AN_DOUBLE, + + // 84 LONG_TO_INT vA, vB + AN_MATH | AN_INT | AN_LONG, + + // 85 LONG_TO_FLOAT vA, vB + AN_MATH | AN_FP | AN_LONG | AN_SINGLE, + + // 86 LONG_TO_DOUBLE vA, vB + AN_MATH | AN_FP | AN_LONG | AN_DOUBLE, + + // 87 FLOAT_TO_INT vA, vB + AN_MATH | AN_FP | AN_INT | AN_SINGLE, + + // 88 FLOAT_TO_LONG vA, vB + AN_MATH | AN_FP | AN_LONG | AN_SINGLE, + + // 89 FLOAT_TO_DOUBLE vA, vB + AN_MATH | AN_FP | AN_SINGLE | AN_DOUBLE, + + // 8A DOUBLE_TO_INT vA, vB + AN_MATH | AN_FP | AN_INT | AN_DOUBLE, + + // 8B DOUBLE_TO_LONG vA, vB + AN_MATH | AN_FP | AN_LONG | AN_DOUBLE, + + // 8C DOUBLE_TO_FLOAT vA, vB + AN_MATH | AN_FP | AN_SINGLE | AN_DOUBLE, + + // 8D INT_TO_BYTE vA, vB + AN_MATH | AN_INT, + + // 8E INT_TO_CHAR vA, vB + AN_MATH | AN_INT, + + // 8F INT_TO_SHORT vA, vB + AN_MATH | AN_INT, + + // 90 ADD_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 91 SUB_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 92 MUL_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 93 DIV_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 94 REM_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 95 AND_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 96 OR_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 97 XOR_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 98 SHL_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 99 SHR_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 9A USHR_INT vAA, vBB, vCC + AN_MATH | AN_INT, + + // 9B ADD_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // 9C SUB_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // 9D MUL_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // 9E DIV_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // 9F REM_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A0 AND_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A1 OR_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A2 XOR_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A3 SHL_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A4 SHR_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A5 USHR_LONG vAA, vBB, vCC + AN_MATH | AN_LONG, + + // A6 ADD_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // A7 SUB_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // A8 MUL_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // A9 DIV_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // AA REM_FLOAT vAA, vBB, vCC + AN_MATH | AN_FP | AN_SINGLE, + + // AB ADD_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // AC SUB_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // AD MUL_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // AE DIV_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // AF REM_DOUBLE vAA, vBB, vCC + AN_MATH | AN_FP | AN_DOUBLE, + + // B0 ADD_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B1 SUB_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B2 MUL_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B3 DIV_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B4 REM_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B5 AND_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B6 OR_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B7 XOR_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B8 SHL_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // B9 SHR_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // BA USHR_INT_2ADDR vA, vB + AN_MATH | AN_INT, + + // BB ADD_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // BC SUB_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // BD MUL_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // BE DIV_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // BF REM_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C0 AND_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C1 OR_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C2 XOR_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C3 SHL_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C4 SHR_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C5 USHR_LONG_2ADDR vA, vB + AN_MATH | AN_LONG, + + // C6 ADD_FLOAT_2ADDR vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // C7 SUB_FLOAT_2ADDR vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // C8 MUL_FLOAT_2ADDR vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // C9 DIV_FLOAT_2ADDR vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // CA REM_FLOAT_2ADDR vA, vB + AN_MATH | AN_FP | AN_SINGLE, + + // CB ADD_DOUBLE_2ADDR vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // CC SUB_DOUBLE_2ADDR vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // CD MUL_DOUBLE_2ADDR vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // CE DIV_DOUBLE_2ADDR vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // CF REM_DOUBLE_2ADDR vA, vB + AN_MATH | AN_FP | AN_DOUBLE, + + // D0 ADD_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D1 RSUB_INT vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D2 MUL_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D3 DIV_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D4 REM_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D5 AND_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D6 OR_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D7 XOR_INT_LIT16 vA, vB, #+CCCC + AN_MATH | AN_INT, + + // D8 ADD_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // D9 RSUB_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DA MUL_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DB DIV_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DC REM_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DD AND_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DE OR_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // DF XOR_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // E0 SHL_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // E1 SHR_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // E2 USHR_INT_LIT8 vAA, vBB, #+CC + AN_MATH | AN_INT, + + // E3 IGET_VOLATILE + AN_NONE, + + // E4 IPUT_VOLATILE + AN_NONE, + + // E5 SGET_VOLATILE + AN_NONE, + + // E6 SPUT_VOLATILE + AN_NONE, + + // E7 IGET_OBJECT_VOLATILE + AN_NONE, + + // E8 IGET_WIDE_VOLATILE + AN_NONE, + + // E9 IPUT_WIDE_VOLATILE + AN_NONE, + + // EA SGET_WIDE_VOLATILE + AN_NONE, + + // EB SPUT_WIDE_VOLATILE + AN_NONE, + + // EC BREAKPOINT + AN_NONE, + + // ED THROW_VERIFICATION_ERROR + AN_HEAVYWEIGHT | AN_BRANCH, + + // EE EXECUTE_INLINE + AN_NONE, + + // EF EXECUTE_INLINE_RANGE + AN_NONE, + + // F0 INVOKE_OBJECT_INIT_RANGE + AN_INVOKE | AN_HEAVYWEIGHT, + + // F1 RETURN_VOID_BARRIER + AN_BRANCH, + + // F2 IGET_QUICK + AN_NONE, + + // F3 IGET_WIDE_QUICK + AN_NONE, + + // F4 IGET_OBJECT_QUICK + AN_NONE, + + // F5 IPUT_QUICK + AN_NONE, + + // F6 IPUT_WIDE_QUICK + AN_NONE, + + // F7 IPUT_OBJECT_QUICK + AN_NONE, + + // F8 INVOKE_VIRTUAL_QUICK + AN_INVOKE | AN_HEAVYWEIGHT, + + // F9 INVOKE_VIRTUAL_QUICK_RANGE + AN_INVOKE | AN_HEAVYWEIGHT, + + // FA INVOKE_SUPER_QUICK + AN_INVOKE | AN_HEAVYWEIGHT, + + // FB INVOKE_SUPER_QUICK_RANGE + AN_INVOKE | AN_HEAVYWEIGHT, + + // FC IPUT_OBJECT_VOLATILE + AN_NONE, + + // FD SGET_OBJECT_VOLATILE + AN_NONE, + + // FE SPUT_OBJECT_VOLATILE + AN_NONE, + + // FF UNUSED_FF + AN_NONE, + + // Beginning of extended MIR opcodes + // 100 MIR_PHI + AN_NONE, + + // 101 MIR_COPY + AN_NONE, + + // 102 MIR_FUSED_CMPL_FLOAT + AN_NONE, + + // 103 MIR_FUSED_CMPG_FLOAT + AN_NONE, + + // 104 MIR_FUSED_CMPL_DOUBLE + AN_NONE, + + // 105 MIR_FUSED_CMPG_DOUBLE + AN_NONE, + + // 106 MIR_FUSED_CMP_LONG + AN_NONE, + + // 107 MIR_NOP + AN_NONE, + + // 108 MIR_NULL_CHECK + AN_NONE, + + // 109 MIR_RANGE_CHECK + AN_NONE, + + // 110 MIR_DIV_ZERO_CHECK + AN_NONE, + + // 111 MIR_CHECK + AN_NONE, + + // 112 MIR_CHECKPART2 + AN_NONE, + + // 113 MIR_SELECT + AN_NONE, +}; + +struct MethodStats { + int dex_instructions; + int math_ops; + int fp_ops; + int array_ops; + int branch_ops; + int heavyweight_ops; + bool has_computational_loop; + float math_ratio; + float fp_ratio; + float array_ratio; + float branch_ratio; + float heavyweight_ratio; +}; + +void MIRGraph::AnalyzeBlock(BasicBlock* bb, MethodStats* stats) { + if (bb->visited || (bb->block_type != kDalvikByteCode)) { + return; + } + bool computational_block = true; + bool has_math = false; + /* + * For the purposes of this scan, we want to treat the set of basic blocks broken + * by an exception edge as a single basic block. We'll scan forward along the fallthrough + * edges until we reach an explicit branch or return. + */ + BasicBlock* ending_bb = bb; + if (ending_bb->last_mir_insn != NULL) { + uint32_t ending_flags = analysis_attributes_[ending_bb->last_mir_insn->dalvikInsn.opcode]; + while ((ending_flags & AN_BRANCH) == 0) { + ending_bb = ending_bb->fall_through; + ending_flags = analysis_attributes_[ending_bb->last_mir_insn->dalvikInsn.opcode]; + } + } + /* + * Ideally, we'd weight the operations by loop nesting level, but to do so we'd + * first need to do some expensive loop detection - and the point of this is to make + * an informed guess before investing in computation. However, we can cheaply detect + * many simple loop forms without having to do full dataflow analysis. + */ + int loop_scale_factor = 1; + // Simple for and while loops + if ((ending_bb->taken != NULL) && (ending_bb->fall_through == NULL)) { + if ((ending_bb->taken->taken == bb) || (ending_bb->taken->fall_through == bb)) { + loop_scale_factor = 25; + } + } + // Simple do-while loop + if ((ending_bb->taken != NULL) && (ending_bb->taken == bb)) { + loop_scale_factor = 25; + } + + BasicBlock* tbb = bb; + bool done = false; + while (!done) { + tbb->visited = true; + for (MIR* mir = tbb->first_mir_insn; mir != NULL; mir = mir->next) { + if (static_cast<uint32_t>(mir->dalvikInsn.opcode) >= kMirOpFirst) { + // Skip any MIR pseudo-op. + continue; + } + uint32_t flags = analysis_attributes_[mir->dalvikInsn.opcode]; + stats->dex_instructions += loop_scale_factor; + if ((flags & AN_BRANCH) == 0) { + computational_block &= ((flags & AN_COMPUTATIONAL) != 0); + } else { + stats->branch_ops += loop_scale_factor; + } + if ((flags & AN_MATH) != 0) { + stats->math_ops += loop_scale_factor; + has_math = true; + } + if ((flags & AN_FP) != 0) { + stats->fp_ops += loop_scale_factor; + } + if ((flags & AN_ARRAYOP) != 0) { + stats->array_ops += loop_scale_factor; + } + if ((flags & AN_HEAVYWEIGHT) != 0) { + stats->heavyweight_ops += loop_scale_factor; + } + } + if (tbb == ending_bb) { + done = true; + } else { + tbb = tbb->fall_through; + } + } + if (has_math && computational_block && (loop_scale_factor > 1)) { + stats->has_computational_loop = true; + } +} + +bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { + float count = stats->dex_instructions; + stats->math_ratio = stats->math_ops / count; + stats->fp_ratio = stats->fp_ops / count; + stats->branch_ratio = stats->branch_ops / count; + stats->array_ratio = stats->array_ops / count; + stats->heavyweight_ratio = stats->heavyweight_ops / count; + + if (cu_->enable_debug & (1 << kDebugShowFilterStats)) { + LOG(INFO) << "STATS " << stats->dex_instructions << ", math:" + << stats->math_ratio << ", fp:" + << stats->fp_ratio << ", br:" + << stats->branch_ratio << ", hw:" + << stats-> heavyweight_ratio << ", arr:" + << stats->array_ratio << ", hot:" + << stats->has_computational_loop << ", " + << PrettyMethod(cu_->method_idx, *cu_->dex_file); + } + + // Computation intensive? + if (stats->has_computational_loop && (stats->heavyweight_ratio < 0.04)) { + return false; + } + + // Complex, logic-intensive? + if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) && + stats->branch_ratio > 0.3) { + return false; + } + + // Significant floating point? + if (stats->fp_ratio > 0.05) { + return false; + } + + // Significant generic math? + if (stats->math_ratio > 0.3) { + return false; + } + + // If array-intensive, compiling is probably worthwhile. + if (stats->array_ratio > 0.1) { + return false; + } + + // If high proportion of expensive operations, skip. + if (stats->heavyweight_ratio > 0.3) { + return true; + } + + return skip_default; +} + + /* + * Will eventually want this to be a bit more sophisticated and happen at verification time. + * Ultimate goal is to drive with profile data. + */ +bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { + if (compiler_filter == Runtime::kSpeed) { + // If going for speed, compile everything. + return false; + } + + if (compiler_filter == Runtime::kInterpretOnly) { + LOG(WARNING) << "InterpretOnly should ideally be filtered out prior to parsing."; + return true; + } + + // Filter 1: Skip huge methods (generally machine-generated initialization methods). + if (GetNumDalvikInsns() > Runtime::Current()->GetHugeMethodThreshold()) { + // Ain't nobody got time for that. + return true; + } + + // Filter 2: Skip class initializers. + if (((cu_->access_flags & kAccConstructor) != 0) && ((cu_->access_flags & kAccStatic) != 0)) { + return true; + } + + // Filter 3: if this method is a special pattern, go ahead and emit the canned pattern. + if (IsSpecialCase()) { + return false; + } + + /* In balanced mode, we generally assume that we'll be compiling, and then detect + * methods that won't benefit and remove them. In space or deferred mode, we do the + * opposite: assume no compilation and then add back presumed hot methods. + */ + bool skip_compilation = (compiler_filter == Runtime::kBalanced) ? false : true; + + + // Filter 4: go ahead and compile the small ones. + size_t small_cutoff = 0; + switch (compiler_filter) { + case Runtime::kBalanced: + small_cutoff = Runtime::Current()->GetSmallMethodThreshold(); + break; + case Runtime::kSpace: + small_cutoff = Runtime::Current()->GetTinyMethodThreshold(); + break; + case Runtime::kDeferCompilation: + small_cutoff = 0; + break; + default: + LOG(FATAL) << "Unexpected compiler_filter_: " << compiler_filter; + } + if (GetNumDalvikInsns() < small_cutoff) { + return false; + } + + // Analyze graph for: + // o floating point computation + // o basic blocks contained in loop with heavy arithmetic. + // o proportion of conditional branches. + + MethodStats stats; + memset(&stats, 0, sizeof(stats)); + + ClearAllVisitedFlags(); + AllNodesIterator iter(this, false /* not iterative */); + for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) { + AnalyzeBlock(bb, &stats); + } + + return ComputeSkipCompilation(&stats, skip_compilation); +} + +} // namespace art |