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
     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