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  * Dalvik interpreter definitions.  These are internal to the interpreter.
     18  *
     19  * This includes defines, types, function declarations, and inline functions
     20  * that are common to all interpreter implementations.
     21  *
     22  * Functions and globals declared here are defined in Interp.c.
     23  */
     24 #ifndef _DALVIK_INTERP_DEFS
     25 #define _DALVIK_INTERP_DEFS
     26 
     27 
     28 /*
     29  * Specify the starting point when switching between interpreters.
     30  */
     31 typedef enum InterpEntry {
     32     kInterpEntryInstr = 0,      // continue to next instruction
     33     kInterpEntryReturn = 1,     // jump to method return
     34     kInterpEntryThrow = 2,      // jump to exception throw
     35 #if defined(WITH_JIT)
     36     kInterpEntryResume = 3,     // Resume after single-step
     37 #endif
     38 } InterpEntry;
     39 
     40 #if defined(WITH_JIT)
     41 /*
     42  * There are six entry points from the compiled code to the interpreter:
     43  * 1) dvmJitToInterpNormal: find if there is a corresponding compilation for
     44  *    the new dalvik PC. If so, chain the originating compilation with the
     45  *    target then jump to it.
     46  * 2) dvmJitToInterpInvokeNoChain: similar to 1) but don't chain. This is
     47  *    for handling 1-to-many mappings like virtual method call and
     48  *    packed switch.
     49  * 3) dvmJitToInterpPunt: use the fast interpreter to execute the next
     50  *    instruction(s) and stay there as long as it is appropriate to return
     51  *    to the compiled land. This is used when the jit'ed code is about to
     52  *    throw an exception.
     53  * 4) dvmJitToInterpSingleStep: use the portable interpreter to execute the
     54  *    next instruction only and return to pre-specified location in the
     55  *    compiled code to resume execution. This is mainly used as debugging
     56  *    feature to bypass problematic opcode implementations without
     57  *    disturbing the trace formation.
     58  * 5) dvmJitToTraceSelect: if there is a single exit from a translation that
     59  *    has already gone hot enough to be translated, we should assume that
     60  *    the exit point should also be translated (this is a common case for
     61  *    invokes).  This trace exit will first check for a chaining
     62  *    opportunity, and if none is available will switch to the debug
     63  *    interpreter immediately for trace selection (as if threshold had
     64  *    just been reached).
     65  * 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site
     66  *    to a predicted callee.
     67  * 7) dvmJitToBackwardBranch: (WITH_SELF_VERIFICATION ONLY) special case of 1)
     68  *    and 5). This is used instead if the ending branch of the trace jumps back
     69  *    into the same basic block.
     70  */
     71 struct JitToInterpEntries {
     72     void *dvmJitToInterpNormal;
     73     void *dvmJitToInterpNoChain;
     74     void *dvmJitToInterpPunt;
     75     void *dvmJitToInterpSingleStep;
     76     void *dvmJitToInterpTraceSelectNoChain;
     77     void *dvmJitToInterpTraceSelect;
     78     void *dvmJitToPatchPredictedChain;
     79 #if defined(WITH_SELF_VERIFICATION)
     80     void *dvmJitToInterpBackwardBranch;
     81 #endif
     82 };
     83 
     84 /*
     85  * Size of save area for callee-save FP regs, which are not automatically
     86  * saved by interpreter main because it doesn't use them (but Jit'd code
     87  * may). Save/restore routine is defined by target, and size should
     88  * be >= max needed by any target.
     89  */
     90 #define JIT_CALLEE_SAVE_DOUBLE_COUNT 8
     91 
     92 /* Number of entries in the 2nd level JIT profiler filter cache */
     93 #define JIT_TRACE_THRESH_FILTER_SIZE 32
     94 /* Granularity of coverage (power of 2) by each cached entry */
     95 #define JIT_TRACE_THRESH_FILTER_GRAN_LOG2 6
     96 #endif
     97 
     98 /*
     99  * Interpreter context, used when switching from one interpreter to
    100  * another.  We also tuck "mterp" state in here.
    101  */
    102 typedef struct InterpState {
    103     /*
    104      * To make some mterp state updates easier, "pc" and "fp" MUST come
    105      * first and MUST appear in this order.
    106      */
    107     const u2*   pc;                     // program counter
    108     u4*         fp;                     // frame pointer
    109 
    110     JValue      retval;                 // return value -- "out" only
    111     const Method* method;               // method being executed
    112 
    113 
    114     /* ----------------------------------------------------------------------
    115      * Mterp-only state
    116      */
    117     DvmDex*         methodClassDex;
    118     Thread*         self;
    119 
    120     /* housekeeping */
    121     void*           bailPtr;
    122 
    123     /*
    124      * These are available globally, from gDvm, or from another glue field
    125      * (self/method).  They're copied in here for speed.
    126      */
    127     const u1*       interpStackEnd;
    128     volatile int*   pSelfSuspendCount;
    129 #if defined(WITH_DEBUGGER)
    130     volatile u1*    pDebuggerActive;
    131 #endif
    132 #if defined(WITH_PROFILER)
    133     volatile int*   pActiveProfilers;
    134 #endif
    135     /* ----------------------------------------------------------------------
    136      */
    137 
    138     /*
    139      * Interpreter switching.
    140      */
    141     InterpEntry entryPoint;             // what to do when we start
    142     int         nextMode;               // INTERP_STD, INTERP_DBG
    143 
    144 #if defined(WITH_JIT)
    145     /*
    146      * Local copies of field from gDvm placed here for fast access
    147      */
    148     unsigned char*     pJitProfTable;
    149     JitState           jitState;
    150     const void*        jitResumeNPC;	// Native PC of compiled code
    151     const u2*          jitResumeDPC;	// Dalvik PC corresponding to NPC
    152     int                jitThreshold;
    153     /*
    154      * ppJitProfTable holds the address of gDvmJit.pJitProfTable, which
    155      * doubles as an on/off switch for the Jit.  Because a change in
    156      * the value of gDvmJit.pJitProfTable isn't reflected in the cached
    157      * copy above (pJitProfTable), we need to periodically refresh it.
    158      * ppJitProfTable is used for that purpose.
    159      */
    160     unsigned char**    ppJitProfTable; // Used to refresh pJitProfTable
    161 #endif
    162 
    163 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
    164     bool        debugIsMethodEntry;     // used for method entry event triggers
    165 #endif
    166 #if defined(WITH_TRACKREF_CHECKS)
    167     int         debugTrackedRefStart;   // tracked refs from prior invocations
    168 #endif
    169 
    170 #if defined(WITH_JIT)
    171     struct JitToInterpEntries jitToInterpEntries;
    172 
    173     int currTraceRun;
    174     int totalTraceLen;        // Number of Dalvik insts in trace
    175     const u2* currTraceHead;  // Start of the trace we're building
    176     const u2* currRunHead;    // Start of run we're building
    177     int currRunLen;           // Length of run in 16-bit words
    178     int lastThreshFilter;
    179     const u2* lastPC;         // Stage the PC first for the threaded interpreter
    180     intptr_t threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
    181     JitTraceRun trace[MAX_JIT_RUN_LEN];
    182     double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
    183 #endif
    184 
    185 } InterpState;
    186 
    187 /*
    188  * These are generated from InterpCore.h.
    189  */
    190 extern bool dvmInterpretDbg(Thread* self, InterpState* interpState);
    191 extern bool dvmInterpretStd(Thread* self, InterpState* interpState);
    192 #define INTERP_STD 0
    193 #define INTERP_DBG 1
    194 
    195 /*
    196  * "mterp" interpreter.
    197  */
    198 extern bool dvmMterpStd(Thread* self, InterpState* interpState);
    199 
    200 /*
    201  * Get the "this" pointer from the current frame.
    202  */
    203 Object* dvmGetThisPtr(const Method* method, const u4* fp);
    204 
    205 /*
    206  * Verify that our tracked local references are valid.
    207  */
    208 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
    209     int debugTrackedRefStart);
    210 
    211 /*
    212  * Process switch statement.
    213  */
    214 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal);
    215 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal);
    216 
    217 /*
    218  * Process fill-array-data.
    219  */
    220 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
    221                                   const u2* arrayData);
    222 
    223 /*
    224  * Find an interface method.
    225  */
    226 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
    227     const Method* method, DvmDex* methodClassDex);
    228 
    229 /*
    230  * Determine if the debugger or profiler is currently active.  Used when
    231  * selecting which interpreter to start or switch to.
    232  */
    233 static inline bool dvmDebuggerOrProfilerActive(void)
    234 {
    235     return gDvm.debuggerActive
    236 #if defined(WITH_PROFILER)
    237         || gDvm.activeProfilers != 0
    238 #endif
    239         ;
    240 }
    241 
    242 #if defined(WITH_JIT)
    243 /*
    244  * Determine if the jit, debugger or profiler is currently active.  Used when
    245  * selecting which interpreter to switch to.
    246  */
    247 static inline bool dvmJitDebuggerOrProfilerActive()
    248 {
    249     return gDvmJit.pProfTable != NULL
    250 #if defined(WITH_PROFILER)
    251         || gDvm.activeProfilers != 0
    252 #endif
    253         ||gDvm.debuggerActive;
    254 }
    255 #endif
    256 
    257 #endif /*_DALVIK_INTERP_DEFS*/
    258