Home | History | Annotate | Download | only in cstubs
      1 /*
      2  * In the C mterp stubs, "goto" is a function call followed immediately
      3  * by a return.
      4  */
      5 
      6 #define GOTO_TARGET_DECL(_target, ...)                                      \
      7     extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
      8 
      9 /* (void)xxx to quiet unused variable compiler warnings. */
     10 #define GOTO_TARGET(_target, ...)                                           \
     11     void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) {                 \
     12         u2 ref, vsrc1, vsrc2, vdst;                                         \
     13         u2 inst = FETCH(0);                                                 \
     14         const Method* methodToCall;                                         \
     15         StackSaveArea* debugSaveArea;                                       \
     16         (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;        \
     17         (void)methodToCall; (void)debugSaveArea;
     18 
     19 #define GOTO_TARGET_END }
     20 
     21 /*
     22  * Redefine what used to be local variable accesses into Thread struct
     23  * references.  (These are undefined down in "footer.cpp".)
     24  */
     25 #define retval                  self->interpSave.retval
     26 #define pc                      self->interpSave.pc
     27 #define fp                      self->interpSave.curFrame
     28 #define curMethod               self->interpSave.method
     29 #define methodClassDex          self->interpSave.methodClassDex
     30 #define debugTrackedRefStart    self->interpSave.debugTrackedRefStart
     31 
     32 /* ugh */
     33 #define STUB_HACK(x) x
     34 #if defined(WITH_JIT)
     35 #define JIT_STUB_HACK(x) x
     36 #else
     37 #define JIT_STUB_HACK(x)
     38 #endif
     39 
     40 /*
     41  * InterpSave's pc and fp must be valid when breaking out to a
     42  * "Reportxxx" routine.  Because the portable interpreter uses local
     43  * variables for these, we must flush prior.  Stubs, however, use
     44  * the interpSave vars directly, so this is a nop for stubs.
     45  */
     46 #define PC_FP_TO_SELF()
     47 #define PC_TO_SELF()
     48 
     49 /*
     50  * Opcode handler framing macros.  Here, each opcode is a separate function
     51  * that takes a "self" argument and returns void.  We can't declare
     52  * these "static" because they may be called from an assembly stub.
     53  * (void)xxx to quiet unused variable compiler warnings.
     54  */
     55 #define HANDLE_OPCODE(_op)                                                  \
     56     extern "C" void dvmMterp_##_op(Thread* self);                           \
     57     void dvmMterp_##_op(Thread* self) {                                     \
     58         u4 ref;                                                             \
     59         u2 vsrc1, vsrc2, vdst;                                              \
     60         u2 inst = FETCH(0);                                                 \
     61         (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
     62 
     63 #define OP_END }
     64 
     65 /*
     66  * Like the "portable" FINISH, but don't reload "inst", and return to caller
     67  * when done.  Further, debugger/profiler checks are handled
     68  * before handler execution in mterp, so we don't do them here either.
     69  */
     70 #if defined(WITH_JIT)
     71 #define FINISH(_offset) {                                                   \
     72         ADJUST_PC(_offset);                                                 \
     73         if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {        \
     74             dvmCheckJit(pc, self);                                          \
     75         }                                                                   \
     76         return;                                                             \
     77     }
     78 #else
     79 #define FINISH(_offset) {                                                   \
     80         ADJUST_PC(_offset);                                                 \
     81         return;                                                             \
     82     }
     83 #endif
     84 
     85 
     86 /*
     87  * The "goto label" statements turn into function calls followed by
     88  * return statements.  Some of the functions take arguments, which in the
     89  * portable interpreter are handled by assigning values to globals.
     90  */
     91 
     92 #define GOTO_exceptionThrown()                                              \
     93     do {                                                                    \
     94         dvmMterp_exceptionThrown(self);                                     \
     95         return;                                                             \
     96     } while(false)
     97 
     98 #define GOTO_returnFromMethod()                                             \
     99     do {                                                                    \
    100         dvmMterp_returnFromMethod(self);                                    \
    101         return;                                                             \
    102     } while(false)
    103 
    104 #define GOTO_invoke(_target, _methodCallRange)                              \
    105     do {                                                                    \
    106         dvmMterp_##_target(self, _methodCallRange);                         \
    107         return;                                                             \
    108     } while(false)
    109 
    110 #define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
    111     do {                                                                    \
    112         dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall,        \
    113             _vsrc1, _vdst);                                                 \
    114         return;                                                             \
    115     } while(false)
    116 
    117 /*
    118  * As a special case, "goto bail" turns into a longjmp.
    119  */
    120 #define GOTO_bail()                                                         \
    121     dvmMterpStdBail(self, false);
    122 
    123 /*
    124  * Periodically check for thread suspension.
    125  *
    126  * While we're at it, see if a debugger has attached or the profiler has
    127  * started.
    128  */
    129 #define PERIODIC_CHECKS(_pcadj) {                              \
    130         if (dvmCheckSuspendQuick(self)) {                                   \
    131             EXPORT_PC();  /* need for precise GC */                         \
    132             dvmCheckSuspendPending(self);                                   \
    133         }                                                                   \
    134     }
    135