| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 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 | |
| Ben Cheng | 3367245 | 2010-01-12 14:59:30 -0800 | [diff] [blame] | 17 | #include <Thread.h> |
| Bill Buzbee | fc519dc | 2010-03-06 23:30:57 -0800 | [diff] [blame] | 18 | #include <setjmp.h> |
| Ben Cheng | 3367245 | 2010-01-12 14:59:30 -0800 | [diff] [blame] | 19 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 20 | #ifndef _DALVIK_VM_COMPILER |
| 21 | #define _DALVIK_VM_COMPILER |
| 22 | |
| Ben Cheng | dca7143 | 2010-03-16 16:04:11 -0700 | [diff] [blame] | 23 | /* |
| 24 | * Uncomment the following to enable JIT signature breakpoint |
| 25 | * #define SIGNATURE_BREAKPOINT |
| 26 | */ |
| 27 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 28 | #define COMPILER_WORK_QUEUE_SIZE 100 |
| Ben Cheng | c3b92b2 | 2010-01-26 16:46:15 -0800 | [diff] [blame] | 29 | #define COMPILER_IC_PATCH_QUEUE_SIZE 64 |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 30 | |
| Ben Cheng | b88ec3c | 2010-05-17 12:50:33 -0700 | [diff] [blame] | 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 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 42 | #define COMPILER_TRACED(X) |
| 43 | #define COMPILER_TRACEE(X) |
| 44 | #define COMPILER_TRACE_CHAINING(X) |
| 45 | |
| Ben Cheng | b88ec3c | 2010-05-17 12:50:33 -0700 | [diff] [blame] | 46 | /* Macro to change the permissions applied to a chunk of the code cache */ |
| Ben Cheng | b88ec3c | 2010-05-17 12:50:33 -0700 | [diff] [blame] | 47 | #define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC) |
| 48 | #define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE) |
| Ben Cheng | b88ec3c | 2010-05-17 12:50:33 -0700 | [diff] [blame] | 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 | |
| Ben Cheng | 34dc796 | 2010-08-26 14:56:31 -0700 | [diff] [blame] | 68 | #define SINGLE_STEP_OP(opcode) \ |
| 69 | (gDvmJit.includeSelectedOp != \ |
| 70 | ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0)) |
| 71 | |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 72 | typedef enum JitInstructionSetType { |
| 73 | DALVIK_JIT_NONE = 0, |
| 74 | DALVIK_JIT_ARM, |
| 75 | DALVIK_JIT_THUMB, |
| 76 | DALVIK_JIT_THUMB2, |
| buzbee | 7520ee7 | 2010-09-17 16:01:49 -0700 | [diff] [blame] | 77 | DALVIK_JIT_IA32 |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 78 | } JitInstructionSetType; |
| 79 | |
| 80 | /* Description of a compiled trace. */ |
| 81 | typedef struct JitTranslationInfo { |
| Ben Cheng | ccd6c01 | 2009-10-15 14:52:45 -0700 | [diff] [blame] | 82 | void *codeAddress; |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 83 | JitInstructionSetType instructionSet; |
| buzbee | 2e152ba | 2010-12-15 16:32:35 -0800 | [diff] [blame] | 84 | int profileCodeSize; |
| Ben Cheng | 60c24f4 | 2010-01-04 12:29:56 -0800 | [diff] [blame] | 85 | bool discardResult; // Used for debugging divergence and IC patching |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 86 | bool methodCompilationAborted; // Cannot compile the whole method |
| Ben Cheng | 3367245 | 2010-01-12 14:59:30 -0800 | [diff] [blame] | 87 | Thread *requestingThread; // For debugging purpose |
| buzbee | 18fba34 | 2011-01-19 15:31:15 -0800 | [diff] [blame] | 88 | int cacheVersion; // Used to identify stale trace requests |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 89 | } JitTranslationInfo; |
| 90 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 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) |
| Ben Cheng | ccd6c01 | 2009-10-15 14:52:45 -0700 | [diff] [blame] | 95 | kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s) |
| buzbee | 2e152ba | 2010-12-15 16:32:35 -0800 | [diff] [blame] | 96 | kWorkOrderProfileMode = 4, // Change profiling mode |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 97 | } WorkOrderKind; |
| 98 | |
| 99 | typedef struct CompilerWorkOrder { |
| 100 | const u2* pc; |
| 101 | WorkOrderKind kind; |
| 102 | void* info; |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 103 | JitTranslationInfo result; |
| Bill Buzbee | fc519dc | 2010-03-06 23:30:57 -0800 | [diff] [blame] | 104 | jmp_buf *bailPtr; |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 105 | } CompilerWorkOrder; |
| 106 | |
| Ben Cheng | c3b92b2 | 2010-01-26 16:46:15 -0800 | [diff] [blame] | 107 | /* Chain cell for predicted method invocation */ |
| 108 | typedef struct PredictedChainingCell { |
| 109 | u4 branch; /* Branch to chained destination */ |
| Ben Cheng | b88ec3c | 2010-05-17 12:50:33 -0700 | [diff] [blame] | 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 */ |
| Ben Cheng | c3b92b2 | 2010-01-26 16:46:15 -0800 | [diff] [blame] | 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 | } ICPatchWorkOrder; |
| 120 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 121 | /* |
| 122 | * Trace description as will appear in the translation cache. Note |
| 123 | * flexible array at end, as these will be of variable size. To |
| 124 | * conserve space in the translation cache, total length of JitTraceRun |
| 125 | * array must be recomputed via seqential scan if needed. |
| 126 | */ |
| 127 | typedef struct { |
| 128 | const Method* method; |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 129 | JitTraceRun trace[0]; // Variable-length trace descriptors |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 130 | } JitTraceDescription; |
| 131 | |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 132 | typedef enum JitMethodAttributes { |
| 133 | kIsCallee = 0, /* Code is part of a callee (invoked by a hot trace) */ |
| 134 | kIsHot, /* Code is part of a hot trace */ |
| 135 | kIsLeaf, /* Method is leaf */ |
| 136 | kIsEmpty, /* Method is empty */ |
| 137 | kIsThrowFree, /* Method doesn't throw */ |
| 138 | kIsGetter, /* Method fits the getter pattern */ |
| 139 | kIsSetter, /* Method fits the setter pattern */ |
| Ben Cheng | cfdeca3 | 2011-01-14 11:36:46 -0800 | [diff] [blame] | 140 | kCannotCompile, /* Method cannot be compiled */ |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 141 | } JitMethodAttributes; |
| 142 | |
| 143 | #define METHOD_IS_CALLEE (1 << kIsCallee) |
| 144 | #define METHOD_IS_HOT (1 << kIsHot) |
| 145 | #define METHOD_IS_LEAF (1 << kIsLeaf) |
| 146 | #define METHOD_IS_EMPTY (1 << kIsEmpty) |
| 147 | #define METHOD_IS_THROW_FREE (1 << kIsThrowFree) |
| 148 | #define METHOD_IS_GETTER (1 << kIsGetter) |
| 149 | #define METHOD_IS_SETTER (1 << kIsSetter) |
| Ben Cheng | cfdeca3 | 2011-01-14 11:36:46 -0800 | [diff] [blame] | 150 | #define METHOD_CANNOT_COMPILE (1 << kCannotCompile) |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 151 | |
| Ben Cheng | 4a41958 | 2010-08-04 13:23:09 -0700 | [diff] [blame] | 152 | /* Vectors to provide optimization hints */ |
| 153 | typedef enum JitOptimizationHints { |
| 154 | kJitOptNoLoop = 0, // Disable loop formation/optimization |
| 155 | } JitOptimizationHints; |
| 156 | |
| 157 | #define JIT_OPT_NO_LOOP (1 << kJitOptNoLoop) |
| 158 | |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 159 | /* Customized node traversal orders for different needs */ |
| 160 | typedef enum DataFlowAnalysisMode { |
| 161 | kAllNodes = 0, // All nodes |
| 162 | kReachableNodes, // All reachable nodes |
| 163 | kPreOrderDFSTraversal, // Depth-First-Search / Pre-Order |
| 164 | kPostOrderDFSTraversal, // Depth-First-Search / Post-Order |
| 165 | kPostOrderDOMTraversal, // Dominator tree / Post-Order |
| 166 | } DataFlowAnalysisMode; |
| 167 | |
| Ben Cheng | 8b258bf | 2009-06-24 17:27:07 -0700 | [diff] [blame] | 168 | typedef struct CompilerMethodStats { |
| 169 | const Method *method; // Used as hash entry signature |
| 170 | int dalvikSize; // # of bytes for dalvik bytecodes |
| 171 | int compiledDalvikSize; // # of compiled dalvik bytecodes |
| 172 | int nativeSize; // # of bytes for produced native code |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 173 | int attributes; // attribute vector |
| Ben Cheng | 8b258bf | 2009-06-24 17:27:07 -0700 | [diff] [blame] | 174 | } CompilerMethodStats; |
| 175 | |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 176 | struct CompilationUnit; |
| 177 | struct BasicBlock; |
| 178 | struct SSARepresentation; |
| 179 | struct GrowableList; |
| 180 | struct JitEntry; |
| 181 | struct MIR; |
| 182 | |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 183 | bool dvmCompilerSetupCodeCache(void); |
| 184 | bool dvmCompilerArchInit(void); |
| 185 | void dvmCompilerArchDump(void); |
| 186 | bool dvmCompilerStartup(void); |
| 187 | void dvmCompilerShutdown(void); |
| Bill Buzbee | 1b3da59 | 2011-02-03 07:38:22 -0800 | [diff] [blame] | 188 | void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 189 | bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info); |
| 190 | void *dvmCheckCodeCache(void *method); |
| Ben Cheng | 7a2697d | 2010-06-07 13:44:23 -0700 | [diff] [blame] | 191 | CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method, |
| 192 | bool isCallee); |
| 193 | bool dvmCompilerCanIncludeThisInstruction(const Method *method, |
| 194 | const DecodedInstruction *insn); |
| Ben Cheng | cfdeca3 | 2011-01-14 11:36:46 -0800 | [diff] [blame] | 195 | bool dvmCompileMethod(const Method *method, JitTranslationInfo *info); |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 196 | bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts, |
| Ben Cheng | 4a41958 | 2010-08-04 13:23:09 -0700 | [diff] [blame] | 197 | JitTranslationInfo *info, jmp_buf *bailPtr, int optHints); |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 198 | void dvmCompilerDumpStats(void); |
| 199 | void dvmCompilerDrainQueue(void); |
| Bill Buzbee | 46cd5b6 | 2009-06-05 15:36:06 -0700 | [diff] [blame] | 200 | void dvmJitUnchainAll(void); |
| Bill Buzbee | 716f120 | 2009-07-23 13:22:09 -0700 | [diff] [blame] | 201 | void dvmCompilerSortAndPrintTraceProfiles(void); |
| Carl Shapiro | 3f349af | 2010-02-25 15:47:08 -0800 | [diff] [blame] | 202 | void dvmCompilerPerformSafePointChecks(void); |
| Ben Cheng | cfdeca3 | 2011-01-14 11:36:46 -0800 | [diff] [blame] | 203 | void dvmCompilerInlineMIR(struct CompilationUnit *cUnit, |
| 204 | JitTranslationInfo *info); |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 205 | void dvmInitializeSSAConversion(struct CompilationUnit *cUnit); |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 206 | int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg); |
| Ben Cheng | 4a41958 | 2010-08-04 13:23:09 -0700 | [diff] [blame] | 207 | bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit); |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 208 | void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit); |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 209 | bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit, |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 210 | struct BasicBlock *bb); |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 211 | bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit, |
| 212 | struct BasicBlock *bb); |
| 213 | bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit, |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 214 | struct BasicBlock *bb); |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 215 | bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit, |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 216 | struct BasicBlock *bb); |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 217 | /* Clear the visited flag for each BB */ |
| 218 | bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit, |
| 219 | struct BasicBlock *bb); |
| 220 | char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn, |
| 221 | char *note); |
| 222 | char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit, |
| 223 | const struct MIR *mir); |
| Ben Cheng | 4238ec2 | 2009-08-24 16:32:22 -0700 | [diff] [blame] | 224 | char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit, |
| 225 | struct SSARepresentation *ssaRep); |
| 226 | void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit, |
| Ben Cheng | 0060307 | 2010-10-28 11:13:58 -0700 | [diff] [blame] | 227 | bool (*func)(struct CompilationUnit *, struct BasicBlock *), |
| 228 | DataFlowAnalysisMode dfaMode, |
| 229 | bool isIterative); |
| 230 | void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit); |
| Bill Buzbee | 06bb839 | 2010-01-31 18:53:15 -0800 | [diff] [blame] | 231 | void dvmCompilerStateRefresh(void); |
| Ben Cheng | 88a0f97 | 2010-02-24 15:00:40 -0800 | [diff] [blame] | 232 | JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc, |
| 233 | const struct JitEntry *desc); |
| Bill Buzbee | bd04724 | 2010-05-13 13:02:53 -0700 | [diff] [blame] | 234 | void *dvmCompilerGetInterpretTemplate(); |
| Bill Buzbee | 1b3da59 | 2011-02-03 07:38:22 -0800 | [diff] [blame] | 235 | JitInstructionSetType dvmCompilerGetInterpretTemplateSet(); |
| Ben Cheng | d72564c | 2011-02-08 17:09:25 -0800 | [diff] [blame] | 236 | u8 dvmGetRegResourceMask(int reg); |
| Ben Cheng | ba4fc8b | 2009-06-01 13:00:29 -0700 | [diff] [blame] | 237 | #endif /* _DALVIK_VM_COMPILER */ |