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