OSDN Git Service

am af5aa1f4: Don\'t treat dvmJitToPatchPredictedChain as a Jit-to-Interp entry point.
[android-x86/dalvik.git] / vm / interp / InterpDefs.h
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 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
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 #if defined(WITH_SELF_VERIFICATION)
79     void *dvmJitToInterpBackwardBranch;
80 #endif
81 };
82
83 /*
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.
88  */
89 #define JIT_CALLEE_SAVE_DOUBLE_COUNT 8
90
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
95 #endif
96
97 /*
98  * Interpreter context, used when switching from one interpreter to
99  * another.  We also tuck "mterp" state in here.
100  */
101 typedef struct InterpState {
102     /*
103      * To make some mterp state updates easier, "pc" and "fp" MUST come
104      * first and MUST appear in this order.
105      */
106     const u2*   pc;                     // program counter
107     u4*         fp;                     // frame pointer
108
109     JValue      retval;                 // return value -- "out" only
110     const Method* method;               // method being executed
111
112
113     /* ----------------------------------------------------------------------
114      * Mterp-only state
115      */
116     DvmDex*         methodClassDex;
117     Thread*         self;
118
119     /* housekeeping */
120     void*           bailPtr;
121
122     /*
123      * These are available globally, from gDvm, or from another glue field
124      * (self/method).  They're copied in here for speed.
125      */
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 */
131     u1*             cardTable;
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     /* ----------------------------------------------------------------------
137      */
138
139     /*
140      * Interpreter switching.
141      */
142     InterpEntry entryPoint;             // what to do when we start
143     int         nextMode;               // INTERP_STD, INTERP_DBG
144
145 #if defined(WITH_JIT)
146     /*
147      * Local copies of field from gDvm placed here for fast access
148      */
149     unsigned char*     pJitProfTable;
150     JitState           jitState;
151     const void*        jitResumeNPC;    // Native PC of compiled code
152     const u2*          jitResumeDPC;    // Dalvik PC corresponding to NPC
153     int                jitThreshold;
154     /*
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.
160      */
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
164
165     struct JitToInterpEntries jitToInterpEntries;
166
167     const void*        jitCacheStart;  // Code cache boundaries
168     const void*        jitCacheEnd;
169
170     int currTraceRun;
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];
180 #endif
181
182     bool        debugIsMethodEntry;     // used for method entry event triggers
183 #if defined(WITH_TRACKREF_CHECKS)
184     int         debugTrackedRefStart;   // tracked refs from prior invocations
185 #endif
186
187
188 } InterpState;
189
190 /*
191  * These are generated from InterpCore.h.
192  */
193 extern bool dvmInterpretDbg(Thread* self, InterpState* interpState);
194 extern bool dvmInterpretStd(Thread* self, InterpState* interpState);
195 #define INTERP_STD 0
196 #define INTERP_DBG 1
197
198 /*
199  * "mterp" interpreter.
200  */
201 extern bool dvmMterpStd(Thread* self, InterpState* interpState);
202
203 /*
204  * Get the "this" pointer from the current frame.
205  */
206 Object* dvmGetThisPtr(const Method* method, const u4* fp);
207
208 /*
209  * Verify that our tracked local references are valid.
210  */
211 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
212     int debugTrackedRefStart);
213
214 /*
215  * Process switch statement.
216  */
217 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
218 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
219
220 /*
221  * Process fill-array-data.
222  */
223 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
224                                   const u2* arrayData);
225
226 /*
227  * Find an interface method.
228  */
229 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
230     const Method* method, DvmDex* methodClassDex);
231
232 /*
233  * Determine if the debugger or profiler is currently active.  Used when
234  * selecting which interpreter to start or switch to.
235  */
236 static inline bool dvmDebuggerOrProfilerActive(void)
237 {
238     bool result = gDvm.debuggerActive;
239 #if !defined(WITH_INLINE_PROFILING)
240     result = result || (gDvm.activeProfilers != 0);
241 #endif
242     return result;
243 }
244
245 #if defined(WITH_JIT)
246 /*
247  * Determine if the jit, debugger or profiler is currently active.  Used when
248  * selecting which interpreter to switch to.
249  */
250 static inline bool dvmJitDebuggerOrProfilerActive()
251 {
252     bool result = (gDvmJit.pProfTable != NULL) || gDvm.debuggerActive;
253 #if !defined(WITH_INLINE_PROFILING)
254     result = result || (gDvm.activeProfilers != 0);
255 #endif
256     return result;
257 }
258
259 /*
260  * Hide the translations and stick with the interpreter as long as one of the
261  * following conditions is true.
262  */
263 static inline bool dvmJitHideTranslation()
264 {
265     return (gDvm.sumThreadSuspendCount != 0) ||
266            (gDvmJit.codeCacheFull == true) ||
267            (gDvmJit.pProfTable == NULL);
268 }
269
270 /*
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).
277  */
278 static inline bool dvmJitStayInPortableInterpreter()
279 {
280     return dvmJitHideTranslation() ||
281            (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater);
282 }
283
284 #endif
285
286 #endif /*_DALVIK_INTERP_DEFS*/