1 /*
2 * Main interpreter loop.
3 *
4 * This was written with an ARM implementation in mind.
5 */
INTERP_FUNC_NAME(Thread * self,InterpState * interpState)6 bool INTERP_FUNC_NAME(Thread* self, InterpState* interpState)
7 {
8 #if defined(EASY_GDB)
9 StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame);
10 #endif
11 #if INTERP_TYPE == INTERP_DBG
12 bool debugIsMethodEntry = false;
13 debugIsMethodEntry = interpState->debugIsMethodEntry;
14 #endif
15 #if defined(WITH_TRACKREF_CHECKS)
16 int debugTrackedRefStart = interpState->debugTrackedRefStart;
17 #endif
18 DvmDex* methodClassDex; // curMethod->clazz->pDvmDex
19 JValue retval;
20
21 /* core state */
22 const Method* curMethod; // method we're interpreting
23 const u2* pc; // program counter
24 u4* fp; // frame pointer
25 u2 inst; // current instruction
26 /* instruction decoding */
27 u2 ref; // 16-bit quantity fetched directly
28 u2 vsrc1, vsrc2, vdst; // usually used for register indexes
29 /* method call setup */
30 const Method* methodToCall;
31 bool methodCallRange;
32
33
34 #if defined(THREADED_INTERP)
35 /* static computed goto table */
36 DEFINE_GOTO_TABLE(handlerTable);
37 #endif
38
39 #if defined(WITH_JIT)
40 #if 0
41 LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
42 interpState->entryPoint,
43 interpState->pc,
44 interpState->method->name);
45 #endif
46 #if INTERP_TYPE == INTERP_DBG
47 const ClassObject* callsiteClass = NULL;
48
49 #if defined(WITH_SELF_VERIFICATION)
50 if (interpState->jitState != kJitSelfVerification) {
51 interpState->self->shadowSpace->jitExitState = kSVSIdle;
52 }
53 #endif
54
55 /* Check to see if we've got a trace selection request. */
56 if (
57 /*
58 * Only perform dvmJitCheckTraceRequest if the entry point is
59 * EntryInstr and the jit state is either kJitTSelectRequest or
60 * kJitTSelectRequestHot. If debugger/profiler happens to be attached,
61 * dvmJitCheckTraceRequest will change the jitState to kJitDone but
62 * but stay in the dbg interpreter.
63 */
64 (interpState->entryPoint == kInterpEntryInstr) &&
65 (interpState->jitState == kJitTSelectRequest ||
66 interpState->jitState == kJitTSelectRequestHot) &&
67 dvmJitCheckTraceRequest(self, interpState)) {
68 interpState->nextMode = INTERP_STD;
69 //LOGD("Invalid trace request, exiting\n");
70 return true;
71 }
72 #endif /* INTERP_TYPE == INTERP_DBG */
73 #endif /* WITH_JIT */
74
75 /* copy state in */
76 curMethod = interpState->method;
77 pc = interpState->pc;
78 fp = interpState->fp;
79 retval = interpState->retval; /* only need for kInterpEntryReturn? */
80
81 methodClassDex = curMethod->clazz->pDvmDex;
82
83 LOGVV("threadid=%d: entry(%s) %s.%s pc=0x%x fp=%p ep=%d\n",
84 self->threadId, (interpState->nextMode == INTERP_STD) ? "STD" : "DBG",
85 curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns,
86 fp, interpState->entryPoint);
87
88 /*
89 * DEBUG: scramble this to ensure we're not relying on it.
90 */
91 methodToCall = (const Method*) -1;
92
93 #if INTERP_TYPE == INTERP_DBG
94 if (debugIsMethodEntry) {
95 ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
96 curMethod->name);
97 DUMP_REGS(curMethod, interpState->fp, false);
98 }
99 #endif
100
101 switch (interpState->entryPoint) {
102 case kInterpEntryInstr:
103 /* just fall through to instruction loop or threaded kickstart */
104 break;
105 case kInterpEntryReturn:
106 CHECK_JIT_VOID();
107 goto returnFromMethod;
108 case kInterpEntryThrow:
109 goto exceptionThrown;
110 default:
111 dvmAbort();
112 }
113
114 #ifdef THREADED_INTERP
115 FINISH(0); /* fetch and execute first instruction */
116 #else
117 while (1) {
118 CHECK_DEBUG_AND_PROF(); /* service debugger and profiling */
119 CHECK_TRACKED_REFS(); /* check local reference tracking */
120
121 /* fetch the next 16 bits from the instruction stream */
122 inst = FETCH(0);
123
124 switch (INST_INST(inst)) {
125 #endif
126
127 /*--- start of opcodes ---*/
128