1 /* 2 * Handler function table, one entry per opcode. 3 */ 4 #undef H 5 #define H(_op) dvmMterp_##_op 6 DEFINE_GOTO_TABLE(gDvmMterpHandlers) 7 8 #undef H 9 #define H(_op) #_op 10 DEFINE_GOTO_TABLE(gDvmMterpHandlerNames) 11 12 #include <setjmp.h> 13 14 /* 15 * C mterp entry point. This just calls the various C fallbacks, making 16 * this a slow but portable interpeter. 17 * 18 * This is only used for the "allstubs" variant. 19 */ 20 void dvmMterpStdRun(Thread* self) 21 { 22 jmp_buf jmpBuf; 23 24 self->bailPtr = &jmpBuf; 25 26 /* We exit via a longjmp */ 27 if (setjmp(jmpBuf)) { 28 LOGVV("mterp threadid=%d returning", dvmThreadSelf()->threadId); 29 return 30 } 31 32 /* run until somebody longjmp()s out */ 33 while (true) { 34 typedef void (*Handler)(Thread* self); 35 36 u2 inst = /*self->interpSave.*/pc[0]; 37 /* 38 * In mterp, dvmCheckBefore is handled via the altHandlerTable, 39 * while in the portable interpreter it is part of the handler 40 * FINISH code. For allstubs, we must do an explicit check 41 * in the interpretation loop. 42 */ 43 if (self-interpBreak.ctl.subMode) { 44 dvmCheckBefore(pc, fp, self, curMethod); 45 } 46 Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff]; 47 (void) gDvmMterpHandlerNames; /* avoid gcc "defined but not used" */ 48 LOGVV("handler %p %s", 49 handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]); 50 (*handler)(self); 51 } 52 } 53 54 /* 55 * C mterp exit point. Call here to bail out of the interpreter. 56 */ 57 void dvmMterpStdBail(Thread* self) 58 { 59 jmp_buf* pJmpBuf = self->bailPtr; 60 longjmp(*pJmpBuf, 1); 61 } 62