| /* |
| * Handler function table, one entry per opcode. |
| */ |
| #undef H |
| #define H(_op) 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. |
| */ |
| bool dvmMterpStdRun(MterpGlue* glue) |
| { |
| jmp_buf jmpBuf; |
| int changeInterp; |
| |
| glue->bailPtr = &jmpBuf; |
| |
| /* |
| * We want to return "changeInterp" as a boolean, but we can't return |
| * zero through longjmp, so we return (boolean+1). |
| */ |
| changeInterp = setjmp(jmpBuf) -1; |
| if (changeInterp >= 0) { |
| Thread* threadSelf = dvmThreadSelf(); |
| LOGVV("mterp threadid=%d returning %d\n", |
| threadSelf->threadId, changeInterp); |
| return changeInterp; |
| } |
| |
| /* |
| * We may not be starting at a point where we're executing instructions. |
| * We need to pick up where the other interpreter left off. |
| * |
| * In some cases we need to call into a throw/return handler which |
| * will do some processing and then either return to us (updating "glue") |
| * or longjmp back out. |
| */ |
| switch (glue->entryPoint) { |
| case kInterpEntryInstr: |
| /* just start at the start */ |
| break; |
| case kInterpEntryReturn: |
| dvmMterp_returnFromMethod(glue); |
| break; |
| case kInterpEntryThrow: |
| dvmMterp_exceptionThrown(glue); |
| break; |
| default: |
| dvmAbort(); |
| } |
| |
| /* run until somebody longjmp()s out */ |
| while (true) { |
| typedef void (*Handler)(MterpGlue* glue); |
| |
| u2 inst = /*glue->*/pc[0]; |
| Handler handler = (Handler) gDvmMterpHandlers[inst & 0xff]; |
| LOGVV("handler %p %s\n", |
| handler, (const char*) gDvmMterpHandlerNames[inst & 0xff]); |
| (*handler)(glue); |
| } |
| } |
| |
| /* |
| * C mterp exit point. Call here to bail out of the interpreter. |
| */ |
| void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) |
| { |
| jmp_buf* pJmpBuf = glue->bailPtr; |
| longjmp(*pJmpBuf, ((int)changeInterp)+1); |
| } |
| |