diff options
Diffstat (limited to 'vm/mterp/cstubs/stubdefs.c')
-rw-r--r-- | vm/mterp/cstubs/stubdefs.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/vm/mterp/cstubs/stubdefs.c b/vm/mterp/cstubs/stubdefs.c new file mode 100644 index 0000000..bf870c6 --- /dev/null +++ b/vm/mterp/cstubs/stubdefs.c @@ -0,0 +1,124 @@ +/* this is a standard (no debug support) interpreter */ +#define INTERP_TYPE INTERP_STD +#define CHECK_DEBUG_AND_PROF() ((void)0) +# define CHECK_TRACKED_REFS() ((void)0) +#define CHECK_JIT_BOOL() (false) +#define CHECK_JIT_VOID() +#define ABORT_JIT_TSELECT() ((void)0) + +/* + * In the C mterp stubs, "goto" is a function call followed immediately + * by a return. + */ + +#define GOTO_TARGET_DECL(_target, ...) \ + void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__); + +#define GOTO_TARGET(_target, ...) \ + void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__) { \ + u2 ref, vsrc1, vsrc2, vdst; \ + u2 inst = FETCH(0); \ + const Method* methodToCall; \ + StackSaveArea* debugSaveArea; + +#define GOTO_TARGET_END } + +/* + * Redefine what used to be local variable accesses into MterpGlue struct + * references. (These are undefined down in "footer.c".) + */ +#define retval glue->retval +#define pc glue->pc +#define fp glue->fp +#define curMethod glue->method +#define methodClassDex glue->methodClassDex +#define self glue->self +#define debugTrackedRefStart glue->debugTrackedRefStart + +/* ugh */ +#define STUB_HACK(x) x + + +/* + * Opcode handler framing macros. Here, each opcode is a separate function + * that takes a "glue" argument and returns void. We can't declare + * these "static" because they may be called from an assembly stub. + */ +#define HANDLE_OPCODE(_op) \ + void dvmMterp_##_op(MterpGlue* glue) { \ + u2 ref, vsrc1, vsrc2, vdst; \ + u2 inst = FETCH(0); + +#define OP_END } + +/* + * Like the "portable" FINISH, but don't reload "inst", and return to caller + * when done. + */ +#define FINISH(_offset) { \ + ADJUST_PC(_offset); \ + CHECK_DEBUG_AND_PROF(); \ + CHECK_TRACKED_REFS(); \ + return; \ + } + + +/* + * The "goto label" statements turn into function calls followed by + * return statements. Some of the functions take arguments, which in the + * portable interpreter are handled by assigning values to globals. + */ + +#define GOTO_exceptionThrown() \ + do { \ + dvmMterp_exceptionThrown(glue); \ + return; \ + } while(false) + +#define GOTO_returnFromMethod() \ + do { \ + dvmMterp_returnFromMethod(glue); \ + return; \ + } while(false) + +#define GOTO_invoke(_target, _methodCallRange) \ + do { \ + dvmMterp_##_target(glue, _methodCallRange); \ + return; \ + } while(false) + +#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \ + do { \ + dvmMterp_invokeMethod(glue, _methodCallRange, _methodToCall, \ + _vsrc1, _vdst); \ + return; \ + } while(false) + +/* + * As a special case, "goto bail" turns into a longjmp. Use "bail_switch" + * if we need to switch to the other interpreter upon our return. + */ +#define GOTO_bail() \ + dvmMterpStdBail(glue, false); +#define GOTO_bail_switch() \ + dvmMterpStdBail(glue, true); + +/* + * 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(_entryPoint, _pcadj) { \ + if (dvmCheckSuspendQuick(self)) { \ + EXPORT_PC(); /* need for precise GC */ \ + dvmCheckSuspendPending(self); \ + } \ + if (NEED_INTERP_SWITCH(INTERP_TYPE)) { \ + ADJUST_PC(_pcadj); \ + glue->entryPoint = _entryPoint; \ + LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n", \ + self->threadId, (_entryPoint), (_pcadj)); \ + GOTO_bail_switch(); \ + } \ + } |