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 * TODO: remove "switch" version. 24 */ 25 #ifdef THREADED_INTERP 26 # define H(_op) &&op_##_op 27 # define HANDLE_OPCODE(_op) op_##_op: 28 # define FINISH(_offset) { \ 29 ADJUST_PC(_offset); \ 30 inst = FETCH(0); \ 31 CHECK_DEBUG_AND_PROF(); \ 32 CHECK_TRACKED_REFS(); \ 33 if (CHECK_JIT_BOOL()) GOTO_bail_switch(); \ 34 goto *handlerTable[INST_INST(inst)]; \ 35 } 36 # define FINISH_BKPT(_opcode) { \ 37 goto *handlerTable[_opcode]; \ 38 } 39 #else 40 # define HANDLE_OPCODE(_op) case _op: 41 # define FINISH(_offset) { ADJUST_PC(_offset); break; } 42 # define FINISH_BKPT(opcode) { > not implemented < } 43 #endif 44 45 #define OP_END 46 47 #if defined(WITH_TRACKREF_CHECKS) 48 # define CHECK_TRACKED_REFS() \ 49 dvmInterpCheckTrackedRefs(self, curMethod, debugTrackedRefStart) 50 #else 51 # define CHECK_TRACKED_REFS() ((void)0) 52 #endif 53 54 55 /* 56 * The "goto" targets just turn into goto statements. The "arguments" are 57 * passed through local variables. 58 */ 59 60 #define GOTO_exceptionThrown() goto exceptionThrown; 61 62 #define GOTO_returnFromMethod() goto returnFromMethod; 63 64 #define GOTO_invoke(_target, _methodCallRange) \ 65 do { \ 66 methodCallRange = _methodCallRange; \ 67 goto _target; \ 68 } while(false) 69 70 /* for this, the "args" are already in the locals */ 71 #define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod; 72 73 #define GOTO_bail() goto bail; 74 #define GOTO_bail_switch() goto bail_switch; 75 76 /* 77 * Periodically check for thread suspension. 78 * 79 * While we're at it, see if a debugger has attached or the profiler has 80 * started. If so, switch to a different "goto" table. 81 */ 82 #define PERIODIC_CHECKS(_entryPoint, _pcadj) { \ 83 if (dvmCheckSuspendQuick(self)) { \ 84 EXPORT_PC(); /* need for precise GC */ \ 85 dvmCheckSuspendPending(self); \ 86 } \ 87 if (NEED_INTERP_SWITCH(INTERP_TYPE)) { \ 88 ADJUST_PC(_pcadj); \ 89 interpState->entryPoint = _entryPoint; \ 90 LOGVV("threadid=%d: switch to %s ep=%d adj=%d\n", \ 91 self->threadId, \ 92 (interpState->nextMode == INTERP_STD) ? "STD" : "DBG", \ 93 (_entryPoint), (_pcadj)); \ 94 GOTO_bail_switch(); \ 95 } \ 96 } 97