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 /* 28 Stack layout 29 30 In what follows, the "top" of the stack is at a low position in memory, 31 and the "bottom" of the stack is in a high position (put more simply, 32 they grow downward). They may be merged with the native stack at a 33 later date. The interpreter assumes that they have a fixed size, 34 determined when the thread is created. 35 36 Dalvik's registers (of which there can be up to 64K) map to the "ins" 37 (method arguments) and "locals" (local variables). The "outs" (arguments 38 to called methods) are specified by the "invoke" operand. The return 39 value, which is passed through the interpreter rather than on the stack, 40 is 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 76 Note the "ins" and "outs" overlap -- values pushed into the "outs" area 77 become the parameters to the called method. The VM guarantees that there 78 will be enough room for all possible "outs" on the stack before calling 79 into a method. 80 81 All "V registers" are 32 bits, and all stack entries are 32-bit aligned. 82 Registers are accessed as a positive offset from the frame pointer, 83 e.g. register v2 is fp[2]. 64-bit quantities are stored in two adjacent 84 registers, addressed by the lower-numbered register, and are in host order. 85 64-bit quantities do not need to start in an even-numbered register. 86 87 We push two stack frames on when calling an interpreted or native method 88 directly from the VM (e.g. invoking <clinit> or via reflection "invoke()"). 89 The first is a "break" frame, which allows us to tell when a call return or 90 exception unroll has reached the VM call site. Without the break frame the 91 stack might look like an uninterrupted series of interpreted method calls. 92 The second frame is for the method itself. 93 94 The "break" frame is used as an alternative to adding additional fields 95 to the StackSaveArea struct itself. They are recognized by having a 96 NULL method pointer. 97 98 When calling a native method from interpreted code, the stack setup is 99 essentially identical to calling an interpreted method. Because it's a 100 native method, though, there are never any "locals" or "outs". 101 102 For native calls into JNI, we want to store a table of local references 103 on the stack. The GC needs to scan them while the native code is running, 104 and we want to trivially discard them when the method returns. See JNI.c 105 for a discussion of how this is managed. In particular note that it is 106 possible to push additional call frames on without calling a method. 107 */ 108 109 110 struct StackSaveArea; 111 typedef 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 */ 122 struct 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 */ 175 INLINE 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 */ 184 bool 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 */ 190 bool dvmPushJNIFrame(Thread* thread, const Method* method); 191 192 /* 193 * JNI local frame management. 194 */ 195 bool dvmPushLocalFrame(Thread* thread, const Method* method); 196 bool 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 */ 205 void dvmCallMethod(Thread* self, const Method* method, Object* obj, 206 JValue* pResult, ...); 207 void dvmCallMethodV(Thread* self, const Method* method, Object* obj, 208 bool fromJni, JValue* pResult, va_list args); 209 void 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 */ 224 Object* 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 */ 233 int 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 */ 240 int dvmComputeExactFrameDepth(const void* fp); 241 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp); 242 243 /* 244 * Get the frame pointer for the caller's stack frame. 245 */ 246 void* dvmGetCallerFP(const void* curFrame); 247 248 /* 249 * Get the class of the method that called us. 250 */ 251 ClassObject* 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 */ 259 ClassObject* 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 */ 267 ClassObject* 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 */ 273 bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray, 274 int* pLength); 275 276 /* 277 * Common handling for stack overflow. 278 */ 279 void dvmHandleStackOverflow(Thread* self, const Method* method); 280 void dvmCleanupStackOverflow(Thread* self, const Object* exception); 281 282 /* debugging; dvmDumpThread() is probably a better starting point */ 283 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread); 284 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread); 285 286 #endif /*_DALVIK_INTERP_STACK*/ 287