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 */
68 struct JitToInterpEntries {
69 void *dvmJitToInterpNormal;
70 void *dvmJitToInterpNoChain;
71 void *dvmJitToInterpPunt;
72 void *dvmJitToInterpSingleStep;
73 void *dvmJitToTraceSelect;
74 void *dvmJitToPatchPredictedChain;
75 };
76
77 #define JIT_TRACE_THRESH_FILTER_SIZE 16
78 #endif
79
80 /*
81 * Interpreter context, used when switching from one interpreter to
82 * another. We also tuck "mterp" state in here.
83 */
84 typedef struct InterpState {
85 /*
86 * To make some mterp state updates easier, "pc" and "fp" MUST come
87 * first and MUST appear in this order.
88 */
89 const u2* pc; // program counter
90 u4* fp; // frame pointer
91
92 JValue retval; // return value -- "out" only
93 const Method* method; // method being executed
94
95
96 /* ----------------------------------------------------------------------
97 * Mterp-only state
98 */
99 DvmDex* methodClassDex;
100 Thread* self;
101
102 /* housekeeping */
103 void* bailPtr;
104
105 /*
106 * These are available globally, from gDvm, or from another glue field
107 * (self/method). They're copied in here for speed.
108 */
109 const u1* interpStackEnd;
110 volatile int* pSelfSuspendCount;
111 #if defined(WITH_DEBUGGER)
112 volatile u1* pDebuggerActive;
113 #endif
114 #if defined(WITH_PROFILER)
115 volatile int* pActiveProfilers;
116 #endif
117 /* ----------------------------------------------------------------------
118 */
119
120 /*
121 * Interpreter switching.
122 */
123 InterpEntry entryPoint; // what to do when we start
124 int nextMode; // INTERP_STD, INTERP_DBG
125
126 #if defined(WITH_JIT)
127 /*
128 * Local copies of field from gDvm placed here for fast access
129 */
130 unsigned char* pJitProfTable;
131 JitState jitState;
132 void* jitResume;
133 u2* jitResumePC;
134 #endif
135
136 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
137 bool debugIsMethodEntry; // used for method entry event triggers
138 #endif
139 #if defined(WITH_TRACKREF_CHECKS)
140 int debugTrackedRefStart; // tracked refs from prior invocations
141 #endif
142
143 #if defined(WITH_JIT)
144 struct JitToInterpEntries jitToInterpEntries;
145
146 int currTraceRun;
147 int totalTraceLen; // Number of Dalvik insts in trace
148 const u2* currTraceHead; // Start of the trace we're building
149 const u2* currRunHead; // Start of run we're building
150 int currRunLen; // Length of run in 16-bit words
151 int lastThreshFilter;
152 const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
153 JitTraceRun trace[MAX_JIT_RUN_LEN];
154 #endif
155
156 } InterpState;
157
158 /*
159 * These are generated from InterpCore.h.
160 */
161 extern bool dvmInterpretDbg(Thread* self, InterpState* interpState);
162 extern bool dvmInterpretStd(Thread* self, InterpState* interpState);
163 #define INTERP_STD 0
164 #define INTERP_DBG 1
165
166 /*
167 * "mterp" interpreter.
168 */
169 extern bool dvmMterpStd(Thread* self, InterpState* interpState);
170
171 /*
172 * Get the "this" pointer from the current frame.
173 */
174 Object* dvmGetThisPtr(const Method* method, const u4* fp);
175
176 /*
177 * Verify that our tracked local references are valid.
178 */
179 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
180 int debugTrackedRefStart);
181
182 /*
183 * Process switch statement.
184 */
185 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
186 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
187
188 /*
189 * Process fill-array-data.
190 */
191 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
192 const u2* arrayData);
193
194 /*
195 * Find an interface method.
196 */
197 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
198 const Method* method, DvmDex* methodClassDex);
199
200 /*
201 * Determine if the debugger or profiler is currently active. Used when
202 * selecting which interpreter to start or switch to.
203 */
dvmDebuggerOrProfilerActive(void)204 static inline bool dvmDebuggerOrProfilerActive(void)
205 {
206 return gDvm.debuggerActive
207 #if defined(WITH_PROFILER)
208 || gDvm.activeProfilers != 0
209 #endif
210 ;
211 }
212
213 #if defined(WITH_JIT)
214 /*
215 * Determine if the jit, debugger or profiler is currently active. Used when
216 * selecting which interpreter to switch to.
217 */
dvmJitDebuggerOrProfilerActive(int jitState)218 static inline bool dvmJitDebuggerOrProfilerActive(int jitState)
219 {
220 return jitState != kJitOff
221 #if defined(WITH_PROFILER)
222 || gDvm.activeProfilers != 0
223 #endif
224 ||gDvm.debuggerActive;
225 }
226 #endif
227
228 #endif /*_DALVIK_INTERP_DEFS*/
229