/*
* 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);
}