• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define FINISH_BKPT(_opcode)       /* FIXME? */
86 #define DISPATCH_EXTENDED(_opcode) /* FIXME? */
87 
88 /*
89  * The "goto label" statements turn into function calls followed by
90  * return statements.  Some of the functions take arguments, which in the
91  * portable interpreter are handled by assigning values to globals.
92  */
93 
94 #define GOTO_exceptionThrown()                                              \
95     do {                                                                    \
96         dvmMterp_exceptionThrown(self);                                     \
97         return;                                                             \
98     } while(false)
99 
100 #define GOTO_returnFromMethod()                                             \
101     do {                                                                    \
102         dvmMterp_returnFromMethod(self);                                    \
103         return;                                                             \
104     } while(false)
105 
106 #define GOTO_invoke(_target, _methodCallRange)                              \
107     do {                                                                    \
108         dvmMterp_##_target(self, _methodCallRange);                         \
109         return;                                                             \
110     } while(false)
111 
112 #define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
113     do {                                                                    \
114         dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall,        \
115             _vsrc1, _vdst);                                                 \
116         return;                                                             \
117     } while(false)
118 
119 /*
120  * As a special case, "goto bail" turns into a longjmp.
121  */
122 #define GOTO_bail()                                                         \
123     dvmMterpStdBail(self)
124 
125 /*
126  * Periodically check for thread suspension.
127  *
128  * While we're at it, see if a debugger has attached or the profiler has
129  * started.
130  */
131 #define PERIODIC_CHECKS(_pcadj) {                              \
132         if (dvmCheckSuspendQuick(self)) {                                   \
133             EXPORT_PC();  /* need for precise GC */                         \
134             dvmCheckSuspendPending(self);                                   \
135         }                                                                   \
136     }
137