Compiler.h revision d72564ca7aa66c6d95b6ca34299258b65ecfd1cb
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#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} JitInstructionSetType; 80 81/* Description of a compiled trace. */ 82typedef struct JitTranslationInfo { 83 void *codeAddress; 84 JitInstructionSetType instructionSet; 85 int profileCodeSize; 86 bool discardResult; // Used for debugging divergence and IC patching 87 bool methodCompilationAborted; // Cannot compile the whole method 88 Thread *requestingThread; // For debugging purpose 89 int cacheVersion; // Used to identify stale trace requests 90} JitTranslationInfo; 91 92typedef enum WorkOrderKind { 93 kWorkOrderInvalid = 0, // Should never see by the backend 94 kWorkOrderMethod = 1, // Work is to compile a whole method 95 kWorkOrderTrace = 2, // Work is to compile code fragment(s) 96 kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s) 97 kWorkOrderProfileMode = 4, // Change profiling mode 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 kSVSNoProfile = 4, // Exiting compiled code and don't collect profiles 145 kSVSTraceSelect = 5, // Exiting compiled code and compile the next pc 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. If the isCode bit is set, it describes 162 * a contiguous sequence of Dalvik byte codes. 163 */ 164typedef struct { 165 unsigned isCode:1; // If set denotes code fragments 166 unsigned numInsts:8; // Number of Byte codes in run 167 unsigned runEnd:1; // Run ends with last byte code 168 jitHint hint:6; // Hint to apply to final code of run 169 u2 startOffset; // Starting offset for trace run 170} JitCodeDesc; 171 172/* 173 * A complete list of trace runs passed to the compiler looks like the 174 * following: 175 * frag1 176 * frag2 177 * frag3 178 * meta1 179 * meta2 180 * frag4 181 * 182 * frags 1-4 have the "isCode" field set, and metas 1-2 are plain pointers or 183 * pointers to auxiliary data structures as long as the LSB is null. 184 * The meaning of the meta content is loosely defined. It is usually the code 185 * fragment right before the first meta field (frag3 in this case) to 186 * understand and parse them. Frag4 could be a dummy one with 0 "numInsts" but 187 * the "runEnd" field set. 188 * 189 * For example, if a trace run contains a method inlining target, the class 190 * type of "this" and the currently resolved method pointer are two instances 191 * of meta information stored there. 192 */ 193typedef union { 194 JitCodeDesc frag; 195 void* meta; 196} JitTraceRun; 197 198/* 199 * Trace description as will appear in the translation cache. Note 200 * flexible array at end, as these will be of variable size. To 201 * conserve space in the translation cache, total length of JitTraceRun 202 * array must be recomputed via seqential scan if needed. 203 */ 204typedef struct { 205 const Method* method; 206 JitTraceRun trace[0]; // Variable-length trace descriptors 207} JitTraceDescription; 208 209typedef enum JitMethodAttributes { 210 kIsCallee = 0, /* Code is part of a callee (invoked by a hot trace) */ 211 kIsHot, /* Code is part of a hot trace */ 212 kIsLeaf, /* Method is leaf */ 213 kIsEmpty, /* Method is empty */ 214 kIsThrowFree, /* Method doesn't throw */ 215 kIsGetter, /* Method fits the getter pattern */ 216 kIsSetter, /* Method fits the setter pattern */ 217 kCannotCompile, /* Method cannot be compiled */ 218} JitMethodAttributes; 219 220#define METHOD_IS_CALLEE (1 << kIsCallee) 221#define METHOD_IS_HOT (1 << kIsHot) 222#define METHOD_IS_LEAF (1 << kIsLeaf) 223#define METHOD_IS_EMPTY (1 << kIsEmpty) 224#define METHOD_IS_THROW_FREE (1 << kIsThrowFree) 225#define METHOD_IS_GETTER (1 << kIsGetter) 226#define METHOD_IS_SETTER (1 << kIsSetter) 227#define METHOD_CANNOT_COMPILE (1 << kCannotCompile) 228 229/* Vectors to provide optimization hints */ 230typedef enum JitOptimizationHints { 231 kJitOptNoLoop = 0, // Disable loop formation/optimization 232} JitOptimizationHints; 233 234#define JIT_OPT_NO_LOOP (1 << kJitOptNoLoop) 235 236/* Customized node traversal orders for different needs */ 237typedef enum DataFlowAnalysisMode { 238 kAllNodes = 0, // All nodes 239 kReachableNodes, // All reachable nodes 240 kPreOrderDFSTraversal, // Depth-First-Search / Pre-Order 241 kPostOrderDFSTraversal, // Depth-First-Search / Post-Order 242 kPostOrderDOMTraversal, // Dominator tree / Post-Order 243} DataFlowAnalysisMode; 244 245typedef struct CompilerMethodStats { 246 const Method *method; // Used as hash entry signature 247 int dalvikSize; // # of bytes for dalvik bytecodes 248 int compiledDalvikSize; // # of compiled dalvik bytecodes 249 int nativeSize; // # of bytes for produced native code 250 int attributes; // attribute vector 251} CompilerMethodStats; 252 253struct CompilationUnit; 254struct BasicBlock; 255struct SSARepresentation; 256struct GrowableList; 257struct JitEntry; 258struct MIR; 259 260bool dvmCompilerSetupCodeCache(void); 261bool dvmCompilerArchInit(void); 262void dvmCompilerArchDump(void); 263bool dvmCompilerStartup(void); 264void dvmCompilerShutdown(void); 265void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); 266bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); 267void *dvmCheckCodeCache(void *method); 268CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method, 269 bool isCallee); 270bool dvmCompilerCanIncludeThisInstruction(const Method *method, 271 const DecodedInstruction *insn); 272bool dvmCompileMethod(const Method *method, JitTranslationInfo *info); 273bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts, 274 JitTranslationInfo *info, jmp_buf *bailPtr, int optHints); 275void dvmCompilerDumpStats(void); 276void dvmCompilerDrainQueue(void); 277void dvmJitUnchainAll(void); 278void dvmCompilerSortAndPrintTraceProfiles(void); 279void dvmCompilerPerformSafePointChecks(void); 280void dvmCompilerInlineMIR(struct CompilationUnit *cUnit, 281 JitTranslationInfo *info); 282void dvmInitializeSSAConversion(struct CompilationUnit *cUnit); 283int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg); 284bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit); 285void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit); 286bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit, 287 struct BasicBlock *bb); 288bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit, 289 struct BasicBlock *bb); 290bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit, 291 struct BasicBlock *bb); 292bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit, 293 struct BasicBlock *bb); 294/* Clear the visited flag for each BB */ 295bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit, 296 struct BasicBlock *bb); 297char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn, 298 char *note); 299char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit, 300 const struct MIR *mir); 301char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit, 302 struct SSARepresentation *ssaRep); 303void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit, 304 bool (*func)(struct CompilationUnit *, struct BasicBlock *), 305 DataFlowAnalysisMode dfaMode, 306 bool isIterative); 307void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit); 308void dvmCompilerStateRefresh(void); 309JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 310 const struct JitEntry *desc); 311void *dvmCompilerGetInterpretTemplate(); 312JitInstructionSetType dvmCompilerGetInterpretTemplateSet(); 313u8 dvmGetRegResourceMask(int reg); 314#endif /* _DALVIK_VM_COMPILER */ 315