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