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