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_H_ 21 #define DALVIK_INTERP_STACK_H_ 22 23 #include "jni.h" 24 #include <stdarg.h> 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 111 //#define PAD_SAVE_AREA /* help debug stack trampling */ 112 113 /* 114 * The VM-specific internal goop. 115 * 116 * The idea is to mimic a typical native stack frame, with copies of the 117 * saved PC and FP. At some point we'd like to have interpreted and 118 * native code share the same stack, though this makes portability harder. 119 */ 120 struct StackSaveArea { 121 #ifdef PAD_SAVE_AREA 122 u4 pad0, pad1, pad2; 123 #endif 124 125 #ifdef EASY_GDB 126 /* make it easier to trek through stack frames in GDB */ 127 StackSaveArea* prevSave; 128 #endif 129 130 /* saved frame pointer for previous frame, or NULL if this is at bottom */ 131 u4* prevFrame; 132 133 /* saved program counter (from method in caller's frame) */ 134 const u2* savedPc; 135 136 /* pointer to method we're *currently* executing; handy for exceptions */ 137 const Method* method; 138 139 union { 140 /* for JNI native methods: bottom of local reference segment */ 141 u4 localRefCookie; 142 143 /* for interpreted methods: saved current PC, for exception stack 144 * traces and debugger traces */ 145 const u2* currentPc; 146 } xtra; 147 148 /* Native return pointer for JIT, or 0 if interpreted */ 149 const u2* returnAddr; 150 #ifdef PAD_SAVE_AREA 151 u4 pad3, pad4, pad5; 152 #endif 153 }; 154 155 /* move between the stack save area and the frame pointer */ 156 #define SAVEAREA_FROM_FP(_fp) ((StackSaveArea*)(_fp) -1) 157 #define FP_FROM_SAVEAREA(_save) ((u4*) ((StackSaveArea*)(_save) +1)) 158 159 /* when calling a function, get a pointer to outs[0] */ 160 #define OUTS_FROM_FP(_fp, _argCount) \ 161 ((u4*) ((u1*)SAVEAREA_FROM_FP(_fp) - sizeof(u4) * (_argCount))) 162 163 /* reserve this many bytes for handling StackOverflowError */ 164 #define STACK_OVERFLOW_RESERVE 768 165 166 /* 167 * Determine if the frame pointer points to a "break frame". 168 */ 169 INLINE bool dvmIsBreakFrame(const u4* fp) 170 { 171 return SAVEAREA_FROM_FP(fp)->method == NULL; 172 } 173 174 /* 175 * Initialize the interp stack (call this after allocating storage and 176 * setting thread->interpStackStart). 177 */ 178 bool dvmInitInterpStack(Thread* thread, int stackSize); 179 180 /* 181 * Push a native method frame directly onto the stack. Used to push the 182 * "fake" native frames at the top of each thread stack. 183 */ 184 bool dvmPushJNIFrame(Thread* thread, const Method* method); 185 186 /* 187 * JNI local frame management. 188 */ 189 bool dvmPushLocalFrame(Thread* thread, const Method* method); 190 bool dvmPopLocalFrame(Thread* thread); 191 192 /* 193 * Call an interpreted method from native code. If this is being called 194 * from a JNI function, references in the argument list will be converted 195 * back to pointers. 196 * 197 * "obj" should be NULL for "direct" methods. 198 */ 199 void dvmCallMethod(Thread* self, const Method* method, Object* obj, 200 JValue* pResult, ...); 201 void dvmCallMethodV(Thread* self, const Method* method, Object* obj, 202 bool fromJni, JValue* pResult, va_list args); 203 void dvmCallMethodA(Thread* self, const Method* method, Object* obj, 204 bool fromJni, JValue* pResult, const jvalue* args); 205 206 /* 207 * Invoke a method, using the specified arguments and return type, through 208 * a reflection interface. 209 * 210 * Deals with boxing/unboxing primitives and performs widening conversions. 211 * 212 * "obj" should be null for a static method. 213 * 214 * "params" and "returnType" come from the Method object, so we don't have 215 * to re-generate them from the method signature. "returnType" should be 216 * NULL if we're invoking a constructor. 217 */ 218 Object* dvmInvokeMethod(Object* invokeObj, const Method* meth, 219 ArrayObject* argList, ArrayObject* params, ClassObject* returnType, 220 bool noAccessCheck); 221 222 /* 223 * Determine the source file line number, given the program counter offset 224 * into the specified method. Returns -2 for native methods, -1 if no 225 * match was found. 226 */ 227 extern "C" int dvmLineNumFromPC(const Method* method, u4 relPc); 228 229 /* 230 * Given a frame pointer, compute the current call depth. The value can be 231 * "exact" (a count of non-break frames) or "vague" (just subtracting 232 * pointers to give relative values). 233 */ 234 int dvmComputeExactFrameDepth(const void* fp); 235 int dvmComputeVagueFrameDepth(Thread* thread, const void* fp); 236 237 /* 238 * Get the frame pointer for the caller's stack frame. 239 */ 240 void* dvmGetCallerFP(const void* curFrame); 241 242 /* 243 * Get the class of the method that called us. 244 */ 245 ClassObject* dvmGetCallerClass(const void* curFrame); 246 247 /* 248 * Get the caller's caller's class. Pass in the current fp. 249 * 250 * This is used by e.g. java.lang.Class, which wants to know about the 251 * class loader of the method that called it. 252 */ 253 ClassObject* dvmGetCaller2Class(const void* curFrame); 254 255 /* 256 * Get the caller's caller's caller's class. Pass in the current fp. 257 * 258 * This is used by e.g. java.lang.Class, which wants to know about the 259 * class loader of the method that called it. 260 */ 261 ClassObject* dvmGetCaller3Class(const void* curFrame); 262 263 /* 264 * Fill an array of method pointers representing the current stack 265 * trace (element 0 is current frame). 266 */ 267 void dvmFillStackTraceArray(const void* fp, const Method** array, size_t length); 268 269 /* 270 * Common handling for stack overflow. 271 */ 272 extern "C" void dvmHandleStackOverflow(Thread* self, const Method* method); 273 extern "C" void dvmCleanupStackOverflow(Thread* self, const Object* exception); 274 275 /* debugging; dvmDumpThread() is probably a better starting point */ 276 void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread); 277 void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread); 278 void dvmDumpNativeStack(const DebugOutputTarget* target, pid_t tid); 279 280 #endif // DALVIK_INTERP_STACK_H_ 281