/* * Handler function table, one entry per opcode. */ #undef H #define H(_op) (const void*) dvmMterp_##_op DEFINE_GOTO_TABLE(gDvmMterpHandlers) #undef H #define H(_op) #_op DEFINE_GOTO_TABLE(gDvmMterpHandlerNames) #include <setjmp.h> /* * C mterp entry point. This just calls the various C fallbacks, making * this a slow but portable interpeter. * * This is only used for the "allstubs" variant. */ void dvmMterpStdRun(Thread* self) { jmp_buf jmpBuf; self->interpSave.bailPtr = &jmpBuf; /* We exit via a longjmp */ if (setjmp(jmpBuf)) { LOGVV("mterp threadid=%d returning", dvmThreadSelf()->threadId); return; } /* run until somebody longjmp()s out */ while (true) { typedef void (*Handler)(Thread* self); u2 inst = /*self->interpSave.*/pc[0]; /* * In mterp, dvmCheckBefore is handled via the altHandlerTable, * while in the portable interpreter it is part of the handler * FINISH code. For allstubs, we must do an explicit check * in the interpretation loop. */ if (self->interpBreak.ctl.subMode) { dvmCheckBefore(pc, fp, self); } Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff]; (void) gDvmMterpHandlerNames; /* avoid gcc "defined but not used" */ LOGVV("handler %p %s", handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]); (*handler)(self); } } /* * C mterp exit point. Call here to bail out of the interpreter. */ void dvmMterpStdBail(Thread* self) { jmp_buf* pJmpBuf = (jmp_buf*) self->interpSave.bailPtr; longjmp(*pJmpBuf, 1); }