/* * In the C mterp stubs, "goto" is a function call followed immediately * by a return. */ #define GOTO_TARGET_DECL(_target, ...) #define GOTO_TARGET(_target, ...) _target: #define GOTO_TARGET_END /* ugh */ #define STUB_HACK(x) #define JIT_STUB_HACK(x) /* * InterpSave's pc and fp must be valid when breaking out to a * "Reportxxx" routine. Because the portable interpreter uses local * variables for these, we must flush prior. Stubs, however, use * the interpSave vars directly, so this is a nop for stubs. */ #define PC_FP_TO_SELF() \ self->interpSave.pc = pc; \ self->interpSave.curFrame = fp; #define PC_TO_SELF() self->interpSave.pc = pc; /* * Instruction framing. For a switch-oriented implementation this is * case/break, for a threaded implementation it's a goto label and an * instruction fetch/computed goto. * * Assumes the existence of "const u2* pc" and (for threaded operation) * "u2 inst". */ # define H(_op) &&op_##_op # define HANDLE_OPCODE(_op) op_##_op: # define FINISH(_offset) { \ ADJUST_PC(_offset); \ inst = FETCH(0); \ if (self->interpBreak.ctl.subMode) { \ dvmCheckBefore(pc, fp, self); \ } \ goto *handlerTable[INST_INST(inst)]; \ } # define FINISH_BKPT(_opcode) { \ goto *handlerTable[_opcode]; \ } # define DISPATCH_EXTENDED(_opcode) { \ goto *handlerTable[0x100 + _opcode]; \ } #define OP_END /* * The "goto" targets just turn into goto statements. The "arguments" are * passed through local variables. */ #define GOTO_exceptionThrown() goto exceptionThrown; #define GOTO_returnFromMethod() goto returnFromMethod; #define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \ do { \ methodCallRange = _methodCallRange; \ jumboFormat = _jumboFormat; \ goto _target; \ } while(false) /* for this, the "args" are already in the locals */ #define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod; #define GOTO_bail() goto bail; /* * Periodically check for thread suspension. * * While we're at it, see if a debugger has attached or the profiler has * started. If so, switch to a different "goto" table. */ #define PERIODIC_CHECKS(_pcadj) { \ if (dvmCheckSuspendQuick(self)) { \ EXPORT_PC(); /* need for precise GC */ \ dvmCheckSuspendPending(self); \ } \ }