1 /* 2 * Copyright (C) 2008 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 * Dalvik interpreter definitions. These are internal to the interpreter. 18 * 19 * This includes defines, types, function declarations, and inline functions 20 * that are common to all interpreter implementations. 21 * 22 * Functions and globals declared here are defined in Interp.c. 23 */ 24 #ifndef _DALVIK_INTERP_DEFS 25 #define _DALVIK_INTERP_DEFS 26 27 28 /* 29 * Specify the starting point when switching between interpreters. 30 */ 31 typedef enum InterpEntry { 32 kInterpEntryInstr = 0, // continue to next instruction 33 kInterpEntryReturn = 1, // jump to method return 34 kInterpEntryThrow = 2, // jump to exception throw 35 #if defined(WITH_JIT) 36 kInterpEntryResume = 3, // Resume after single-step 37 #endif 38 } InterpEntry; 39 40 #if defined(WITH_JIT) 41 /* 42 * There are six entry points from the compiled code to the interpreter: 43 * 1) dvmJitToInterpNormal: find if there is a corresponding compilation for 44 * the new dalvik PC. If so, chain the originating compilation with the 45 * target then jump to it. 46 * 2) dvmJitToInterpInvokeNoChain: similar to 1) but don't chain. This is 47 * for handling 1-to-many mappings like virtual method call and 48 * packed switch. 49 * 3) dvmJitToInterpPunt: use the fast interpreter to execute the next 50 * instruction(s) and stay there as long as it is appropriate to return 51 * to the compiled land. This is used when the jit'ed code is about to 52 * throw an exception. 53 * 4) dvmJitToInterpSingleStep: use the portable interpreter to execute the 54 * next instruction only and return to pre-specified location in the 55 * compiled code to resume execution. This is mainly used as debugging 56 * feature to bypass problematic opcode implementations without 57 * disturbing the trace formation. 58 * 5) dvmJitToTraceSelect: if there is a single exit from a translation that 59 * has already gone hot enough to be translated, we should assume that 60 * the exit point should also be translated (this is a common case for 61 * invokes). This trace exit will first check for a chaining 62 * opportunity, and if none is available will switch to the debug 63 * interpreter immediately for trace selection (as if threshold had 64 * just been reached). 65 * 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site 66 * to a predicted callee. 67 * 7) dvmJitToBackwardBranch: (WITH_SELF_VERIFICATION ONLY) special case of 1) 68 * and 5). This is used instead if the ending branch of the trace jumps back 69 * into the same basic block. 70 */ 71 struct JitToInterpEntries { 72 void *dvmJitToInterpNormal; 73 void *dvmJitToInterpNoChain; 74 void *dvmJitToInterpPunt; 75 void *dvmJitToInterpSingleStep; 76 void *dvmJitToInterpTraceSelectNoChain; 77 void *dvmJitToInterpTraceSelect; 78 void *dvmJitToPatchPredictedChain; 79 #if defined(WITH_SELF_VERIFICATION) 80 void *dvmJitToInterpBackwardBranch; 81 #endif 82 }; 83 84 /* 85 * Size of save area for callee-save FP regs, which are not automatically 86 * saved by interpreter main because it doesn't use them (but Jit'd code 87 * may). Save/restore routine is defined by target, and size should 88 * be >= max needed by any target. 89 */ 90 #define JIT_CALLEE_SAVE_DOUBLE_COUNT 8 91 92 /* Number of entries in the 2nd level JIT profiler filter cache */ 93 #define JIT_TRACE_THRESH_FILTER_SIZE 32 94 /* Number of low dalvik pc address bits to include in 2nd level filter key */ 95 #define JIT_TRACE_THRESH_FILTER_PC_BITS 4 96 #endif 97 98 /* 99 * Interpreter context, used when switching from one interpreter to 100 * another. We also tuck "mterp" state in here. 101 */ 102 typedef struct InterpState { 103 /* 104 * To make some mterp state updates easier, "pc" and "fp" MUST come 105 * first and MUST appear in this order. 106 */ 107 const u2* pc; // program counter 108 u4* fp; // frame pointer 109 110 JValue retval; // return value -- "out" only 111 const Method* method; // method being executed 112 113 114 /* ---------------------------------------------------------------------- 115 * Mterp-only state 116 */ 117 DvmDex* methodClassDex; 118 Thread* self; 119 120 /* housekeeping */ 121 void* bailPtr; 122 123 /* 124 * These are available globally, from gDvm, or from another glue field 125 * (self/method). They're copied in here for speed. 126 */ 127 /* copy of self->interpStackEnd */ 128 const u1* interpStackEnd; 129 /* points at self->suspendCount */ 130 volatile int* pSelfSuspendCount; 131 /* Biased base of GC's card table */ 132 u1* cardTable; 133 /* points at gDvm.debuggerActive, or NULL if debugger not enabled */ 134 volatile u1* pDebuggerActive; 135 /* points at gDvm.activeProfilers */ 136 volatile int* pActiveProfilers; 137 /* ---------------------------------------------------------------------- 138 */ 139 140 /* 141 * Interpreter switching. 142 */ 143 InterpEntry entryPoint; // what to do when we start 144 int nextMode; // INTERP_STD, INTERP_DBG 145 146 #if defined(WITH_JIT) 147 /* 148 * Local copies of field from gDvm placed here for fast access 149 */ 150 unsigned char* pJitProfTable; 151 JitState jitState; 152 const void* jitResumeNPC; // Native PC of compiled code 153 const u2* jitResumeDPC; // Dalvik PC corresponding to NPC 154 int jitThreshold; 155 /* 156 * ppJitProfTable holds the address of gDvmJit.pJitProfTable, which 157 * doubles as an on/off switch for the Jit. Because a change in 158 * the value of gDvmJit.pJitProfTable isn't reflected in the cached 159 * copy above (pJitProfTable), we need to periodically refresh it. 160 * ppJitProfTable is used for that purpose. 161 */ 162 unsigned char** ppJitProfTable; // Used to refresh pJitProfTable 163 int icRechainCount; // Count down to next rechain request 164 #endif 165 166 bool debugIsMethodEntry; // used for method entry event triggers 167 #if defined(WITH_TRACKREF_CHECKS) 168 int debugTrackedRefStart; // tracked refs from prior invocations 169 #endif 170 171 #if defined(WITH_JIT) 172 struct JitToInterpEntries jitToInterpEntries; 173 174 int currTraceRun; 175 int totalTraceLen; // Number of Dalvik insts in trace 176 const u2* currTraceHead; // Start of the trace we're building 177 const u2* currRunHead; // Start of run we're building 178 int currRunLen; // Length of run in 16-bit words 179 int lastThreshFilter; 180 const u2* lastPC; // Stage the PC first for the threaded interpreter 181 intptr_t threshFilter[JIT_TRACE_THRESH_FILTER_SIZE]; 182 JitTraceRun trace[MAX_JIT_RUN_LEN]; 183 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT]; 184 #endif 185 186 } InterpState; 187 188 /* 189 * These are generated from InterpCore.h. 190 */ 191 extern bool dvmInterpretDbg(Thread* self, InterpState* interpState); 192 extern bool dvmInterpretStd(Thread* self, InterpState* interpState); 193 #define INTERP_STD 0 194 #define INTERP_DBG 1 195 196 /* 197 * "mterp" interpreter. 198 */ 199 extern bool dvmMterpStd(Thread* self, InterpState* interpState); 200 201 /* 202 * Get the "this" pointer from the current frame. 203 */ 204 Object* dvmGetThisPtr(const Method* method, const u4* fp); 205 206 /* 207 * Verify that our tracked local references are valid. 208 */ 209 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method, 210 int debugTrackedRefStart); 211 212 /* 213 * Process switch statement. 214 */ 215 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal); 216 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal); 217 218 /* 219 * Process fill-array-data. 220 */ 221 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject, 222 const u2* arrayData); 223 224 /* 225 * Find an interface method. 226 */ 227 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx, 228 const Method* method, DvmDex* methodClassDex); 229 230 /* 231 * Determine if the debugger or profiler is currently active. Used when 232 * selecting which interpreter to start or switch to. 233 */ 234 static inline bool dvmDebuggerOrProfilerActive(void) 235 { 236 return gDvm.debuggerActive || gDvm.activeProfilers != 0; 237 } 238 239 #if defined(WITH_JIT) 240 /* 241 * Determine if the jit, debugger or profiler is currently active. Used when 242 * selecting which interpreter to switch to. 243 */ 244 static inline bool dvmJitDebuggerOrProfilerActive() 245 { 246 return gDvmJit.pProfTable != NULL 247 || gDvm.activeProfilers != 0 248 || gDvm.debuggerActive; 249 } 250 251 /* 252 * Hide the translations and stick with the interpreter as long as one of the 253 * following conditions is true. 254 */ 255 static inline bool dvmJitHideTranslation() 256 { 257 return (gDvm.sumThreadSuspendCount != 0) || 258 (gDvmJit.codeCacheFull == true) || 259 (gDvmJit.pProfTable == NULL); 260 } 261 262 /* 263 * The fast and debug interpreter may be doing ping-pong without making forward 264 * progress if the same trace building request sent upon entering the fast 265 * interpreter is rejected immediately by the debug interpreter. Use the 266 * following function to poll the rejection reasons and stay in the debug 267 * interpreter until they are cleared. This will guarantee forward progress 268 * in the extreme corner cases (eg set compiler threashold to 1). 269 */ 270 static inline bool dvmJitStayInPortableInterpreter() 271 { 272 return dvmJitHideTranslation() || 273 (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater); 274 } 275 #endif 276 277 #endif /*_DALVIK_INTERP_DEFS*/ 278