• 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 
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