• 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  * Stack frames, and uses thereof.
18  */
19 #ifndef _DALVIK_INTERP_STACK
20 #define _DALVIK_INTERP_STACK
21 
22 #include "jni.h"
23 #include <stdarg.h>
24 
25 
26 /*
27 Stack layout
28 
29 In what follows, the "top" of the stack is at a low position in memory,
30 and the "bottom" of the stack is in a high position (put more simply,
31 they grow downward).  They may be merged with the native stack at a
32 later date.  The interpreter assumes that they have a fixed size,
33 determined when the thread is created.
34 
35 Dalvik's registers (of which there can be up to 64K) map to the "ins"
36 (method arguments) and "locals" (local variables).  The "outs" (arguments
37 to called methods) are specified by the "invoke" operand.  The return
38 value, which is passed through the interpreter rather than on the stack,
39 is retrieved with a "move-result" instruction.
40 
41     Low addresses (0x00000000)
42 
43                      +- - - - - - - - -+
44                      -  out0           -
45                      +-----------------+  <-- stack ptr (top of stack)
46                      +  VM-specific    +
47                      +  internal goop  +
48                      +-----------------+  <-- curFrame: FP for cur function
49                      +  v0 == local0   +
50 +-----------------+  +-----------------+
51 +  out0           +  +  v1 == in0      +
52 +-----------------+  +-----------------+
53 +  out1           +  +  v2 == in1      +
54 +-----------------+  +-----------------+
55 +  VM-specific    +
56 +  internal goop  +
57 +-----------------+  <-- frame ptr (FP) for previous function
58 +  v0 == local0   +
59 +-----------------+
60 +  v1 == local1   +
61 +-----------------+
62 +  v2 == in0      +
63 +-----------------+
64 +  v3 == in1      +
65 +-----------------+
66 +  v4 == in2      +
67 +-----------------+
68 -                 -
69 -                 -
70 -                 -
71 +-----------------+  <-- interpStackStart
72 
73     High addresses (0xffffffff)
74 
75 Note the "ins" and "outs" overlap -- values pushed into the "outs" area
76 become the parameters to the called method.  The VM guarantees that there
77 will be enough room for all possible "outs" on the stack before calling
78 into a method.
79 
80 All "V registers" are 32 bits, and all stack entries are 32-bit aligned.
81 Registers are accessed as a positive offset from the frame pointer,
82 e.g. register v2 is fp[2].  64-bit quantities are stored in two adjacent
83 registers, addressed by the lower-numbered register, and are in host order.
84 64-bit quantities do not need to start in an even-numbered register.
85 
86 We push two stack frames on when calling an interpreted or native method
87 directly from the VM (e.g. invoking <clinit> or via reflection "invoke()").
88 The first is a "break" frame, which allows us to tell when a call return or
89 exception unroll has reached the VM call site.  Without the break frame the
90 stack might look like an uninterrupted series of interpreted method calls.
91 The second frame is for the method itself.
92 
93 The "break" frame is used as an alternative to adding additional fields
94 to the StackSaveArea struct itself.  They are recognized by having a
95 NULL method pointer.
96 
97 When calling a native method from interpreted code, the stack setup is
98 essentially identical to calling an interpreted method.  Because it's a
99 native method, though, there are never any "locals" or "outs".
100 
101 For native calls into JNI, we want to store a table of local references
102 on the stack.  The GC needs to scan them while the native code is running,
103 and we want to trivially discard them when the method returns.  See JNI.c
104 for a discussion of how this is managed.  In particular note that it is
105 possible to push additional call frames on without calling a method.
106 */
107 
108 
109 struct StackSaveArea;
110 typedef struct StackSaveArea StackSaveArea;
111 
112 //#define PAD_SAVE_AREA       /* help debug stack trampling */
113 
114 /*
115  * The VM-specific internal goop.
116  *
117  * The idea is to mimic a typical native stack frame, with copies of the
118  * saved PC and FP.  At some point we'd like to have interpreted and
119  * native code share the same stack, though this makes portability harder.
120  */
121 struct StackSaveArea {
122 #ifdef PAD_SAVE_AREA
123     u4          pad0, pad1, pad2;
124 #endif
125 
126 #ifdef EASY_GDB
127     /* make it easier to trek through stack frames in GDB */
128     StackSaveArea* prevSave;
129 #endif
130 
131     /* saved frame pointer for previous frame, or NULL if this is at bottom */
132     void*       prevFrame;
133 
134     /* saved program counter (from method in caller's frame) */
135     const u2*   savedPc;
136 
137     /* pointer to method we're *currently* executing; handy for exceptions */
138     const Method* method;
139 
140     union {
141         /* for JNI native methods: top of local reference storage */
142         Object**    localRefTop;
143 
144         /* for interpreted methods: saved current PC, for exception stack
145          * traces and debugger traces */
146         const u2*   currentPc;
147     } xtra;
148 
149 #ifdef PAD_SAVE_AREA
150     u4          pad3, pad4, pad5;
151 #endif
152 };
153 
154 /* move between the stack save area and the frame pointer */
155 #define SAVEAREA_FROM_FP(_fp)   ((StackSaveArea*)(_fp) -1)
156 #define FP_FROM_SAVEAREA(_save) ((void*) ((StackSaveArea*)(_save) +1))
157 
158 /* when calling a function, get a pointer to outs[0] */
159 #define OUTS_FROM_FP(_fp, _argCount) \
160     ((u4*) ((u1*)SAVEAREA_FROM_FP(_fp) - sizeof(u4) * (_argCount)))
161 
162 /* reserve this many bytes for handling StackOverflowError */
163 #define STACK_OVERFLOW_RESERVE  512
164 
165 /*
166  * Determine if the frame pointer points to a "break frame".
167  */
dvmIsBreakFrame(const u4 * fp)168 INLINE bool dvmIsBreakFrame(const u4* fp)
169 {
170     return SAVEAREA_FROM_FP(fp)->method == NULL;
171 }
172 
173 /*
174  * Initialize the interp stack (call this after allocating storage and
175  * setting thread->interpStackStart).
176  */
177 bool dvmInitInterpStack(Thread* thread, int stackSize);
178 
179 /*
180  * Push a native method frame directly onto the stack.  Used to push the
181  * "fake" native frames at the top of each thread stack.
182  */
183 bool dvmPushJNIFrame(Thread* thread, const Method* method);
184 
185 /*
186  * JNI local frame management.
187  */
188 bool dvmPushLocalFrame(Thread* thread, const Method* method);
189 bool dvmPopLocalFrame(Thread* thread);
190 
191 /*
192  * Call an interpreted method from native code.
193  *
194  * "obj" should be NULL for "direct" methods.
195  */
196 void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
197     JValue* pResult, va_list args);
198 void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
199     JValue* pResult, const jvalue* args);
200 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
201     JValue* pResult, ...);
202 
203 /*
204  * Invoke a method, using the specified arguments and return type, through
205  * a reflection interface.
206  *
207  * Deals with boxing/unboxing primitives and performs widening conversions.
208  *
209  * "obj" should be null for a static method.
210  *
211  * "params" and "returnType" come from the Method object, so we don't have
212  * to re-generate them from the method signature.  "returnType" should be
213  * NULL if we're invoking a constructor.
214  */
215 Object* dvmInvokeMethod(Object* invokeObj, const Method* meth,
216     ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
217     bool noAccessCheck);
218 
219 /*
220  * Determine the source file line number, given the program counter offset
221  * into the specified method.  Returns -2 for native methods, -1 if no
222  * match was found.
223  */
224 int dvmLineNumFromPC(const Method* method, u4 relPc);
225 
226 /*
227  * Given a frame pointer, compute the current call depth.  The value can be
228  * "exact" (a count of non-break frames) or "vague" (just subtracting
229  * pointers to give relative values).
230  */
231 int dvmComputeExactFrameDepth(const void* fp);
232 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp);
233 
234 /*
235  * Get the frame pointer for the caller's stack frame.
236  */
237 void* dvmGetCallerFP(const void* curFrame);
238 
239 /*
240  * Get the class of the method that called us.
241  */
242 ClassObject* dvmGetCallerClass(const void* curFrame);
243 
244 /*
245  * Get the caller's caller's class.  Pass in the current fp.
246  *
247  * This is used by e.g. java.lang.Class, which wants to know about the
248  * class loader of the method that called it.
249  */
250 ClassObject* dvmGetCaller2Class(const void* curFrame);
251 
252 /*
253  * Get the caller's caller's caller's class.  Pass in the current fp.
254  *
255  * This is used by e.g. java.lang.Class, which wants to know about the
256  * class loader of the method that called it.
257  */
258 ClassObject* dvmGetCaller3Class(const void* curFrame);
259 
260 /*
261  * Allocate and fill an array of method pointers representing the current
262  * stack trace (element 0 is current frame).
263  */
264 bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
265     int* pLength);
266 
267 /*
268  * Common handling for stack overflow.
269  */
270 void dvmHandleStackOverflow(Thread* self);
271 void dvmCleanupStackOverflow(Thread* self);
272 
273 /* debugging; dvmDumpThread() is probably a better starting point */
274 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread);
275 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread);
276 
277 #endif /*_DALVIK_INTERP_STACK*/
278