Home | History | Annotate | Download | only in interp
      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