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