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 */
dvmDebuggerOrProfilerActive(void)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 */
dvmJitDebuggerOrProfilerActive()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 */
dvmJitHideTranslation()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 */
dvmJitStayInPortableInterpreter()270 static inline bool dvmJitStayInPortableInterpreter()
271 {
272 return dvmJitHideTranslation() ||
273 (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater);
274 }
275 #endif
276
277 #endif /*_DALVIK_INTERP_DEFS*/
278