/*
* Main interpreter loop.
*
* This was written with an ARM implementation in mind.
*/
void dvmInterpretPortable(Thread* self)
{
#if defined(EASY_GDB)
StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
#endif
DvmDex* methodClassDex; // curMethod->clazz->pDvmDex
JValue retval;
/* core state */
const Method* curMethod; // method we're interpreting
const u2* pc; // program counter
u4* fp; // frame pointer
u2 inst; // current instruction
/* instruction decoding */
u4 ref; // 16 or 32-bit quantity fetched directly
u2 vsrc1, vsrc2, vdst; // usually used for register indexes
/* method call setup */
const Method* methodToCall;
bool methodCallRange;
/* static computed goto table */
DEFINE_GOTO_TABLE(handlerTable);
/* copy state in */
curMethod = self->interpSave.method;
pc = self->interpSave.pc;
fp = self->interpSave.curFrame;
retval = self->interpSave.retval; /* only need for kInterpEntryReturn? */
methodClassDex = curMethod->clazz->pDvmDex;
LOGVV("threadid=%d: %s.%s pc=%#x fp=%p",
self->threadId, curMethod->clazz->descriptor, curMethod->name,
pc - curMethod->insns, fp);
/*
* Handle any ongoing profiling and prep for debugging.
*/
if (self->interpBreak.ctl.subMode != 0) {
TRACE_METHOD_ENTER(self, curMethod);
self->debugIsMethodEntry = true; // Always true on startup
}
/*
* DEBUG: scramble this to ensure we're not relying on it.
*/
methodToCall = (const Method*) -1;
#if 0
if (self->debugIsMethodEntry) {
ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
curMethod->name);
DUMP_REGS(curMethod, self->interpSave.curFrame, false);
}
#endif
FINISH(0); /* fetch and execute first instruction */
/*--- start of opcodes ---*/