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