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