Compiler.h revision fbdcfb9ea9e2a78f295834424c3f24986ea45dac
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#include <Thread.h>
18#include <setjmp.h>
19
20#ifndef _DALVIK_VM_COMPILER
21#define _DALVIK_VM_COMPILER
22
23/*
24 * Uncomment the following to enable JIT signature breakpoint
25 * #define SIGNATURE_BREAKPOINT
26 */
27
28#define MAX_JIT_RUN_LEN                 64
29#define COMPILER_WORK_QUEUE_SIZE        100
30#define COMPILER_IC_PATCH_QUEUE_SIZE    64
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#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)
51#else
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)
56#endif
57
58/* Acquire the lock before removing PROT_WRITE from the specified mem region */
59#define UNPROTECT_CODE_CACHE(addr, size)                                       \
60    {                                                                          \
61        dvmLockMutex(&gDvmJit.codeCacheProtectionLock);                        \
62        mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
63                 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
64                 (UNPROTECT_CODE_CACHE_ATTRS));                                \
65    }
66
67/* Add the PROT_WRITE to the specified memory region then release the lock */
68#define PROTECT_CODE_CACHE(addr, size)                                         \
69    {                                                                          \
70        mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
71                 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
72                 (PROTECT_CODE_CACHE_ATTRS));                                  \
73        dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock);                      \
74    }
75
76typedef enum JitInstructionSetType {
77    DALVIK_JIT_NONE = 0,
78    DALVIK_JIT_ARM,
79    DALVIK_JIT_THUMB,
80    DALVIK_JIT_THUMB2,
81    DALVIK_JIT_THUMB2EE,
82    DALVIK_JIT_X86
83} JitInstructionSetType;
84
85/* Description of a compiled trace. */
86typedef struct JitTranslationInfo {
87    void *codeAddress;
88    JitInstructionSetType instructionSet;
89    bool discardResult;         // Used for debugging divergence and IC patching
90    Thread *requestingThread;   // For debugging purpose
91} JitTranslationInfo;
92
93typedef 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} WorkOrderKind;
99
100typedef struct CompilerWorkOrder {
101    const u2* pc;
102    WorkOrderKind kind;
103    void* info;
104    JitTranslationInfo result;
105    jmp_buf *bailPtr;
106} CompilerWorkOrder;
107
108/* Chain cell for predicted method invocation */
109typedef struct PredictedChainingCell {
110    u4 branch;                  /* Branch to chained destination */
111    const ClassObject *clazz;   /* key for prediction */
112    const Method *method;       /* to lookup native PC from dalvik PC */
113    const ClassObject *stagedClazz;   /* possible next key for prediction */
114} PredictedChainingCell;
115
116/* Work order for inline cache patching */
117typedef struct ICPatchWorkOrder {
118    PredictedChainingCell *cellAddr;    /* Address to be patched */
119    PredictedChainingCell cellContent;  /* content of the new cell */
120} ICPatchWorkOrder;
121
122/* States of the dbg interpreter when serving a JIT-related request */
123typedef enum JitState {
124    /* Entering states in the debug interpreter */
125    kJitNot = 0,               // Non-JIT related reasons */
126    kJitTSelectRequest = 1,    // Request a trace (subject to filtering)
127    kJitTSelectRequestHot = 2, // Request a hot trace (bypass the filter)
128    kJitSelfVerification = 3,  // Self Verification Mode
129
130    /* Operational states in the debug interpreter */
131    kJitTSelect = 4,           // Actively selecting a trace
132    kJitTSelectEnd = 5,        // Done with the trace - wrap it up
133    kJitSingleStep = 6,        // Single step interpretation
134    kJitSingleStepEnd = 7,     // Done with single step, ready return to mterp
135    kJitDone = 8,              // Ready to leave the debug interpreter
136} JitState;
137
138#if defined(WITH_SELF_VERIFICATION)
139typedef enum SelfVerificationState {
140    kSVSIdle = 0,           // Idle
141    kSVSStart = 1,          // Shadow space set up, running compiled code
142    kSVSPunt = 2,           // Exiting compiled code by punting
143    kSVSSingleStep = 3,     // Exiting compiled code by single stepping
144    kSVSTraceSelectNoChain = 4,// Exiting compiled code by trace select no chain
145    kSVSTraceSelect = 5,    // Exiting compiled code by trace select
146    kSVSNormal = 6,         // Exiting compiled code normally
147    kSVSNoChain = 7,        // Exiting compiled code by no chain
148    kSVSBackwardBranch = 8, // Exiting compiled code with backward branch trace
149    kSVSDebugInterp = 9,    // Normal state restored, running debug interpreter
150} SelfVerificationState;
151#endif
152
153typedef enum JitHint {
154   kJitHintNone = 0,
155   kJitHintTaken = 1,         // Last inst in run was taken branch
156   kJitHintNotTaken = 2,      // Last inst in run was not taken branch
157   kJitHintNoBias = 3,        // Last inst in run was unbiased branch
158} jitHint;
159
160/*
161 * Element of a Jit trace description.  Describes a contiguous
162 * sequence of Dalvik byte codes, the last of which can be
163 * associated with a hint.
164 * Dalvik byte code
165 */
166typedef struct {
167    u2    startOffset;       // Starting offset for trace run
168    unsigned numInsts:8;     // Number of Byte codes in run
169    unsigned runEnd:1;       // Run ends with last byte code
170    jitHint  hint:7;         // Hint to apply to final code of run
171} JitCodeDesc;
172
173typedef union {
174    JitCodeDesc frag;
175    void*       hint;
176} JitTraceRun;
177
178/*
179 * Trace description as will appear in the translation cache.  Note
180 * flexible array at end, as these will be of variable size.  To
181 * conserve space in the translation cache, total length of JitTraceRun
182 * array must be recomputed via seqential scan if needed.
183 */
184typedef struct {
185    const Method* method;
186    JitTraceRun trace[];
187} JitTraceDescription;
188
189typedef struct CompilerMethodStats {
190    const Method *method;       // Used as hash entry signature
191    int dalvikSize;             // # of bytes for dalvik bytecodes
192    int compiledDalvikSize;     // # of compiled dalvik bytecodes
193    int nativeSize;             // # of bytes for produced native code
194} CompilerMethodStats;
195
196bool dvmCompilerSetupCodeCache(void);
197bool dvmCompilerArchInit(void);
198void dvmCompilerArchDump(void);
199bool dvmCompilerStartup(void);
200void dvmCompilerShutdown(void);
201bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
202void *dvmCheckCodeCache(void *method);
203bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
204bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
205                     JitTranslationInfo *info, jmp_buf *bailPtr);
206void dvmCompilerDumpStats(void);
207void dvmCompilerDrainQueue(void);
208void dvmJitUnchainAll(void);
209void dvmCompilerSortAndPrintTraceProfiles(void);
210void dvmCompilerPerformSafePointChecks(void);
211
212struct CompilationUnit;
213struct BasicBlock;
214struct SSARepresentation;
215struct GrowableList;
216struct JitEntry;
217
218void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
219int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
220void dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
221void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
222void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
223                           struct BasicBlock *bb);
224void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
225                                struct BasicBlock *bb);
226void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
227                                      struct BasicBlock *bb);
228void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
229                                       struct BasicBlock *bb);
230char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn);
231char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
232                              struct SSARepresentation *ssaRep);
233void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
234                void (*func)(struct CompilationUnit *, struct BasicBlock *));
235void dvmCompilerStateRefresh(void);
236JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
237                                            const struct JitEntry *desc);
238void *dvmCompilerGetInterpretTemplate();
239#endif /* _DALVIK_VM_COMPILER */
240