• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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