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 72typedef 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. */ 81typedef 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 91typedef 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 99typedef 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 */ 108typedef 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 */ 116typedef 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 */ 130typedef struct { 131 const Method* method; 132 JitTraceRun trace[0]; // Variable-length trace descriptors 133} JitTraceDescription; 134 135typedef 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 */ 156typedef 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 */ 163typedef 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 171typedef 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 179struct CompilationUnit; 180struct BasicBlock; 181struct SSARepresentation; 182struct GrowableList; 183struct JitEntry; 184struct MIR; 185 186bool dvmCompilerSetupCodeCache(void); 187bool dvmCompilerArchInit(void); 188void dvmCompilerArchDump(void); 189bool dvmCompilerStartup(void); 190void dvmCompilerShutdown(void); 191void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); 192bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); 193void *dvmCheckCodeCache(void *method); 194CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method, 195 bool isCallee); 196bool dvmCompilerCanIncludeThisInstruction(const Method *method, 197 const DecodedInstruction *insn); 198bool dvmCompileMethod(const Method *method, JitTranslationInfo *info); 199bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts, 200 JitTranslationInfo *info, jmp_buf *bailPtr, int optHints); 201void dvmCompilerDumpStats(void); 202void dvmCompilerDrainQueue(void); 203void dvmJitUnchainAll(void); 204void dvmJitScanAllClassPointers(void (*callback)(void *ptr)); 205void dvmCompilerSortAndPrintTraceProfiles(void); 206void dvmCompilerPerformSafePointChecks(void); 207void dvmCompilerInlineMIR(struct CompilationUnit *cUnit, 208 JitTranslationInfo *info); 209void dvmInitializeSSAConversion(struct CompilationUnit *cUnit); 210int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg); 211bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit); 212void dvmCompilerInsertBackwardChaining(struct CompilationUnit *cUnit); 213void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit); 214bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit, 215 struct BasicBlock *bb); 216bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit, 217 struct BasicBlock *bb); 218bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit, 219 struct BasicBlock *bb); 220bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit, 221 struct BasicBlock *bb); 222/* Clear the visited flag for each BB */ 223bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit, 224 struct BasicBlock *bb); 225char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn, 226 const char *note); 227char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit, 228 const struct MIR *mir); 229char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit, 230 struct SSARepresentation *ssaRep); 231void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit, 232 bool (*func)(struct CompilationUnit *, struct BasicBlock *), 233 DataFlowAnalysisMode dfaMode, 234 bool isIterative); 235void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit); 236bool dvmCompilerBuildLoop(struct CompilationUnit *cUnit); 237void dvmCompilerUpdateGlobalState(void); 238JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 239 const struct JitEntry *desc); 240extern "C" void *dvmCompilerGetInterpretTemplate(); 241JitInstructionSetType dvmCompilerGetInterpretTemplateSet(); 242u8 dvmGetRegResourceMask(int reg); 243void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix); 244 245#endif // DALVIK_VM_COMPILER_H_ 246