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 8 #define GOTO_TARGET(_target, ...) _target: 9 10 #define GOTO_TARGET_END 11 12 /* ugh */ 13 #define STUB_HACK(x) 14 15 /* 16 * Instruction framing. For a switch-oriented implementation this is 17 * case/break, for a threaded implementation it's a goto label and an 18 * instruction fetch/computed goto. 19 * 20 * Assumes the existence of "const u2* pc" and (for threaded operation) 21 * "u2 inst". 22 */ 23 #ifdef THREADED_INTERP 24 # define H(_op) &&op_##_op 25 # define HANDLE_OPCODE(_op) op_##_op: 26 # define FINISH(_offset) { \ 27 ADJUST_PC(_offset); \ 28 inst = FETCH(0); \ 29 CHECK_DEBUG_AND_PROF(); \ 30 CHECK_TRACKED_REFS(); \ 31 CHECK_JIT(); \ 32 goto *handlerTable[INST_INST(inst)]; \ 33 } 34 #else 35 # define HANDLE_OPCODE(_op) case _op: 36 # define FINISH(_offset) { ADJUST_PC(_offset); break; } 37 #endif 38 39 #define OP_END 40 41 #if defined(WITH_TRACKREF_CHECKS) 42 # define CHECK_TRACKED_REFS() \ 43 dvmInterpCheckTrackedRefs(self, curMethod, debugTrackedRefStart) 44 #else 45 # define CHECK_TRACKED_REFS() ((void)0) 46 #endif 47 48 49 /* 50 * The "goto" targets just turn into goto statements. The "arguments" are 51 * passed through local variables. 52 */ 53 54 #define GOTO_exceptionThrown() goto exceptionThrown; 55 56 #define GOTO_returnFromMethod() goto returnFromMethod; 57 58 #define GOTO_invoke(_target, _methodCallRange) \ 59 do { \ 60 methodCallRange = _methodCallRange; \ 61 goto _target; \ 62 } while(false) 63 64 /* for this, the "args" are already in the locals */ 65 #define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod; 66 67 #define GOTO_bail() goto bail; 68 #define GOTO_bail_switch() goto bail_switch; 69 70 /* 71 * Periodically check for thread suspension. 72 * 73 * While we're at it, see if a debugger has attached or the profiler has 74 * started. If so, switch to a different "goto" table. 75 */ 76 #define PERIODIC_CHECKS(_entryPoint, _pcadj) { \ 77 if (dvmCheckSuspendQuick(self)) { \ 78 EXPORT_PC(); /* need for precise GC */ \ 79 dvmCheckSuspendPending(self); \ 80 } \ 81 if (NEED_INTERP_SWITCH(INTERP_TYPE)) { \ 82 ADJUST_PC(_pcadj); \ 83 interpState->entryPoint = _entryPoint; \ 84 LOGVV("threadid=%d: switch to %s ep=%d adj=%d\n", \ 85 self->threadId, \ 86 (interpState->nextMode == INTERP_STD) ? "STD" : "DBG", \ 87 (_entryPoint), (_pcadj)); \ 88 GOTO_bail_switch(); \ 89 } \ 90 } 91 92