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 #if !defined(WITH_JIT_TUNING) 49 #define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC) 50 #define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE) 51 #else 52 /* When doing JIT profiling always grant the write permission */ 53 #define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | \ 54 (gDvmJit.profile ? PROT_WRITE : 0)) 55 #define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE) 56 #endif 57 58 /* Acquire the lock before removing PROT_WRITE from the specified mem region */ 59 #define UNPROTECT_CODE_CACHE(addr, size) \ 60 { \ 61 dvmLockMutex(&gDvmJit.codeCacheProtectionLock); \ 62 mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask), \ 63 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask), \ 64 (UNPROTECT_CODE_CACHE_ATTRS)); \ 65 } 66 67 /* Add the PROT_WRITE to the specified memory region then release the lock */ 68 #define PROTECT_CODE_CACHE(addr, size) \ 69 { \ 70 mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask), \ 71 (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask), \ 72 (PROTECT_CODE_CACHE_ATTRS)); \ 73 dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock); \ 74 } 75 76 #define SINGLE_STEP_OP(opcode) \ 77 (gDvmJit.includeSelectedOp != \ 78 ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0)) 79 80 typedef enum JitInstructionSetType { 81 DALVIK_JIT_NONE = 0, 82 DALVIK_JIT_ARM, 83 DALVIK_JIT_THUMB, 84 DALVIK_JIT_THUMB2, 85 DALVIK_JIT_THUMB2EE, 86 DALVIK_JIT_X86 87 } JitInstructionSetType; 88 89 /* Description of a compiled trace. */ 90 typedef struct JitTranslationInfo { 91 void *codeAddress; 92 JitInstructionSetType instructionSet; 93 bool discardResult; // Used for debugging divergence and IC patching 94 bool methodCompilationAborted; // Cannot compile the whole method 95 Thread *requestingThread; // For debugging purpose 96 } JitTranslationInfo; 97 98 typedef enum WorkOrderKind { 99 kWorkOrderInvalid = 0, // Should never see by the backend 100 kWorkOrderMethod = 1, // Work is to compile a whole method 101 kWorkOrderTrace = 2, // Work is to compile code fragment(s) 102 kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s) 103 } WorkOrderKind; 104 105 typedef struct CompilerWorkOrder { 106 const u2* pc; 107 WorkOrderKind kind; 108 void* info; 109 JitTranslationInfo result; 110 jmp_buf *bailPtr; 111 } CompilerWorkOrder; 112 113 /* Chain cell for predicted method invocation */ 114 typedef struct PredictedChainingCell { 115 u4 branch; /* Branch to chained destination */ 116 const ClassObject *clazz; /* key for prediction */ 117 const Method *method; /* to lookup native PC from dalvik PC */ 118 const ClassObject *stagedClazz; /* possible next key for prediction */ 119 } PredictedChainingCell; 120 121 /* Work order for inline cache patching */ 122 typedef struct ICPatchWorkOrder { 123 PredictedChainingCell *cellAddr; /* Address to be patched */ 124 PredictedChainingCell cellContent; /* content of the new cell */ 125 } ICPatchWorkOrder; 126 127 /* States of the dbg interpreter when serving a JIT-related request */ 128 typedef enum JitState { 129 /* Entering states in the debug interpreter */ 130 kJitNot = 0, // Non-JIT related reasons */ 131 kJitTSelectRequest = 1, // Request a trace (subject to filtering) 132 kJitTSelectRequestHot = 2, // Request a hot trace (bypass the filter) 133 kJitSelfVerification = 3, // Self Verification Mode 134 135 /* Operational states in the debug interpreter */ 136 kJitTSelect = 4, // Actively selecting a trace 137 kJitTSelectEnd = 5, // Done with the trace - wrap it up 138 kJitSingleStep = 6, // Single step interpretation 139 kJitSingleStepEnd = 7, // Done with single step, ready return to mterp 140 kJitDone = 8, // Ready to leave the debug interpreter 141 } JitState; 142 143 #if defined(WITH_SELF_VERIFICATION) 144 typedef enum SelfVerificationState { 145 kSVSIdle = 0, // Idle 146 kSVSStart = 1, // Shadow space set up, running compiled code 147 kSVSPunt = 2, // Exiting compiled code by punting 148 kSVSSingleStep = 3, // Exiting compiled code by single stepping 149 kSVSNoProfile = 4, // Exiting compiled code and don't collect profiles 150 kSVSTraceSelect = 5, // Exiting compiled code and compile the next pc 151 kSVSNormal = 6, // Exiting compiled code normally 152 kSVSNoChain = 7, // Exiting compiled code by no chain 153 kSVSBackwardBranch = 8, // Exiting compiled code with backward branch trace 154 kSVSDebugInterp = 9, // Normal state restored, running debug interpreter 155 } SelfVerificationState; 156 #endif 157 158 typedef enum JitHint { 159 kJitHintNone = 0, 160 kJitHintTaken = 1, // Last inst in run was taken branch 161 kJitHintNotTaken = 2, // Last inst in run was not taken branch 162 kJitHintNoBias = 3, // Last inst in run was unbiased branch 163 } jitHint; 164 165 /* 166 * Element of a Jit trace description. If the isCode bit is set, it describes 167 * a contiguous sequence of Dalvik byte codes. 168 */ 169 typedef struct { 170 unsigned isCode:1; // If set denotes code fragments 171 unsigned numInsts:8; // Number of Byte codes in run 172 unsigned runEnd:1; // Run ends with last byte code 173 jitHint hint:6; // Hint to apply to final code of run 174 u2 startOffset; // Starting offset for trace run 175 } JitCodeDesc; 176 177 /* 178 * A complete list of trace runs passed to the compiler looks like the 179 * following: 180 * frag1 181 * frag2 182 * frag3 183 * meta1 184 * meta2 185 * frag4 186 * 187 * frags 1-4 have the "isCode" field set, and metas 1-2 are plain pointers or 188 * pointers to auxiliary data structures as long as the LSB is null. 189 * The meaning of the meta content is loosely defined. It is usually the code 190 * fragment right before the first meta field (frag3 in this case) to 191 * understand and parse them. Frag4 could be a dummy one with 0 "numInsts" but 192 * the "runEnd" field set. 193 * 194 * For example, if a trace run contains a method inlining target, the class 195 * type of "this" and the currently resolved method pointer are two instances 196 * of meta information stored there. 197 */ 198 typedef union { 199 JitCodeDesc frag; 200 void* meta; 201 } JitTraceRun; 202 203 /* 204 * Trace description as will appear in the translation cache. Note 205 * flexible array at end, as these will be of variable size. To 206 * conserve space in the translation cache, total length of JitTraceRun 207 * array must be recomputed via seqential scan if needed. 208 */ 209 typedef struct { 210 const Method* method; 211 JitTraceRun trace[0]; // Variable-length trace descriptors 212 } JitTraceDescription; 213 214 typedef enum JitMethodAttributes { 215 kIsCallee = 0, /* Code is part of a callee (invoked by a hot trace) */ 216 kIsHot, /* Code is part of a hot trace */ 217 kIsLeaf, /* Method is leaf */ 218 kIsEmpty, /* Method is empty */ 219 kIsThrowFree, /* Method doesn't throw */ 220 kIsGetter, /* Method fits the getter pattern */ 221 kIsSetter, /* Method fits the setter pattern */ 222 } JitMethodAttributes; 223 224 #define METHOD_IS_CALLEE (1 << kIsCallee) 225 #define METHOD_IS_HOT (1 << kIsHot) 226 #define METHOD_IS_LEAF (1 << kIsLeaf) 227 #define METHOD_IS_EMPTY (1 << kIsEmpty) 228 #define METHOD_IS_THROW_FREE (1 << kIsThrowFree) 229 #define METHOD_IS_GETTER (1 << kIsGetter) 230 #define METHOD_IS_SETTER (1 << kIsSetter) 231 232 /* Vectors to provide optimization hints */ 233 typedef enum JitOptimizationHints { 234 kJitOptNoLoop = 0, // Disable loop formation/optimization 235 } JitOptimizationHints; 236 237 #define JIT_OPT_NO_LOOP (1 << kJitOptNoLoop) 238 239 typedef struct CompilerMethodStats { 240 const Method *method; // Used as hash entry signature 241 int dalvikSize; // # of bytes for dalvik bytecodes 242 int compiledDalvikSize; // # of compiled dalvik bytecodes 243 int nativeSize; // # of bytes for produced native code 244 int attributes; // attribute vector 245 } CompilerMethodStats; 246 247 struct CompilationUnit; 248 struct BasicBlock; 249 struct SSARepresentation; 250 struct GrowableList; 251 struct JitEntry; 252 struct MIR; 253 254 bool dvmCompilerSetupCodeCache(void); 255 bool dvmCompilerArchInit(void); 256 void dvmCompilerArchDump(void); 257 bool dvmCompilerStartup(void); 258 void dvmCompilerShutdown(void); 259 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); 260 void *dvmCheckCodeCache(void *method); 261 CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method, 262 bool isCallee); 263 bool dvmCompilerCanIncludeThisInstruction(const Method *method, 264 const DecodedInstruction *insn); 265 bool dvmCompileMethod(struct CompilationUnit *cUnit, const Method *method, 266 JitTranslationInfo *info); 267 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts, 268 JitTranslationInfo *info, jmp_buf *bailPtr, int optHints); 269 void dvmCompilerDumpStats(void); 270 void dvmCompilerDrainQueue(void); 271 void dvmJitUnchainAll(void); 272 void dvmCompilerSortAndPrintTraceProfiles(void); 273 void dvmCompilerPerformSafePointChecks(void); 274 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit); 275 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit); 276 int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg); 277 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit); 278 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit); 279 void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit, 280 struct BasicBlock *bb); 281 void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit, 282 struct BasicBlock *bb); 283 void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit, 284 struct BasicBlock *bb); 285 void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit, 286 struct BasicBlock *bb); 287 char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn, char *note); 288 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit, 289 struct SSARepresentation *ssaRep); 290 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit, 291 void (*func)(struct CompilationUnit *, struct BasicBlock *)); 292 void dvmCompilerStateRefresh(void); 293 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, 294 const struct JitEntry *desc); 295 void *dvmCompilerGetInterpretTemplate(); 296 #endif /* _DALVIK_VM_COMPILER */ 297