• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef DALVIK_VM_COMPILER_H_
18 #define DALVIK_VM_COMPILER_H_
19 
20 #include <setjmp.h>
21 #include "Thread.h"
22 
23 /*
24  * Uncomment the following to enable JIT signature breakpoint
25  * #define SIGNATURE_BREAKPOINT
26  */
27 
28 #define COMPILER_WORK_QUEUE_SIZE        100
29 #define COMPILER_IC_PATCH_QUEUE_SIZE    64
30 #define COMPILER_PC_OFFSET_SIZE         100
31 
32 /* Architectural-independent parameters for predicted chains */
33 #define PREDICTED_CHAIN_CLAZZ_INIT       0
34 #define PREDICTED_CHAIN_METHOD_INIT      0
35 #define PREDICTED_CHAIN_COUNTER_INIT     0
36 /* A fake value which will avoid initialization and won't match any class */
37 #define PREDICTED_CHAIN_FAKE_CLAZZ       0xdeadc001
38 /* Has to be positive */
39 #define PREDICTED_CHAIN_COUNTER_AVOID    0x7fffffff
40 /* Rechain after this many misses - shared globally and has to be positive */
41 #define PREDICTED_CHAIN_COUNTER_RECHAIN  8192
42 
43 #define COMPILER_TRACED(X)
44 #define COMPILER_TRACEE(X)
45 #define COMPILER_TRACE_CHAINING(X)
46 
47 /* Macro to change the permissions applied to a chunk of the code cache */
48 #define PROTECT_CODE_CACHE_ATTRS       (PROT_READ | PROT_EXEC)
49 #define UNPROTECT_CODE_CACHE_ATTRS     (PROT_READ | PROT_EXEC | PROT_WRITE)
50 
51 /* Acquire the lock before removing PROT_WRITE from the specified mem region */
52 #define UNPROTECT_CODE_CACHE(addr, size)                                       \
53     {                                                                          \
54         dvmLockMutex(&gDvmJit.codeCacheProtectionLock);                        \
55         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
56                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
57                  (UNPROTECT_CODE_CACHE_ATTRS));                                \
58     }
59 
60 /* Add the PROT_WRITE to the specified memory region then release the lock */
61 #define PROTECT_CODE_CACHE(addr, size)                                         \
62     {                                                                          \
63         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
64                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
65                  (PROTECT_CODE_CACHE_ATTRS));                                  \
66         dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock);                      \
67     }
68 
69 #define SINGLE_STEP_OP(opcode)                                                 \
70     (gDvmJit.includeSelectedOp !=                                              \
71      ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0))
72 
73 typedef enum JitInstructionSetType {
74     DALVIK_JIT_NONE = 0,
75     DALVIK_JIT_ARM,
76     DALVIK_JIT_THUMB,
77     DALVIK_JIT_THUMB2,
78     DALVIK_JIT_IA32,
79     DALVIK_JIT_MIPS
80 } JitInstructionSetType;
81 
82 /* Description of a compiled trace. */
83 typedef struct JitTranslationInfo {
84     void *codeAddress;
85     JitInstructionSetType instructionSet;
86     int profileCodeSize;
87     bool discardResult;         // Used for debugging divergence and IC patching
88     bool methodCompilationAborted;  // Cannot compile the whole method
89     Thread *requestingThread;   // For debugging purpose
90     int cacheVersion;           // Used to identify stale trace requests
91 } JitTranslationInfo;
92 
93 typedef enum WorkOrderKind {
94     kWorkOrderInvalid = 0,      // Should never see by the backend
95     kWorkOrderMethod = 1,       // Work is to compile a whole method
96     kWorkOrderTrace = 2,        // Work is to compile code fragment(s)
97     kWorkOrderTraceDebug = 3,   // Work is to compile/debug code fragment(s)
98     kWorkOrderProfileMode = 4,  // Change profiling mode
99 } WorkOrderKind;
100 
101 typedef struct CompilerWorkOrder {
102     const u2* pc;
103     WorkOrderKind kind;
104     void* info;
105     JitTranslationInfo result;
106     jmp_buf *bailPtr;
107 } CompilerWorkOrder;
108 
109 /* Chain cell for predicted method invocation */
110 typedef struct PredictedChainingCell {
111     u4 branch;                  /* Branch to chained destination */
112 #ifdef __mips__
113     u4 delay_slot;              /* nop goes here */
114 #elif defined(ARCH_IA32)
115     u4 branch2;                 /* IA32 branch instr may be > 32 bits */
116 #endif
117     const ClassObject *clazz;   /* key for prediction */
118     const Method *method;       /* to lookup native PC from dalvik PC */
119     const ClassObject *stagedClazz;   /* possible next key for prediction */
120 } PredictedChainingCell;
121 
122 /* Work order for inline cache patching */
123 typedef struct ICPatchWorkOrder {
124     PredictedChainingCell *cellAddr;    /* Address to be patched */
125     PredictedChainingCell cellContent;  /* content of the new cell */
126     const char *classDescriptor;        /* Descriptor of the class object */
127     Object *classLoader;                /* Class loader */
128     u4 serialNumber;                    /* Serial # (for verification only) */
129 } ICPatchWorkOrder;
130 
131 /*
132  * Trace description as will appear in the translation cache.  Note
133  * flexible array at end, as these will be of variable size.  To
134  * conserve space in the translation cache, total length of JitTraceRun
135  * array must be recomputed via seqential scan if needed.
136  */
137 typedef struct {
138     const Method* method;
139     JitTraceRun trace[0];       // Variable-length trace descriptors
140 } JitTraceDescription;
141 
142 typedef enum JitMethodAttributes {
143     kIsCallee = 0,      /* Code is part of a callee (invoked by a hot trace) */
144     kIsHot,             /* Code is part of a hot trace */
145     kIsLeaf,            /* Method is leaf */
146     kIsEmpty,           /* Method is empty */
147     kIsThrowFree,       /* Method doesn't throw */
148     kIsGetter,          /* Method fits the getter pattern */
149     kIsSetter,          /* Method fits the setter pattern */
150     kCannotCompile,     /* Method cannot be compiled */
151 } JitMethodAttributes;
152 
153 #define METHOD_IS_CALLEE        (1 << kIsCallee)
154 #define METHOD_IS_HOT           (1 << kIsHot)
155 #define METHOD_IS_LEAF          (1 << kIsLeaf)
156 #define METHOD_IS_EMPTY         (1 << kIsEmpty)
157 #define METHOD_IS_THROW_FREE    (1 << kIsThrowFree)
158 #define METHOD_IS_GETTER        (1 << kIsGetter)
159 #define METHOD_IS_SETTER        (1 << kIsSetter)
160 #define METHOD_CANNOT_COMPILE   (1 << kCannotCompile)
161 
162 /* Vectors to provide optimization hints */
163 typedef enum JitOptimizationHints {
164     kJitOptNoLoop = 0,          // Disable loop formation/optimization
165 } JitOptimizationHints;
166 
167 #define JIT_OPT_NO_LOOP         (1 << kJitOptNoLoop)
168 
169 /* Customized node traversal orders for different needs */
170 typedef enum DataFlowAnalysisMode {
171     kAllNodes = 0,              // All nodes
172     kReachableNodes,            // All reachable nodes
173     kPreOrderDFSTraversal,      // Depth-First-Search / Pre-Order
174     kPostOrderDFSTraversal,     // Depth-First-Search / Post-Order
175     kPostOrderDOMTraversal,     // Dominator tree / Post-Order
176 } DataFlowAnalysisMode;
177 
178 typedef struct CompilerMethodStats {
179     const Method *method;       // Used as hash entry signature
180     int dalvikSize;             // # of bytes for dalvik bytecodes
181     int compiledDalvikSize;     // # of compiled dalvik bytecodes
182     int nativeSize;             // # of bytes for produced native code
183     int attributes;             // attribute vector
184 } CompilerMethodStats;
185 
186 struct CompilationUnit;
187 struct BasicBlock;
188 struct SSARepresentation;
189 struct GrowableList;
190 struct JitEntry;
191 struct MIR;
192 
193 bool dvmCompilerSetupCodeCache(void);
194 bool dvmCompilerArchInit(void);
195 void dvmCompilerArchDump(void);
196 bool dvmCompilerStartup(void);
197 void dvmCompilerShutdown(void);
198 void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
199 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
200 void *dvmCheckCodeCache(void *method);
201 CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
202                                                   bool isCallee);
203 bool dvmCompilerCanIncludeThisInstruction(const Method *method,
204                                           const DecodedInstruction *insn);
205 bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
206 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
207                      JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
208 void dvmCompilerDumpStats(void);
209 void dvmCompilerDrainQueue(void);
210 void dvmJitUnchainAll(void);
211 void dvmJitScanAllClassPointers(void (*callback)(void *ptr));
212 void dvmCompilerSortAndPrintTraceProfiles(void);
213 void dvmCompilerPerformSafePointChecks(void);
214 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit,
215                           JitTranslationInfo *info);
216 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
217 int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg);
218 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
219 void dvmCompilerInsertBackwardChaining(struct CompilationUnit *cUnit);
220 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
221 bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit,
222                                 struct BasicBlock *bb);
223 bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
224                                 struct BasicBlock *bb);
225 bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
226                                       struct BasicBlock *bb);
227 bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
228                                        struct BasicBlock *bb);
229 /* Clear the visited flag for each BB */
230 bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
231                                  struct BasicBlock *bb);
232 char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
233                                       const char *note);
234 char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit,
235                                   const struct MIR *mir);
236 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
237                               struct SSARepresentation *ssaRep);
238 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
239                 bool (*func)(struct CompilationUnit *, struct BasicBlock *),
240                 DataFlowAnalysisMode dfaMode,
241                 bool isIterative);
242 void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit);
243 bool dvmCompilerBuildLoop(struct CompilationUnit *cUnit);
244 void dvmCompilerUpdateGlobalState(void);
245 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
246                                             const struct JitEntry *desc);
247 extern "C" void *dvmCompilerGetInterpretTemplate();
248 JitInstructionSetType dvmCompilerGetInterpretTemplateSet();
249 u8 dvmGetRegResourceMask(int reg);
250 void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix);
251 bool dvmIsOpcodeSupportedByJit(Opcode opcode);
252 
253 #endif  // DALVIK_VM_COMPILER_H_
254