1 /*
2 * Handler function table, one entry per opcode.
3 */
4 #undef H
5 #define H(_op) (const void*) dvmMterp_##_op
6 DEFINE_GOTO_TABLE(gDvmMterpHandlers)
7
8 #undef H
9 #define H(_op) #_op
DEFINE_GOTO_TABLE(gDvmMterpHandlerNames)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->interpSave.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);
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 */
dvmMterpStdBail(Thread * self)57 void dvmMterpStdBail(Thread* self)
58 {
59 jmp_buf* pJmpBuf = (jmp_buf*) self->interpSave.bailPtr;
60 longjmp(*pJmpBuf, 1);
61 }
62