• 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  */
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