2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * Dalvik interpreter definitions. These are internal to the interpreter.
19 * This includes defines, types, function declarations, and inline functions
20 * that are common to all interpreter implementations.
22 * Functions and globals declared here are defined in Interp.c.
24 #ifndef _DALVIK_INTERP_DEFS
25 #define _DALVIK_INTERP_DEFS
29 * Specify the starting point when switching between interpreters.
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
36 kInterpEntryResume = 3, // Resume after single-step
42 * There are seven 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
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
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
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.
71 struct JitToInterpEntries {
72 void *dvmJitToInterpNormal;
73 void *dvmJitToInterpNoChain;
74 void *dvmJitToInterpPunt;
75 void *dvmJitToInterpSingleStep;
76 void *dvmJitToInterpTraceSelectNoChain;
77 void *dvmJitToInterpTraceSelect;
78 #if defined(WITH_SELF_VERIFICATION)
79 void *dvmJitToInterpBackwardBranch;
84 * Size of save area for callee-save FP regs, which are not automatically
85 * saved by interpreter main because it doesn't use them (but Jit'd code
86 * may). Save/restore routine is defined by target, and size should
87 * be >= max needed by any target.
89 #define JIT_CALLEE_SAVE_DOUBLE_COUNT 8
91 /* Number of entries in the 2nd level JIT profiler filter cache */
92 #define JIT_TRACE_THRESH_FILTER_SIZE 32
93 /* Number of low dalvik pc address bits to include in 2nd level filter key */
94 #define JIT_TRACE_THRESH_FILTER_PC_BITS 4
98 * Interpreter context, used when switching from one interpreter to
99 * another. We also tuck "mterp" state in here.
101 typedef struct InterpState {
103 * To make some mterp state updates easier, "pc" and "fp" MUST come
104 * first and MUST appear in this order.
106 const u2* pc; // program counter
107 u4* fp; // frame pointer
109 JValue retval; // return value -- "out" only
110 const Method* method; // method being executed
113 /* ----------------------------------------------------------------------
116 DvmDex* methodClassDex;
123 * These are available globally, from gDvm, or from another glue field
124 * (self/method). They're copied in here for speed.
126 /* copy of self->interpStackEnd */
127 const u1* interpStackEnd;
128 /* points at self->suspendCount */
129 volatile int* pSelfSuspendCount;
130 /* Biased base of GC's card table */
132 /* points at gDvm.debuggerActive, or NULL if debugger not enabled */
133 volatile u1* pDebuggerActive;
134 /* points at gDvm.activeProfilers */
135 volatile int* pActiveProfilers;
136 /* ----------------------------------------------------------------------
140 * Interpreter switching.
142 InterpEntry entryPoint; // what to do when we start
143 int nextMode; // INTERP_STD, INTERP_DBG
145 #if defined(WITH_JIT)
147 * Local copies of field from gDvm placed here for fast access
149 unsigned char* pJitProfTable;
151 const void* jitResumeNPC; // Native PC of compiled code
152 const u2* jitResumeDPC; // Dalvik PC corresponding to NPC
155 * ppJitProfTable holds the address of gDvmJit.pJitProfTable, which
156 * doubles as an on/off switch for the Jit. Because a change in
157 * the value of gDvmJit.pJitProfTable isn't reflected in the cached
158 * copy above (pJitProfTable), we need to periodically refresh it.
159 * ppJitProfTable is used for that purpose.
161 unsigned char** ppJitProfTable; // Used to refresh pJitProfTable
162 int icRechainCount; // Count down to next rechain request
163 const void* pProfileCountdown; // Address of profile countdown timer
165 struct JitToInterpEntries jitToInterpEntries;
167 const void* jitCacheStart; // Code cache boundaries
168 const void* jitCacheEnd;
171 int totalTraceLen; // Number of Dalvik insts in trace
172 const u2* currTraceHead; // Start of the trace we're building
173 const u2* currRunHead; // Start of run we're building
174 int currRunLen; // Length of run in 16-bit words
175 int lastThreshFilter;
176 const u2* lastPC; // Stage the PC first for the threaded interpreter
177 intptr_t threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
178 JitTraceRun trace[MAX_JIT_RUN_LEN];
179 double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
182 bool debugIsMethodEntry; // used for method entry event triggers
183 #if defined(WITH_TRACKREF_CHECKS)
184 int debugTrackedRefStart; // tracked refs from prior invocations
191 * These are generated from InterpCore.h.
193 extern bool dvmInterpretDbg(Thread* self, InterpState* interpState);
194 extern bool dvmInterpretStd(Thread* self, InterpState* interpState);
199 * "mterp" interpreter.
201 extern bool dvmMterpStd(Thread* self, InterpState* interpState);
204 * Get the "this" pointer from the current frame.
206 Object* dvmGetThisPtr(const Method* method, const u4* fp);
209 * Verify that our tracked local references are valid.
211 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
212 int debugTrackedRefStart);
215 * Process switch statement.
217 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
218 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
221 * Process fill-array-data.
223 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
224 const u2* arrayData);
227 * Find an interface method.
229 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
230 const Method* method, DvmDex* methodClassDex);
233 * Determine if the debugger or profiler is currently active. Used when
234 * selecting which interpreter to start or switch to.
236 static inline bool dvmDebuggerOrProfilerActive(void)
238 bool result = gDvm.debuggerActive;
239 #if !defined(WITH_INLINE_PROFILING)
240 result = result || (gDvm.activeProfilers != 0);
245 #if defined(WITH_JIT)
247 * Determine if the jit, debugger or profiler is currently active. Used when
248 * selecting which interpreter to switch to.
250 static inline bool dvmJitDebuggerOrProfilerActive()
252 bool result = (gDvmJit.pProfTable != NULL) || gDvm.debuggerActive;
253 #if !defined(WITH_INLINE_PROFILING)
254 result = result || (gDvm.activeProfilers != 0);
260 * Hide the translations and stick with the interpreter as long as one of the
261 * following conditions is true.
263 static inline bool dvmJitHideTranslation()
265 return (gDvm.sumThreadSuspendCount != 0) ||
266 (gDvmJit.codeCacheFull == true) ||
267 (gDvmJit.pProfTable == NULL);
271 * The fast and debug interpreter may be doing ping-pong without making forward
272 * progress if the same trace building request sent upon entering the fast
273 * interpreter is rejected immediately by the debug interpreter. Use the
274 * following function to poll the rejection reasons and stay in the debug
275 * interpreter until they are cleared. This will guarantee forward progress
276 * in the extreme corner cases (eg set compiler threashold to 1).
278 static inline bool dvmJitStayInPortableInterpreter()
280 return dvmJitHideTranslation() ||
281 (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater);
286 #endif /*_DALVIK_INTERP_DEFS*/