2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #ifndef _DALVIK_VM_COMPILER
21 #define _DALVIK_VM_COMPILER
24 * Uncomment the following to enable JIT signature breakpoint
25 * #define SIGNATURE_BREAKPOINT
28 #define MAX_JIT_RUN_LEN 64
29 #define COMPILER_WORK_QUEUE_SIZE 100
30 #define COMPILER_IC_PATCH_QUEUE_SIZE 64
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
43 #define COMPILER_TRACED(X)
44 #define COMPILER_TRACEE(X)
45 #define COMPILER_TRACE_CHAINING(X)
47 /* Macro to change the permissions applied to a chunk of the code cache */
48 #if !defined(WITH_JIT_TUNING)
49 #define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC)
50 #define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE)
52 /* When doing JIT profiling always grant the write permission */
53 #define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | \
54 (gDvmJit.profile ? PROT_WRITE : 0))
55 #define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE)
58 /* Acquire the lock before removing PROT_WRITE from the specified mem region */
59 #define UNPROTECT_CODE_CACHE(addr, size) \
61 dvmLockMutex(&gDvmJit.codeCacheProtectionLock); \
62 mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask), \
63 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask), \
64 (UNPROTECT_CODE_CACHE_ATTRS)); \
67 /* Add the PROT_WRITE to the specified memory region then release the lock */
68 #define PROTECT_CODE_CACHE(addr, size) \
70 mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask), \
71 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask), \
72 (PROTECT_CODE_CACHE_ATTRS)); \
73 dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock); \
76 #define SINGLE_STEP_OP(opcode) \
77 (gDvmJit.includeSelectedOp != \
78 ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0))
80 typedef enum JitInstructionSetType {
87 } JitInstructionSetType;
89 /* Description of a compiled trace. */
90 typedef struct JitTranslationInfo {
92 JitInstructionSetType instructionSet;
93 bool discardResult; // Used for debugging divergence and IC patching
94 bool methodCompilationAborted; // Cannot compile the whole method
95 Thread *requestingThread; // For debugging purpose
98 typedef enum WorkOrderKind {
99 kWorkOrderInvalid = 0, // Should never see by the backend
100 kWorkOrderMethod = 1, // Work is to compile a whole method
101 kWorkOrderTrace = 2, // Work is to compile code fragment(s)
102 kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s)
105 typedef struct CompilerWorkOrder {
109 JitTranslationInfo result;
113 /* Chain cell for predicted method invocation */
114 typedef struct PredictedChainingCell {
115 u4 branch; /* Branch to chained destination */
116 const ClassObject *clazz; /* key for prediction */
117 const Method *method; /* to lookup native PC from dalvik PC */
118 const ClassObject *stagedClazz; /* possible next key for prediction */
119 } PredictedChainingCell;
121 /* Work order for inline cache patching */
122 typedef struct ICPatchWorkOrder {
123 PredictedChainingCell *cellAddr; /* Address to be patched */
124 PredictedChainingCell cellContent; /* content of the new cell */
127 /* States of the dbg interpreter when serving a JIT-related request */
128 typedef enum JitState {
129 /* Entering states in the debug interpreter */
130 kJitNot = 0, // Non-JIT related reasons */
131 kJitTSelectRequest = 1, // Request a trace (subject to filtering)
132 kJitTSelectRequestHot = 2, // Request a hot trace (bypass the filter)
133 kJitSelfVerification = 3, // Self Verification Mode
135 /* Operational states in the debug interpreter */
136 kJitTSelect = 4, // Actively selecting a trace
137 kJitTSelectEnd = 5, // Done with the trace - wrap it up
138 kJitSingleStep = 6, // Single step interpretation
139 kJitSingleStepEnd = 7, // Done with single step, ready return to mterp
140 kJitDone = 8, // Ready to leave the debug interpreter
143 #if defined(WITH_SELF_VERIFICATION)
144 typedef enum SelfVerificationState {
145 kSVSIdle = 0, // Idle
146 kSVSStart = 1, // Shadow space set up, running compiled code
147 kSVSPunt = 2, // Exiting compiled code by punting
148 kSVSSingleStep = 3, // Exiting compiled code by single stepping
149 kSVSNoProfile = 4, // Exiting compiled code and don't collect profiles
150 kSVSTraceSelect = 5, // Exiting compiled code and compile the next pc
151 kSVSNormal = 6, // Exiting compiled code normally
152 kSVSNoChain = 7, // Exiting compiled code by no chain
153 kSVSBackwardBranch = 8, // Exiting compiled code with backward branch trace
154 kSVSDebugInterp = 9, // Normal state restored, running debug interpreter
155 } SelfVerificationState;
158 typedef enum JitHint {
160 kJitHintTaken = 1, // Last inst in run was taken branch
161 kJitHintNotTaken = 2, // Last inst in run was not taken branch
162 kJitHintNoBias = 3, // Last inst in run was unbiased branch
166 * Element of a Jit trace description. If the isCode bit is set, it describes
167 * a contiguous sequence of Dalvik byte codes.
170 unsigned isCode:1; // If set denotes code fragments
171 unsigned numInsts:8; // Number of Byte codes in run
172 unsigned runEnd:1; // Run ends with last byte code
173 jitHint hint:6; // Hint to apply to final code of run
174 u2 startOffset; // Starting offset for trace run
178 * A complete list of trace runs passed to the compiler looks like the
187 * frags 1-4 have the "isCode" field set, and metas 1-2 are plain pointers or
188 * pointers to auxiliary data structures as long as the LSB is null.
189 * The meaning of the meta content is loosely defined. It is usually the code
190 * fragment right before the first meta field (frag3 in this case) to
191 * understand and parse them. Frag4 could be a dummy one with 0 "numInsts" but
192 * the "runEnd" field set.
194 * For example, if a trace run contains a method inlining target, the class
195 * type of "this" and the currently resolved method pointer are two instances
196 * of meta information stored there.
204 * Trace description as will appear in the translation cache. Note
205 * flexible array at end, as these will be of variable size. To
206 * conserve space in the translation cache, total length of JitTraceRun
207 * array must be recomputed via seqential scan if needed.
210 const Method* method;
211 JitTraceRun trace[0]; // Variable-length trace descriptors
212 } JitTraceDescription;
214 typedef enum JitMethodAttributes {
215 kIsCallee = 0, /* Code is part of a callee (invoked by a hot trace) */
216 kIsHot, /* Code is part of a hot trace */
217 kIsLeaf, /* Method is leaf */
218 kIsEmpty, /* Method is empty */
219 kIsThrowFree, /* Method doesn't throw */
220 kIsGetter, /* Method fits the getter pattern */
221 kIsSetter, /* Method fits the setter pattern */
222 } JitMethodAttributes;
224 #define METHOD_IS_CALLEE (1 << kIsCallee)
225 #define METHOD_IS_HOT (1 << kIsHot)
226 #define METHOD_IS_LEAF (1 << kIsLeaf)
227 #define METHOD_IS_EMPTY (1 << kIsEmpty)
228 #define METHOD_IS_THROW_FREE (1 << kIsThrowFree)
229 #define METHOD_IS_GETTER (1 << kIsGetter)
230 #define METHOD_IS_SETTER (1 << kIsSetter)
232 /* Vectors to provide optimization hints */
233 typedef enum JitOptimizationHints {
234 kJitOptNoLoop = 0, // Disable loop formation/optimization
235 } JitOptimizationHints;
237 #define JIT_OPT_NO_LOOP (1 << kJitOptNoLoop)
239 typedef struct CompilerMethodStats {
240 const Method *method; // Used as hash entry signature
241 int dalvikSize; // # of bytes for dalvik bytecodes
242 int compiledDalvikSize; // # of compiled dalvik bytecodes
243 int nativeSize; // # of bytes for produced native code
244 int attributes; // attribute vector
245 } CompilerMethodStats;
247 struct CompilationUnit;
249 struct SSARepresentation;
254 bool dvmCompilerSetupCodeCache(void);
255 bool dvmCompilerArchInit(void);
256 void dvmCompilerArchDump(void);
257 bool dvmCompilerStartup(void);
258 void dvmCompilerShutdown(void);
259 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
260 void *dvmCheckCodeCache(void *method);
261 CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
263 bool dvmCompilerCanIncludeThisInstruction(const Method *method,
264 const DecodedInstruction *insn);
265 bool dvmCompileMethod(struct CompilationUnit *cUnit, const Method *method,
266 JitTranslationInfo *info);
267 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
268 JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
269 void dvmCompilerDumpStats(void);
270 void dvmCompilerDrainQueue(void);
271 void dvmJitUnchainAll(void);
272 void dvmCompilerSortAndPrintTraceProfiles(void);
273 void dvmCompilerPerformSafePointChecks(void);
274 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit);
275 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
276 int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
277 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
278 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
279 void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
280 struct BasicBlock *bb);
281 void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
282 struct BasicBlock *bb);
283 void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
284 struct BasicBlock *bb);
285 void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
286 struct BasicBlock *bb);
287 char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn, char *note);
288 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
289 struct SSARepresentation *ssaRep);
290 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
291 void (*func)(struct CompilationUnit *, struct BasicBlock *));
292 void dvmCompilerStateRefresh(void);
293 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
294 const struct JitEntry *desc);
295 void *dvmCompilerGetInterpretTemplate();
296 #endif /* _DALVIK_VM_COMPILER */