summaryrefslogtreecommitdiff
path: root/vm/mterp/cstubs/stubdefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/mterp/cstubs/stubdefs.c')
-rw-r--r--vm/mterp/cstubs/stubdefs.c124
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(); \
+ } \
+ }