Compiler.h revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
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
73typedef 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. */
83typedef 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
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    kWorkOrderProfileMode = 4,  // Change profiling mode
99} WorkOrderKind;
100
101typedef 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 */
110typedef 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 */
123typedef 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 */
137typedef struct {
138    const Method* method;
139    JitTraceRun trace[0];       // Variable-length trace descriptors
140} JitTraceDescription;
141
142typedef 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 */
163typedef 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 */
170typedef 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
178typedef 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
186struct CompilationUnit;
187struct BasicBlock;
188struct SSARepresentation;
189struct GrowableList;
190struct JitEntry;
191struct MIR;
192
193bool dvmCompilerSetupCodeCache(void);
194bool dvmCompilerArchInit(void);
195void dvmCompilerArchDump(void);
196bool dvmCompilerStartup(void);
197void dvmCompilerShutdown(void);
198void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
199bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
200void *dvmCheckCodeCache(void *method);
201CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
202                                                  bool isCallee);
203bool dvmCompilerCanIncludeThisInstruction(const Method *method,
204                                          const DecodedInstruction *insn);
205bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
206bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
207                     JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
208void dvmCompilerDumpStats(void);
209void dvmCompilerDrainQueue(void);
210void dvmJitUnchainAll(void);
211void dvmJitScanAllClassPointers(void (*callback)(void *ptr));
212void dvmCompilerSortAndPrintTraceProfiles(void);
213void dvmCompilerPerformSafePointChecks(void);
214void dvmCompilerInlineMIR(struct CompilationUnit *cUnit,
215                          JitTranslationInfo *info);
216void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
217int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg);
218bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
219void dvmCompilerInsertBackwardChaining(struct CompilationUnit *cUnit);
220void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
221bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit,
222                                struct BasicBlock *bb);
223bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
224                                struct BasicBlock *bb);
225bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
226                                      struct BasicBlock *bb);
227bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
228                                       struct BasicBlock *bb);
229/* Clear the visited flag for each BB */
230bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
231                                 struct BasicBlock *bb);
232char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
233                                      const char *note);
234char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit,
235                                  const struct MIR *mir);
236char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
237                              struct SSARepresentation *ssaRep);
238void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
239                bool (*func)(struct CompilationUnit *, struct BasicBlock *),
240                DataFlowAnalysisMode dfaMode,
241                bool isIterative);
242void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit);
243bool dvmCompilerBuildLoop(struct CompilationUnit *cUnit);
244void dvmCompilerUpdateGlobalState(void);
245JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
246                                            const struct JitEntry *desc);
247extern "C" void *dvmCompilerGetInterpretTemplate();
248JitInstructionSetType dvmCompilerGetInterpretTemplateSet();
249u8 dvmGetRegResourceMask(int reg);
250void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix);
251bool dvmIsOpcodeSupportedByJit(Opcode opcode);
252
253#endif  // DALVIK_VM_COMPILER_H_
254