blob: f2a481b290b1389b0a821e81b90704e6c7024daf [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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/*
27Stack layout
28
29In what follows, the "top" of the stack is at a low position in memory,
30and the "bottom" of the stack is in a high position (put more simply,
31they grow downward). They may be merged with the native stack at a
32later date. The interpreter assumes that they have a fixed size,
33determined when the thread is created.
34
35Dalvik's registers (of which there can be up to 64K) map to the "ins"
36(method arguments) and "locals" (local variables). The "outs" (arguments
37to called methods) are specified by the "invoke" operand. The return
38value, which is passed through the interpreter rather than on the stack,
39is 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
75Note the "ins" and "outs" overlap -- values pushed into the "outs" area
76become the parameters to the called method. The VM guarantees that there
77will be enough room for all possible "outs" on the stack before calling
78into a method.
79
80All "V registers" are 32 bits, and all stack entries are 32-bit aligned.
81Registers are accessed as a positive offset from the frame pointer,
82e.g. register v2 is fp[2]. 64-bit quantities are stored in two adjacent
83registers, addressed by the lower-numbered register, and are in host order.
8464-bit quantities do not need to start in an even-numbered register.
85
86We push two stack frames on when calling an interpreted or native method
87directly from the VM (e.g. invoking <clinit> or via reflection "invoke()").
88The first is a "break" frame, which allows us to tell when a call return or
89exception unroll has reached the VM call site. Without the break frame the
90stack might look like an uninterrupted series of interpreted method calls.
91The second frame is for the method itself.
92
93The "break" frame is used as an alternative to adding additional fields
94to the StackSaveArea struct itself. They are recognized by having a
95NULL method pointer.
96
97When calling a native method from interpreted code, the stack setup is
98essentially identical to calling an interpreted method. Because it's a
99native method, though, there are never any "locals" or "outs".
100
101For native calls into JNI, we want to store a table of local references
102on the stack. The GC needs to scan them while the native code is running,
103and we want to trivially discard them when the method returns. See JNI.c
104for a discussion of how this is managed. In particular note that it is
105possible to push additional call frames on without calling a method.
106*/
107
108
109struct StackSaveArea;
110typedef 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 */
121struct 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
Ben Chengba4fc8b2009-06-01 13:00:29 -0700149 /* Native return pointer for JIT, or 0 if interpreted */
150 const u2* returnAddr;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800151#ifdef PAD_SAVE_AREA
152 u4 pad3, pad4, pad5;
153#endif
154};
155
156/* move between the stack save area and the frame pointer */
157#define SAVEAREA_FROM_FP(_fp) ((StackSaveArea*)(_fp) -1)
158#define FP_FROM_SAVEAREA(_save) ((void*) ((StackSaveArea*)(_save) +1))
159
160/* when calling a function, get a pointer to outs[0] */
161#define OUTS_FROM_FP(_fp, _argCount) \
162 ((u4*) ((u1*)SAVEAREA_FROM_FP(_fp) - sizeof(u4) * (_argCount)))
163
164/* reserve this many bytes for handling StackOverflowError */
165#define STACK_OVERFLOW_RESERVE 512
166
167/*
168 * Determine if the frame pointer points to a "break frame".
169 */
170INLINE bool dvmIsBreakFrame(const u4* fp)
171{
172 return SAVEAREA_FROM_FP(fp)->method == NULL;
173}
174
175/*
176 * Initialize the interp stack (call this after allocating storage and
177 * setting thread->interpStackStart).
178 */
179bool dvmInitInterpStack(Thread* thread, int stackSize);
180
181/*
182 * Push a native method frame directly onto the stack. Used to push the
183 * "fake" native frames at the top of each thread stack.
184 */
185bool dvmPushJNIFrame(Thread* thread, const Method* method);
186
187/*
188 * JNI local frame management.
189 */
190bool dvmPushLocalFrame(Thread* thread, const Method* method);
191bool dvmPopLocalFrame(Thread* thread);
192
193/*
194 * Call an interpreted method from native code.
195 *
196 * "obj" should be NULL for "direct" methods.
197 */
198void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
199 JValue* pResult, va_list args);
200void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
201 JValue* pResult, const jvalue* args);
202void dvmCallMethod(Thread* self, const Method* method, Object* obj,
203 JValue* pResult, ...);
204
205/*
206 * Invoke a method, using the specified arguments and return type, through
207 * a reflection interface.
208 *
209 * Deals with boxing/unboxing primitives and performs widening conversions.
210 *
211 * "obj" should be null for a static method.
212 *
213 * "params" and "returnType" come from the Method object, so we don't have
214 * to re-generate them from the method signature. "returnType" should be
215 * NULL if we're invoking a constructor.
216 */
217Object* dvmInvokeMethod(Object* invokeObj, const Method* meth,
218 ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
219 bool noAccessCheck);
220
221/*
222 * Determine the source file line number, given the program counter offset
223 * into the specified method. Returns -2 for native methods, -1 if no
224 * match was found.
225 */
226int dvmLineNumFromPC(const Method* method, u4 relPc);
227
228/*
229 * Given a frame pointer, compute the current call depth. The value can be
230 * "exact" (a count of non-break frames) or "vague" (just subtracting
231 * pointers to give relative values).
232 */
233int dvmComputeExactFrameDepth(const void* fp);
234int dvmComputeVagueFrameDepth(Thread* thread, const void* fp);
235
236/*
237 * Get the frame pointer for the caller's stack frame.
238 */
239void* dvmGetCallerFP(const void* curFrame);
240
241/*
242 * Get the class of the method that called us.
243 */
244ClassObject* dvmGetCallerClass(const void* curFrame);
245
246/*
247 * Get the caller's caller's class. Pass in the current fp.
248 *
249 * This is used by e.g. java.lang.Class, which wants to know about the
250 * class loader of the method that called it.
251 */
252ClassObject* dvmGetCaller2Class(const void* curFrame);
253
254/*
255 * Get the caller's caller's caller's class. Pass in the current fp.
256 *
257 * This is used by e.g. java.lang.Class, which wants to know about the
258 * class loader of the method that called it.
259 */
260ClassObject* dvmGetCaller3Class(const void* curFrame);
261
262/*
263 * Allocate and fill an array of method pointers representing the current
264 * stack trace (element 0 is current frame).
265 */
266bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
267 int* pLength);
268
269/*
270 * Common handling for stack overflow.
271 */
272void dvmHandleStackOverflow(Thread* self);
273void dvmCleanupStackOverflow(Thread* self);
274
275/* debugging; dvmDumpThread() is probably a better starting point */
276void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread);
277void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread);
278
279#endif /*_DALVIK_INTERP_STACK*/