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#define JIT_STUB_HACK(x) 15 16/* 17 * InterpSave's pc and fp must be valid when breaking out to a 18 * "Reportxxx" routine. Because the portable interpreter uses local 19 * variables for these, we must flush prior. Stubs, however, use 20 * the interpSave vars directly, so this is a nop for stubs. 21 */ 22#define PC_FP_TO_SELF() \ 23 self->interpSave.pc = pc; \ 24 self->interpSave.curFrame = fp; 25#define PC_TO_SELF() self->interpSave.pc = pc; 26 27/* 28 * Instruction framing. For a switch-oriented implementation this is 29 * case/break, for a threaded implementation it's a goto label and an 30 * instruction fetch/computed goto. 31 * 32 * Assumes the existence of "const u2* pc" and (for threaded operation) 33 * "u2 inst". 34 */ 35# define H(_op) &&op_##_op 36# define HANDLE_OPCODE(_op) op_##_op: 37# define FINISH(_offset) { \ 38 ADJUST_PC(_offset); \ 39 inst = FETCH(0); \ 40 if (self->interpBreak.ctl.subMode) { \ 41 dvmCheckBefore(pc, fp, self); \ 42 } \ 43 goto *handlerTable[INST_INST(inst)]; \ 44 } 45# define FINISH_BKPT(_opcode) { \ 46 goto *handlerTable[_opcode]; \ 47 } 48 49#define OP_END 50 51/* 52 * The "goto" targets just turn into goto statements. The "arguments" are 53 * passed through local variables. 54 */ 55 56#define GOTO_exceptionThrown() goto exceptionThrown; 57 58#define GOTO_returnFromMethod() goto returnFromMethod; 59 60#define GOTO_invoke(_target, _methodCallRange) \ 61 do { \ 62 methodCallRange = _methodCallRange; \ 63 goto _target; \ 64 } while(false) 65 66/* for this, the "args" are already in the locals */ 67#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod; 68 69#define GOTO_bail() goto bail; 70 71/* 72 * Periodically check for thread suspension. 73 * 74 * While we're at it, see if a debugger has attached or the profiler has 75 * started. If so, switch to a different "goto" table. 76 */ 77#define PERIODIC_CHECKS(_pcadj) { \ 78 if (dvmCheckSuspendQuick(self)) { \ 79 EXPORT_PC(); /* need for precise GC */ \ 80 dvmCheckSuspendPending(self); \ 81 } \ 82 } 83