stubdefs.cpp revision 9a3147c7412f4794434b4c2604aa2ba784867774
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    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.c".)
24 */
25#define retval                  self->retval
26#define pc                      self->interpSave.pc
27#define fp                      self->interpSave.fp
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/*
42 * Opcode handler framing macros.  Here, each opcode is a separate function
43 * that takes a "self" argument and returns void.  We can't declare
44 * these "static" because they may be called from an assembly stub.
45 * (void)xxx to quiet unused variable compiler warnings.
46 */
47#define HANDLE_OPCODE(_op)                                                  \
48    void dvmMterp_##_op(Thread* self) {                                     \
49        u4 ref;                                                             \
50        u2 vsrc1, vsrc2, vdst;                                              \
51        u2 inst = FETCH(0);                                                 \
52        (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
53
54#define OP_END }
55
56/*
57 * Like the "portable" FINISH, but don't reload "inst", and return to caller
58 * when done.  Further, debugger/profiler checks are handled
59 * before handler execution in mterp, so we don't do them here either.
60 */
61#if defined(WITH_JIT)
62#define FINISH(_offset) {                                                   \
63        ADJUST_PC(_offset);                                                 \
64        if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {        \
65            dvmCheckJit(pc, self);                                          \
66        }                                                                   \
67        return;                                                             \
68    }
69#else
70#define FINISH(_offset) {                                                   \
71        ADJUST_PC(_offset);                                                 \
72        return;                                                             \
73    }
74#endif
75
76
77/*
78 * The "goto label" statements turn into function calls followed by
79 * return statements.  Some of the functions take arguments, which in the
80 * portable interpreter are handled by assigning values to globals.
81 */
82
83#define GOTO_exceptionThrown()                                              \
84    do {                                                                    \
85        dvmMterp_exceptionThrown(self);                                     \
86        return;                                                             \
87    } while(false)
88
89#define GOTO_returnFromMethod()                                             \
90    do {                                                                    \
91        dvmMterp_returnFromMethod(self);                                    \
92        return;                                                             \
93    } while(false)
94
95#define GOTO_invoke(_target, _methodCallRange, _jumboFormat)                \
96    do {                                                                    \
97        dvmMterp_##_target(self, _methodCallRange, _jumboFormat);           \
98        return;                                                             \
99    } while(false)
100
101#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
102    do {                                                                    \
103        dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall,        \
104            _vsrc1, _vdst);                                                 \
105        return;                                                             \
106    } while(false)
107
108/*
109 * As a special case, "goto bail" turns into a longjmp.
110 */
111#define GOTO_bail()                                                         \
112    dvmMterpStdBail(self, false);
113
114/*
115 * Periodically check for thread suspension.
116 *
117 * While we're at it, see if a debugger has attached or the profiler has
118 * started.
119 */
120#define PERIODIC_CHECKS(_pcadj) {                              \
121        if (dvmCheckSuspendQuick(self)) {                                   \
122            EXPORT_PC();  /* need for precise GC */                         \
123            dvmCheckSuspendPending(self);                                   \
124        }                                                                   \
125    }
126