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