OSDN Git Service

Fix implicit conversions, rename reserved works, enable -Wc++-compat.
[android-x86/dalvik.git] / vm / interp / Interp.c
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Main interpreter entry point and support functions.
19  *
20  * The entry point selects the "standard" or "debug" interpreter and
21  * facilitates switching between them.  The standard interpreter may
22  * use the "fast" or "portable" implementation.
23  *
24  * Some debugger support functions are included here.
25  */
26 #include "Dalvik.h"
27 #include "interp/InterpDefs.h"
28
29
30 /*
31  * ===========================================================================
32  *      Debugger support
33  * ===========================================================================
34  */
35
36 // fwd
37 static BreakpointSet* dvmBreakpointSetAlloc(void);
38 static void dvmBreakpointSetFree(BreakpointSet* pSet);
39
40 /*
41  * Initialize global breakpoint structures.
42  */
43 bool dvmBreakpointStartup(void)
44 {
45     gDvm.breakpointSet = dvmBreakpointSetAlloc();
46     return (gDvm.breakpointSet != NULL);
47 }
48
49 /*
50  * Free resources.
51  */
52 void dvmBreakpointShutdown(void)
53 {
54     dvmBreakpointSetFree(gDvm.breakpointSet);
55 }
56
57
58 /*
59  * This represents a breakpoint inserted in the instruction stream.
60  *
61  * The debugger may ask us to create the same breakpoint multiple times.
62  * We only remove the breakpoint when the last instance is cleared.
63  */
64 typedef struct {
65     Method*     method;                 /* method we're associated with */
66     u2*         addr;                   /* absolute memory address */
67     u1          originalOpcode;         /* original 8-bit opcode value */
68     int         setCount;               /* #of times this breakpoint was set */
69 } Breakpoint;
70
71 /*
72  * Set of breakpoints.
73  */
74 struct BreakpointSet {
75     /* grab lock before reading or writing anything else in here */
76     pthread_mutex_t lock;
77
78     /* vector of breakpoint structures */
79     int         alloc;
80     int         count;
81     Breakpoint* breakpoints;
82 };
83
84 /*
85  * Initialize a BreakpointSet.  Initially empty.
86  */
87 static BreakpointSet* dvmBreakpointSetAlloc(void)
88 {
89     BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
90
91     dvmInitMutex(&pSet->lock);
92     /* leave the rest zeroed -- will alloc on first use */
93
94     return pSet;
95 }
96
97 /*
98  * Free storage associated with a BreakpointSet.
99  */
100 static void dvmBreakpointSetFree(BreakpointSet* pSet)
101 {
102     if (pSet == NULL)
103         return;
104
105     free(pSet->breakpoints);
106     free(pSet);
107 }
108
109 /*
110  * Lock the breakpoint set.
111  *
112  * It's not currently necessary to switch to VMWAIT in the event of
113  * contention, because nothing in here can block.  However, it's possible
114  * that the bytecode-updater code could become fancier in the future, so
115  * we do the trylock dance as a bit of future-proofing.
116  */
117 static void dvmBreakpointSetLock(BreakpointSet* pSet)
118 {
119     if (dvmTryLockMutex(&pSet->lock) != 0) {
120         Thread* self = dvmThreadSelf();
121         ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
122         dvmLockMutex(&pSet->lock);
123         dvmChangeStatus(self, oldStatus);
124     }
125 }
126
127 /*
128  * Unlock the breakpoint set.
129  */
130 static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
131 {
132     dvmUnlockMutex(&pSet->lock);
133 }
134
135 /*
136  * Return the #of breakpoints.
137  */
138 static int dvmBreakpointSetCount(const BreakpointSet* pSet)
139 {
140     return pSet->count;
141 }
142
143 /*
144  * See if we already have an entry for this address.
145  *
146  * The BreakpointSet's lock must be acquired before calling here.
147  *
148  * Returns the index of the breakpoint entry, or -1 if not found.
149  */
150 static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
151 {
152     int i;
153
154     for (i = 0; i < pSet->count; i++) {
155         Breakpoint* pBreak = &pSet->breakpoints[i];
156         if (pBreak->addr == addr)
157             return i;
158     }
159
160     return -1;
161 }
162
163 /*
164  * Retrieve the opcode that was originally at the specified location.
165  *
166  * The BreakpointSet's lock must be acquired before calling here.
167  *
168  * Returns "true" with the opcode in *pOrig on success.
169  */
170 static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
171     const u2* addr, u1* pOrig)
172 {
173     int idx = dvmBreakpointSetFind(pSet, addr);
174     if (idx < 0)
175         return false;
176
177     *pOrig = pSet->breakpoints[idx].originalOpcode;
178     return true;
179 }
180
181 /*
182  * Check the opcode.  If it's a "magic" NOP, indicating the start of
183  * switch or array data in the instruction stream, we don't want to set
184  * a breakpoint.
185  *
186  * This can happen because the line number information dx generates
187  * associates the switch data with the switch statement's line number,
188  * and some debuggers put breakpoints at every address associated with
189  * a given line.  The result is that the breakpoint stomps on the NOP
190  * instruction that doubles as a data table magic number, and an explicit
191  * check in the interpreter results in an exception being thrown.
192  *
193  * We don't want to simply refuse to add the breakpoint to the table,
194  * because that confuses the housekeeping.  We don't want to reject the
195  * debugger's event request, and we want to be sure that there's exactly
196  * one un-set operation for every set op.
197  */
198 static bool instructionIsMagicNop(const u2* addr)
199 {
200     u2 curVal = *addr;
201     return ((curVal & 0xff) == OP_NOP && (curVal >> 8) != 0);
202 }
203
204 /*
205  * Add a breakpoint at a specific address.  If the address is already
206  * present in the table, this just increments the count.
207  *
208  * For a new entry, this will extract and preserve the current opcode from
209  * the instruction stream, and replace it with a breakpoint opcode.
210  *
211  * The BreakpointSet's lock must be acquired before calling here.
212  *
213  * Returns "true" on success.
214  */
215 static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
216     unsigned int instrOffset)
217 {
218     const int kBreakpointGrowth = 10;
219     const u2* addr = method->insns + instrOffset;
220     int idx = dvmBreakpointSetFind(pSet, addr);
221     Breakpoint* pBreak;
222
223     if (idx < 0) {
224         if (pSet->count == pSet->alloc) {
225             int newSize = pSet->alloc + kBreakpointGrowth;
226             Breakpoint* newVec;
227
228             LOGV("+++ increasing breakpoint set size to %d\n", newSize);
229
230             /* pSet->breakpoints will be NULL on first entry */
231             newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
232             if (newVec == NULL)
233                 return false;
234
235             pSet->breakpoints = newVec;
236             pSet->alloc = newSize;
237         }
238
239         pBreak = &pSet->breakpoints[pSet->count++];
240         pBreak->method = method;
241         pBreak->addr = (u2*)addr;
242         pBreak->originalOpcode = *(u1*)addr;
243         pBreak->setCount = 1;
244
245         /*
246          * Change the opcode.  We must ensure that the BreakpointSet
247          * updates happen before we change the opcode.
248          *
249          * If the method has not been verified, we do NOT insert the
250          * breakpoint yet, since that will screw up the verifier.  The
251          * debugger is allowed to insert breakpoints in unverified code,
252          * but since we don't execute unverified code we don't need to
253          * alter the bytecode yet.
254          *
255          * The class init code will "flush" all pending opcode writes
256          * before verification completes.
257          */
258         assert(*(u1*)addr != OP_BREAKPOINT);
259         if (dvmIsClassVerified(method->clazz)) {
260             LOGV("Class %s verified, adding breakpoint at %p\n",
261                 method->clazz->descriptor, addr);
262             if (instructionIsMagicNop(addr)) {
263                 LOGV("Refusing to set breakpoint on %04x at %s.%s + 0x%x\n",
264                     *addr, method->clazz->descriptor, method->name,
265                     instrOffset);
266             } else {
267                 ANDROID_MEMBAR_FULL();
268                 dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
269                     OP_BREAKPOINT);
270             }
271         } else {
272             LOGV("Class %s NOT verified, deferring breakpoint at %p\n",
273                 method->clazz->descriptor, addr);
274         }
275     } else {
276         /*
277          * Breakpoint already exists, just increase the count.
278          */
279         pBreak = &pSet->breakpoints[idx];
280         pBreak->setCount++;
281     }
282
283     return true;
284 }
285
286 /*
287  * Remove one instance of the specified breakpoint.  When the count
288  * reaches zero, the entry is removed from the table, and the original
289  * opcode is restored.
290  *
291  * The BreakpointSet's lock must be acquired before calling here.
292  */
293 static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
294     unsigned int instrOffset)
295 {
296     const u2* addr = method->insns + instrOffset;
297     int idx = dvmBreakpointSetFind(pSet, addr);
298
299     if (idx < 0) {
300         /* breakpoint not found in set -- unexpected */
301         if (*(u1*)addr == OP_BREAKPOINT) {
302             LOGE("Unable to restore breakpoint opcode (%s.%s +0x%x)\n",
303                 method->clazz->descriptor, method->name, instrOffset);
304             dvmAbort();
305         } else {
306             LOGW("Breakpoint was already restored? (%s.%s +0x%x)\n",
307                 method->clazz->descriptor, method->name, instrOffset);
308         }
309     } else {
310         Breakpoint* pBreak = &pSet->breakpoints[idx];
311         if (pBreak->setCount == 1) {
312             /*
313              * Must restore opcode before removing set entry.
314              *
315              * If the breakpoint was never flushed, we could be ovewriting
316              * a value with the same value.  Not a problem, though we
317              * could end up causing a copy-on-write here when we didn't
318              * need to.  (Not worth worrying about.)
319              */
320             dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
321                 pBreak->originalOpcode);
322             ANDROID_MEMBAR_FULL();
323
324             if (idx != pSet->count-1) {
325                 /* shift down */
326                 memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
327                     (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
328             }
329             pSet->count--;
330             pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
331         } else {
332             pBreak->setCount--;
333             assert(pBreak->setCount > 0);
334         }
335     }
336 }
337
338 /*
339  * Flush any breakpoints associated with methods in "clazz".  We want to
340  * change the opcode, which might not have happened when the breakpoint
341  * was initially set because the class was in the process of being
342  * verified.
343  *
344  * The BreakpointSet's lock must be acquired before calling here.
345  */
346 static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
347 {
348     int i;
349     for (i = 0; i < pSet->count; i++) {
350         Breakpoint* pBreak = &pSet->breakpoints[i];
351         if (pBreak->method->clazz == clazz) {
352             /*
353              * The breakpoint is associated with a method in this class.
354              * It might already be there or it might not; either way,
355              * flush it out.
356              */
357             LOGV("Flushing breakpoint at %p for %s\n",
358                 pBreak->addr, clazz->descriptor);
359             if (instructionIsMagicNop(pBreak->addr)) {
360                 LOGV("Refusing to flush breakpoint on %04x at %s.%s + 0x%x\n",
361                     *pBreak->addr, pBreak->method->clazz->descriptor,
362                     pBreak->method->name, pBreak->addr - pBreak->method->insns);
363             } else {
364                 dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
365                     OP_BREAKPOINT);
366             }
367         }
368     }
369 }
370
371
372 /*
373  * Do any debugger-attach-time initialization.
374  */
375 void dvmInitBreakpoints(void)
376 {
377     /* quick sanity check */
378     BreakpointSet* pSet = gDvm.breakpointSet;
379     dvmBreakpointSetLock(pSet);
380     if (dvmBreakpointSetCount(pSet) != 0) {
381         LOGW("WARNING: %d leftover breakpoints\n", dvmBreakpointSetCount(pSet));
382         /* generally not good, but we can keep going */
383     }
384     dvmBreakpointSetUnlock(pSet);
385 }
386
387 /*
388  * Add an address to the list, putting it in the first non-empty slot.
389  *
390  * Sometimes the debugger likes to add two entries for one breakpoint.
391  * We add two entries here, so that we get the right behavior when it's
392  * removed twice.
393  *
394  * This will only be run from the JDWP thread, and it will happen while
395  * we are updating the event list, which is synchronized.  We're guaranteed
396  * to be the only one adding entries, and the lock ensures that nobody
397  * will be trying to remove them while we're in here.
398  *
399  * "addr" is the absolute address of the breakpoint bytecode.
400  */
401 void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
402 {
403     BreakpointSet* pSet = gDvm.breakpointSet;
404     dvmBreakpointSetLock(pSet);
405     dvmBreakpointSetAdd(pSet, method, instrOffset);
406     dvmBreakpointSetUnlock(pSet);
407 }
408
409 /*
410  * Remove an address from the list by setting the entry to NULL.
411  *
412  * This can be called from the JDWP thread (because the debugger has
413  * cancelled the breakpoint) or from an event thread (because it's a
414  * single-shot breakpoint, e.g. "run to line").  We only get here as
415  * the result of removing an entry from the event list, which is
416  * synchronized, so it should not be possible for two threads to be
417  * updating breakpoints at the same time.
418  */
419 void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
420 {
421     BreakpointSet* pSet = gDvm.breakpointSet;
422     dvmBreakpointSetLock(pSet);
423     dvmBreakpointSetRemove(pSet, method, instrOffset);
424     dvmBreakpointSetUnlock(pSet);
425 }
426
427 /*
428  * Get the original opcode from under a breakpoint.
429  *
430  * On SMP hardware it's possible one core might try to execute a breakpoint
431  * after another core has cleared it.  We need to handle the case where
432  * there's no entry in the breakpoint set.  (The memory barriers in the
433  * locks and in the breakpoint update code should ensure that, once we've
434  * observed the absence of a breakpoint entry, we will also now observe
435  * the restoration of the original opcode.  The fact that we're holding
436  * the lock prevents other threads from confusing things further.)
437  */
438 u1 dvmGetOriginalOpcode(const u2* addr)
439 {
440     BreakpointSet* pSet = gDvm.breakpointSet;
441     u1 orig = 0;
442
443     dvmBreakpointSetLock(pSet);
444     if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
445         orig = *(u1*)addr;
446         if (orig == OP_BREAKPOINT) {
447             LOGE("GLITCH: can't find breakpoint, opcode is still set\n");
448             dvmAbort();
449         }
450     }
451     dvmBreakpointSetUnlock(pSet);
452
453     return orig;
454 }
455
456 /*
457  * Flush any breakpoints associated with methods in "clazz".
458  *
459  * We don't want to modify the bytecode of a method before the verifier
460  * gets a chance to look at it, so we postpone opcode replacement until
461  * after verification completes.
462  */
463 void dvmFlushBreakpoints(ClassObject* clazz)
464 {
465     BreakpointSet* pSet = gDvm.breakpointSet;
466
467     if (pSet == NULL)
468         return;
469
470     assert(dvmIsClassVerified(clazz));
471     dvmBreakpointSetLock(pSet);
472     dvmBreakpointSetFlush(pSet, clazz);
473     dvmBreakpointSetUnlock(pSet);
474 }
475
476 /*
477  * Add a single step event.  Currently this is a global item.
478  *
479  * We set up some initial values based on the thread's current state.  This
480  * won't work well if the thread is running, so it's up to the caller to
481  * verify that it's suspended.
482  *
483  * This is only called from the JDWP thread.
484  */
485 bool dvmAddSingleStep(Thread* thread, int size, int depth)
486 {
487     StepControl* pCtrl = &gDvm.stepControl;
488
489     if (pCtrl->active && thread != pCtrl->thread) {
490         LOGW("WARNING: single-step active for %p; adding %p\n",
491             pCtrl->thread, thread);
492
493         /*
494          * Keep going, overwriting previous.  This can happen if you
495          * suspend a thread in Object.wait, hit the single-step key, then
496          * switch to another thread and do the same thing again.
497          * The first thread's step is still pending.
498          *
499          * TODO: consider making single-step per-thread.  Adds to the
500          * overhead, but could be useful in rare situations.
501          */
502     }
503
504     pCtrl->size = size;
505     pCtrl->depth = depth;
506     pCtrl->thread = thread;
507
508     /*
509      * We may be stepping into or over method calls, or running until we
510      * return from the current method.  To make this work we need to track
511      * the current line, current method, and current stack depth.  We need
512      * to be checking these after most instructions, notably those that
513      * call methods, return from methods, or are on a different line from the
514      * previous instruction.
515      *
516      * We have to start with a snapshot of the current state.  If we're in
517      * an interpreted method, everything we need is in the current frame.  If
518      * we're in a native method, possibly with some extra JNI frames pushed
519      * on by PushLocalFrame, we want to use the topmost native method.
520      */
521     const StackSaveArea* saveArea;
522     void* fp;
523     void* prevFp = NULL;
524
525     for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
526         const Method* method;
527
528         saveArea = SAVEAREA_FROM_FP(fp);
529         method = saveArea->method;
530
531         if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
532             break;
533         prevFp = fp;
534     }
535     if (fp == NULL) {
536         LOGW("Unexpected: step req in native-only threadid=%d\n",
537             thread->threadId);
538         return false;
539     }
540     if (prevFp != NULL) {
541         /*
542          * First interpreted frame wasn't the one at the bottom.  Break
543          * frames are only inserted when calling from native->interp, so we
544          * don't need to worry about one being here.
545          */
546         LOGV("##### init step while in native method\n");
547         fp = prevFp;
548         assert(!dvmIsBreakFrame((u4*)fp));
549         assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
550         saveArea = SAVEAREA_FROM_FP(fp);
551     }
552
553     /*
554      * Pull the goodies out.  "xtra.currentPc" should be accurate since
555      * we update it on every instruction while the debugger is connected.
556      */
557     pCtrl->method = saveArea->method;
558     // Clear out any old address set
559     if (pCtrl->pAddressSet != NULL) {
560         // (discard const)
561         free((void *)pCtrl->pAddressSet);
562         pCtrl->pAddressSet = NULL;
563     }
564     if (dvmIsNativeMethod(pCtrl->method)) {
565         pCtrl->line = -1;
566     } else {
567         pCtrl->line = dvmLineNumFromPC(saveArea->method,
568                         saveArea->xtra.currentPc - saveArea->method->insns);
569         pCtrl->pAddressSet
570                 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
571     }
572     pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
573     pCtrl->active = true;
574
575     LOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s\n",
576         pCtrl->thread, pCtrl->method, pCtrl->method->name,
577         pCtrl->line, pCtrl->frameDepth,
578         dvmJdwpStepDepthStr(pCtrl->depth),
579         dvmJdwpStepSizeStr(pCtrl->size));
580
581     return true;
582 }
583
584 /*
585  * Disable a single step event.
586  */
587 void dvmClearSingleStep(Thread* thread)
588 {
589     UNUSED_PARAMETER(thread);
590
591     gDvm.stepControl.active = false;
592 }
593
594
595 /*
596  * Recover the "this" pointer from the current interpreted method.  "this"
597  * is always in "in0" for non-static methods.
598  *
599  * The "ins" start at (#of registers - #of ins).  Note in0 != v0.
600  *
601  * This works because "dx" guarantees that it will work.  It's probably
602  * fairly common to have a virtual method that doesn't use its "this"
603  * pointer, in which case we're potentially wasting a register.  However,
604  * the debugger doesn't treat "this" as just another argument.  For
605  * example, events (such as breakpoints) can be enabled for specific
606  * values of "this".  There is also a separate StackFrame.ThisObject call
607  * in JDWP that is expected to work for any non-native non-static method.
608  *
609  * Because we need it when setting up debugger event filters, we want to
610  * be able to do this quickly.
611  */
612 Object* dvmGetThisPtr(const Method* method, const u4* fp)
613 {
614     if (dvmIsStaticMethod(method))
615         return NULL;
616     return (Object*)fp[method->registersSize - method->insSize];
617 }
618
619
620 #if defined(WITH_TRACKREF_CHECKS)
621 /*
622  * Verify that all internally-tracked references have been released.  If
623  * they haven't, print them and abort the VM.
624  *
625  * "debugTrackedRefStart" indicates how many refs were on the list when
626  * we were first invoked.
627  */
628 void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
629     int debugTrackedRefStart)
630 {
631     if (dvmReferenceTableEntries(&self->internalLocalRefTable)
632         != (size_t) debugTrackedRefStart)
633     {
634         char* desc;
635         Object** top;
636         int count;
637
638         count = dvmReferenceTableEntries(&self->internalLocalRefTable);
639
640         LOGE("TRACK: unreleased internal reference (prev=%d total=%d)\n",
641             debugTrackedRefStart, count);
642         desc = dexProtoCopyMethodDescriptor(&method->prototype);
643         LOGE("       current method is %s.%s %s\n", method->clazz->descriptor,
644             method->name, desc);
645         free(desc);
646         top = self->internalLocalRefTable.table + debugTrackedRefStart;
647         while (top < self->internalLocalRefTable.nextEntry) {
648             LOGE("  %p (%s)\n",
649                  *top,
650                  ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
651             top++;
652         }
653         dvmDumpThread(self, false);
654
655         dvmAbort();
656     }
657     //LOGI("TRACK OK\n");
658 }
659 #endif
660
661
662 #ifdef LOG_INSTR
663 /*
664  * Dump the v-registers.  Sent to the ILOG log tag.
665  */
666 void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
667 {
668     int i, localCount;
669
670     localCount = method->registersSize - method->insSize;
671
672     LOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):\n", framePtr);
673     for (i = method->registersSize-1; i >= 0; i--) {
674         if (i >= localCount) {
675             LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d in%-2d : 0x%08x\n",
676                 i, i-localCount, framePtr[i]);
677         } else {
678             if (inOnly) {
679                 LOG(LOG_VERBOSE, LOG_TAG"i", "  [...]\n");
680                 break;
681             }
682             const char* name = "";
683 #if 0   // "locals" structure has changed -- need to rewrite this
684             int j;
685             DexFile* pDexFile = method->clazz->pDexFile;
686             const DexCode* pDexCode = dvmGetMethodCode(method);
687             int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
688             const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
689             for (j = 0; j < localsSize, j++) {
690                 if (locals[j].registerNum == (u4) i) {
691                     name = dvmDexStringStr(locals[j].pName);
692                     break;
693                 }
694             }
695 #endif
696             LOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d      : 0x%08x %s\n",
697                 i, framePtr[i], name);
698         }
699     }
700 }
701 #endif
702
703
704 /*
705  * ===========================================================================
706  *      Entry point and general support functions
707  * ===========================================================================
708  */
709
710 /*
711  * Construct an s4 from two consecutive half-words of switch data.
712  * This needs to check endianness because the DEX optimizer only swaps
713  * half-words in instruction stream.
714  *
715  * "switchData" must be 32-bit aligned.
716  */
717 #if __BYTE_ORDER == __LITTLE_ENDIAN
718 static inline s4 s4FromSwitchData(const void* switchData) {
719     return *(s4*) switchData;
720 }
721 #else
722 static inline s4 s4FromSwitchData(const void* switchData) {
723     u2* data = switchData;
724     return data[0] | (((s4) data[1]) << 16);
725 }
726 #endif
727
728 /*
729  * Find the matching case.  Returns the offset to the handler instructions.
730  *
731  * Returns 3 if we don't find a match (it's the size of the packed-switch
732  * instruction).
733  */
734 s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
735 {
736     const int kInstrLen = 3;
737     u2 size;
738     s4 firstKey;
739     const s4* entries;
740
741     /*
742      * Packed switch data format:
743      *  ushort ident = 0x0100   magic value
744      *  ushort size             number of entries in the table
745      *  int first_key           first (and lowest) switch case value
746      *  int targets[size]       branch targets, relative to switch opcode
747      *
748      * Total size is (4+size*2) 16-bit code units.
749      */
750     if (*switchData++ != kPackedSwitchSignature) {
751         /* should have been caught by verifier */
752         dvmThrowException("Ljava/lang/InternalError;",
753             "bad packed switch magic");
754         return kInstrLen;
755     }
756
757     size = *switchData++;
758     assert(size > 0);
759
760     firstKey = *switchData++;
761     firstKey |= (*switchData++) << 16;
762
763     if (testVal < firstKey || testVal >= firstKey + size) {
764         LOGVV("Value %d not found in switch (%d-%d)\n",
765             testVal, firstKey, firstKey+size-1);
766         return kInstrLen;
767     }
768
769     /* The entries are guaranteed to be aligned on a 32-bit boundary;
770      * we can treat them as a native int array.
771      */
772     entries = (const s4*) switchData;
773     assert(((u4)entries & 0x3) == 0);
774
775     assert(testVal - firstKey >= 0 && testVal - firstKey < size);
776     LOGVV("Value %d found in slot %d (goto 0x%02x)\n",
777         testVal, testVal - firstKey,
778         s4FromSwitchData(&entries[testVal - firstKey]));
779     return s4FromSwitchData(&entries[testVal - firstKey]);
780 }
781
782 /*
783  * Find the matching case.  Returns the offset to the handler instructions.
784  *
785  * Returns 3 if we don't find a match (it's the size of the sparse-switch
786  * instruction).
787  */
788 s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
789 {
790     const int kInstrLen = 3;
791     u2 size;
792     const s4* keys;
793     const s4* entries;
794
795     /*
796      * Sparse switch data format:
797      *  ushort ident = 0x0200   magic value
798      *  ushort size             number of entries in the table; > 0
799      *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
800      *  int targets[size]       branch targets, relative to switch opcode
801      *
802      * Total size is (2+size*4) 16-bit code units.
803      */
804
805     if (*switchData++ != kSparseSwitchSignature) {
806         /* should have been caught by verifier */
807         dvmThrowException("Ljava/lang/InternalError;",
808             "bad sparse switch magic");
809         return kInstrLen;
810     }
811
812     size = *switchData++;
813     assert(size > 0);
814
815     /* The keys are guaranteed to be aligned on a 32-bit boundary;
816      * we can treat them as a native int array.
817      */
818     keys = (const s4*) switchData;
819     assert(((u4)keys & 0x3) == 0);
820
821     /* The entries are guaranteed to be aligned on a 32-bit boundary;
822      * we can treat them as a native int array.
823      */
824     entries = keys + size;
825     assert(((u4)entries & 0x3) == 0);
826
827     /*
828      * Binary-search through the array of keys, which are guaranteed to
829      * be sorted low-to-high.
830      */
831     int lo = 0;
832     int hi = size - 1;
833     while (lo <= hi) {
834         int mid = (lo + hi) >> 1;
835
836         s4 foundVal = s4FromSwitchData(&keys[mid]);
837         if (testVal < foundVal) {
838             hi = mid - 1;
839         } else if (testVal > foundVal) {
840             lo = mid + 1;
841         } else {
842             LOGVV("Value %d found in entry %d (goto 0x%02x)\n",
843                 testVal, mid, s4FromSwitchData(&entries[mid]));
844             return s4FromSwitchData(&entries[mid]);
845         }
846     }
847
848     LOGVV("Value %d not found in switch\n", testVal);
849     return kInstrLen;
850 }
851
852 /*
853  * Copy data for a fill-array-data instruction.  On a little-endian machine
854  * we can just do a memcpy(), on a big-endian system we have work to do.
855  *
856  * The trick here is that dexopt has byte-swapped each code unit, which is
857  * exactly what we want for short/char data.  For byte data we need to undo
858  * the swap, and for 4- or 8-byte values we need to swap pieces within
859  * each word.
860  */
861 static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
862 {
863 #if __BYTE_ORDER == __LITTLE_ENDIAN
864     memcpy(dest, src, size*width);
865 #else
866     int i;
867
868     switch (width) {
869     case 1:
870         /* un-swap pairs of bytes as we go */
871         for (i = (size-1) & ~1; i >= 0; i -= 2) {
872             ((u1*)dest)[i] = ((u1*)src)[i+1];
873             ((u1*)dest)[i+1] = ((u1*)src)[i];
874         }
875         /*
876          * "src" is padded to end on a two-byte boundary, but we don't want to
877          * assume "dest" is, so we handle odd length specially.
878          */
879         if ((size & 1) != 0) {
880             ((u1*)dest)[size-1] = ((u1*)src)[size];
881         }
882         break;
883     case 2:
884         /* already swapped correctly */
885         memcpy(dest, src, size*width);
886         break;
887     case 4:
888         /* swap word halves */
889         for (i = 0; i < (int) size; i++) {
890             ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
891         }
892         break;
893     case 8:
894         /* swap word halves and words */
895         for (i = 0; i < (int) (size << 1); i += 2) {
896             ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
897             ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
898         }
899         break;
900     default:
901         LOGE("Unexpected width %d in copySwappedArrayData\n", width);
902         dvmAbort();
903         break;
904     }
905 #endif
906 }
907
908 /*
909  * Fill the array with predefined constant values.
910  *
911  * Returns true if job is completed, otherwise false to indicate that
912  * an exception has been thrown.
913  */
914 bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
915 {
916     u2 width;
917     u4 size;
918
919     if (arrayObj == NULL) {
920         dvmThrowException("Ljava/lang/NullPointerException;", NULL);
921         return false;
922     }
923     assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
924                                CLASS_ISOBJECTARRAY));
925
926     /*
927      * Array data table format:
928      *  ushort ident = 0x0300   magic value
929      *  ushort width            width of each element in the table
930      *  uint   size             number of elements in the table
931      *  ubyte  data[size*width] table of data values (may contain a single-byte
932      *                          padding at the end)
933      *
934      * Total size is 4+(width * size + 1)/2 16-bit code units.
935      */
936     if (arrayData[0] != kArrayDataSignature) {
937         dvmThrowException("Ljava/lang/InternalError;", "bad array data magic");
938         return false;
939     }
940
941     width = arrayData[1];
942     size = arrayData[2] | (((u4)arrayData[3]) << 16);
943
944     if (size > arrayObj->length) {
945         dvmThrowAIOOBE(size, arrayObj->length);
946         return false;
947     }
948     copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
949     return true;
950 }
951
952 /*
953  * Find the concrete method that corresponds to "methodIdx".  The code in
954  * "method" is executing invoke-method with "thisClass" as its first argument.
955  *
956  * Returns NULL with an exception raised on failure.
957  */
958 Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
959     const Method* method, DvmDex* methodClassDex)
960 {
961     Method* absMethod;
962     Method* methodToCall;
963     int i, vtableIndex;
964
965     /*
966      * Resolve the method.  This gives us the abstract method from the
967      * interface class declaration.
968      */
969     absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
970     if (absMethod == NULL) {
971         absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
972         if (absMethod == NULL) {
973             LOGV("+ unknown method\n");
974             return NULL;
975         }
976     }
977
978     /* make sure absMethod->methodIndex means what we think it means */
979     assert(dvmIsAbstractMethod(absMethod));
980
981     /*
982      * Run through the "this" object's iftable.  Find the entry for
983      * absMethod's class, then use absMethod->methodIndex to find
984      * the method's entry.  The value there is the offset into our
985      * vtable of the actual method to execute.
986      *
987      * The verifier does not guarantee that objects stored into
988      * interface references actually implement the interface, so this
989      * check cannot be eliminated.
990      */
991     for (i = 0; i < thisClass->iftableCount; i++) {
992         if (thisClass->iftable[i].clazz == absMethod->clazz)
993             break;
994     }
995     if (i == thisClass->iftableCount) {
996         /* impossible in verified DEX, need to check for it in unverified */
997         dvmThrowException("Ljava/lang/IncompatibleClassChangeError;",
998             "interface not implemented");
999         return NULL;
1000     }
1001
1002     assert(absMethod->methodIndex <
1003         thisClass->iftable[i].clazz->virtualMethodCount);
1004
1005     vtableIndex =
1006         thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
1007     assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
1008     methodToCall = thisClass->vtable[vtableIndex];
1009
1010 #if 0
1011     /* this can happen when there's a stale class file */
1012     if (dvmIsAbstractMethod(methodToCall)) {
1013         dvmThrowException("Ljava/lang/AbstractMethodError;",
1014             "interface method not implemented");
1015         return NULL;
1016     }
1017 #else
1018     assert(!dvmIsAbstractMethod(methodToCall) ||
1019         methodToCall->nativeFunc != NULL);
1020 #endif
1021
1022     LOGVV("+++ interface=%s.%s concrete=%s.%s\n",
1023         absMethod->clazz->descriptor, absMethod->name,
1024         methodToCall->clazz->descriptor, methodToCall->name);
1025     assert(methodToCall != NULL);
1026
1027     return methodToCall;
1028 }
1029
1030
1031
1032 /*
1033  * Helpers for dvmThrowVerificationError().
1034  *
1035  * Each returns a newly-allocated string.
1036  */
1037 #define kThrowShow_accessFromClass     1
1038 static char* classNameFromIndex(const Method* method, int ref,
1039     VerifyErrorRefType refType, int flags)
1040 {
1041     static const int kBufLen = 256;
1042     const DvmDex* pDvmDex = method->clazz->pDvmDex;
1043
1044     if (refType == VERIFY_ERROR_REF_FIELD) {
1045         /* get class ID from field ID */
1046         const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1047         ref = pFieldId->classIdx;
1048     } else if (refType == VERIFY_ERROR_REF_METHOD) {
1049         /* get class ID from method ID */
1050         const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1051         ref = pMethodId->classIdx;
1052     }
1053
1054     const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
1055     char* dotClassName = dvmHumanReadableDescriptor(className);
1056     if (flags == 0)
1057         return dotClassName;
1058
1059     char* result = (char*) malloc(kBufLen);
1060
1061     if ((flags & kThrowShow_accessFromClass) != 0) {
1062         char* dotFromName =
1063             dvmHumanReadableDescriptor(method->clazz->descriptor);
1064         snprintf(result, kBufLen, "tried to access class %s from class %s",
1065             dotClassName, dotFromName);
1066         free(dotFromName);
1067     } else {
1068         assert(false);      // should've been caught above
1069         result[0] = '\0';
1070     }
1071
1072     free(dotClassName);
1073     return result;
1074 }
1075 static char* fieldNameFromIndex(const Method* method, int ref,
1076     VerifyErrorRefType refType, int flags)
1077 {
1078     static const int kBufLen = 256;
1079     const DvmDex* pDvmDex = method->clazz->pDvmDex;
1080     const DexFieldId* pFieldId;
1081     const char* className;
1082     const char* fieldName;
1083
1084     if (refType != VERIFY_ERROR_REF_FIELD) {
1085         LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
1086         return NULL;    /* no message */
1087     }
1088
1089     pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
1090     className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
1091     fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
1092
1093     char* dotName = dvmHumanReadableDescriptor(className);
1094     char* result = (char*) malloc(kBufLen);
1095
1096     if ((flags & kThrowShow_accessFromClass) != 0) {
1097         char* dotFromName =
1098             dvmHumanReadableDescriptor(method->clazz->descriptor);
1099         snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
1100             dotName, fieldName, dotFromName);
1101         free(dotFromName);
1102     } else {
1103         snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
1104     }
1105
1106     free(dotName);
1107     return result;
1108 }
1109 static char* methodNameFromIndex(const Method* method, int ref,
1110     VerifyErrorRefType refType, int flags)
1111 {
1112     static const int kBufLen = 384;
1113     const DvmDex* pDvmDex = method->clazz->pDvmDex;
1114     const DexMethodId* pMethodId;
1115     const char* className;
1116     const char* methodName;
1117
1118     if (refType != VERIFY_ERROR_REF_METHOD) {
1119         LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
1120         return NULL;    /* no message */
1121     }
1122
1123     pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
1124     className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
1125     methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
1126
1127     char* dotName = dvmHumanReadableDescriptor(className);
1128     char* result = (char*) malloc(kBufLen);
1129
1130     if ((flags & kThrowShow_accessFromClass) != 0) {
1131         char* dotFromName =
1132             dvmHumanReadableDescriptor(method->clazz->descriptor);
1133         char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1134         snprintf(result, kBufLen,
1135             "tried to access method %s.%s:%s from class %s",
1136             dotName, methodName, desc, dotFromName);
1137         free(dotFromName);
1138         free(desc);
1139     } else {
1140         snprintf(result, kBufLen, "%s.%s", dotName, methodName);
1141     }
1142
1143     free(dotName);
1144     return result;
1145 }
1146
1147 /*
1148  * Throw an exception for a problem identified by the verifier.
1149  *
1150  * This is used by the invoke-verification-error instruction.  It always
1151  * throws an exception.
1152  *
1153  * "kind" indicates the kind of failure encountered by the verifier.  It
1154  * has two parts, an error code and an indication of the reference type.
1155  */
1156 void dvmThrowVerificationError(const Method* method, int kind, int ref)
1157 {
1158     const int typeMask = 0xff << kVerifyErrorRefTypeShift;
1159     VerifyError errorKind = kind & ~typeMask;
1160     VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
1161     const char* exceptionName = "Ljava/lang/VerifyError;";
1162     char* msg = NULL;
1163
1164     switch ((VerifyError) errorKind) {
1165     case VERIFY_ERROR_NO_CLASS:
1166         exceptionName = "Ljava/lang/NoClassDefFoundError;";
1167         msg = classNameFromIndex(method, ref, refType, 0);
1168         break;
1169     case VERIFY_ERROR_NO_FIELD:
1170         exceptionName = "Ljava/lang/NoSuchFieldError;";
1171         msg = fieldNameFromIndex(method, ref, refType, 0);
1172         break;
1173     case VERIFY_ERROR_NO_METHOD:
1174         exceptionName = "Ljava/lang/NoSuchMethodError;";
1175         msg = methodNameFromIndex(method, ref, refType, 0);
1176         break;
1177     case VERIFY_ERROR_ACCESS_CLASS:
1178         exceptionName = "Ljava/lang/IllegalAccessError;";
1179         msg = classNameFromIndex(method, ref, refType,
1180             kThrowShow_accessFromClass);
1181         break;
1182     case VERIFY_ERROR_ACCESS_FIELD:
1183         exceptionName = "Ljava/lang/IllegalAccessError;";
1184         msg = fieldNameFromIndex(method, ref, refType,
1185             kThrowShow_accessFromClass);
1186         break;
1187     case VERIFY_ERROR_ACCESS_METHOD:
1188         exceptionName = "Ljava/lang/IllegalAccessError;";
1189         msg = methodNameFromIndex(method, ref, refType,
1190             kThrowShow_accessFromClass);
1191         break;
1192     case VERIFY_ERROR_CLASS_CHANGE:
1193         exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
1194         msg = classNameFromIndex(method, ref, refType, 0);
1195         break;
1196     case VERIFY_ERROR_INSTANTIATION:
1197         exceptionName = "Ljava/lang/InstantiationError;";
1198         msg = classNameFromIndex(method, ref, refType, 0);
1199         break;
1200
1201     case VERIFY_ERROR_GENERIC:
1202         /* generic VerifyError; use default exception, no message */
1203         break;
1204     case VERIFY_ERROR_NONE:
1205         /* should never happen; use default exception */
1206         assert(false);
1207         msg = strdup("weird - no error specified");
1208         break;
1209
1210     /* no default clause -- want warning if enum updated */
1211     }
1212
1213     dvmThrowException(exceptionName, msg);
1214     free(msg);
1215 }
1216
1217 /*
1218  * Main interpreter loop entry point.  Select "standard" or "debug"
1219  * interpreter and switch between them as required.
1220  *
1221  * This begins executing code at the start of "method".  On exit, "pResult"
1222  * holds the return value of the method (or, if "method" returns NULL, it
1223  * holds an undefined value).
1224  *
1225  * The interpreted stack frame, which holds the method arguments, has
1226  * already been set up.
1227  */
1228 void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
1229 {
1230     InterpState interpState;
1231     bool change;
1232 #if defined(WITH_JIT)
1233     /* Target-specific save/restore */
1234     extern void dvmJitCalleeSave(double *saveArea);
1235     extern void dvmJitCalleeRestore(double *saveArea);
1236     /* Interpreter entry points from compiled code */
1237     extern void dvmJitToInterpNormal();
1238     extern void dvmJitToInterpNoChain();
1239     extern void dvmJitToInterpPunt();
1240     extern void dvmJitToInterpSingleStep();
1241     extern void dvmJitToInterpTraceSelectNoChain();
1242     extern void dvmJitToInterpTraceSelect();
1243     extern void dvmJitToPatchPredictedChain();
1244 #if defined(WITH_SELF_VERIFICATION)
1245     extern void dvmJitToInterpBackwardBranch();
1246 #endif
1247
1248     /*
1249      * Reserve a static entity here to quickly setup runtime contents as
1250      * gcc will issue block copy instructions.
1251      */
1252     static struct JitToInterpEntries jitToInterpEntries = {
1253         dvmJitToInterpNormal,
1254         dvmJitToInterpNoChain,
1255         dvmJitToInterpPunt,
1256         dvmJitToInterpSingleStep,
1257         dvmJitToInterpTraceSelectNoChain,
1258         dvmJitToInterpTraceSelect,
1259         dvmJitToPatchPredictedChain,
1260 #if defined(WITH_SELF_VERIFICATION)
1261         dvmJitToInterpBackwardBranch,
1262 #endif
1263     };
1264
1265     /*
1266      * If the previous VM left the code cache through single-stepping the
1267      * inJitCodeCache flag will be set when the VM is re-entered (for example,
1268      * in self-verification mode we single-step NEW_INSTANCE which may re-enter
1269      * the VM through findClassFromLoaderNoInit). Because of that, we cannot
1270      * assert that self->inJitCodeCache is NULL here.
1271      */
1272 #endif
1273
1274
1275 #if defined(WITH_TRACKREF_CHECKS)
1276     interpState.debugTrackedRefStart =
1277         dvmReferenceTableEntries(&self->internalLocalRefTable);
1278 #endif
1279     interpState.debugIsMethodEntry = true;
1280 #if defined(WITH_JIT)
1281     dvmJitCalleeSave(interpState.calleeSave);
1282     /* Initialize the state to kJitNot */
1283     interpState.jitState = kJitNot;
1284
1285     /* Setup the Jit-to-interpreter entry points */
1286     interpState.jitToInterpEntries = jitToInterpEntries;
1287
1288     /*
1289      * Initialize the threshold filter [don't bother to zero out the
1290      * actual table.  We're looking for matches, and an occasional
1291      * false positive is acceptible.
1292      */
1293     interpState.lastThreshFilter = 0;
1294
1295     interpState.icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
1296 #endif
1297
1298     /*
1299      * Initialize working state.
1300      *
1301      * No need to initialize "retval".
1302      */
1303     interpState.method = method;
1304     interpState.fp = (u4*) self->curFrame;
1305     interpState.pc = method->insns;
1306     interpState.entryPoint = kInterpEntryInstr;
1307
1308     if (dvmDebuggerOrProfilerActive())
1309         interpState.nextMode = INTERP_DBG;
1310     else
1311         interpState.nextMode = INTERP_STD;
1312
1313     assert(!dvmIsNativeMethod(method));
1314
1315     /*
1316      * Make sure the class is ready to go.  Shouldn't be possible to get
1317      * here otherwise.
1318      */
1319     if (method->clazz->status < CLASS_INITIALIZING ||
1320         method->clazz->status == CLASS_ERROR)
1321     {
1322         LOGE("ERROR: tried to execute code in unprepared class '%s' (%d)\n",
1323             method->clazz->descriptor, method->clazz->status);
1324         dvmDumpThread(self, false);
1325         dvmAbort();
1326     }
1327
1328     typedef bool (*Interpreter)(Thread*, InterpState*);
1329     Interpreter stdInterp;
1330     if (gDvm.executionMode == kExecutionModeInterpFast)
1331         stdInterp = dvmMterpStd;
1332 #if defined(WITH_JIT)
1333     else if (gDvm.executionMode == kExecutionModeJit)
1334 /* If profiling overhead can be kept low enough, we can use a profiling
1335  * mterp fast for both Jit and "fast" modes.  If overhead is too high,
1336  * create a specialized profiling interpreter.
1337  */
1338         stdInterp = dvmMterpStd;
1339 #endif
1340     else
1341         stdInterp = dvmInterpretStd;
1342
1343     change = true;
1344     while (change) {
1345         switch (interpState.nextMode) {
1346         case INTERP_STD:
1347             LOGVV("threadid=%d: interp STD\n", self->threadId);
1348             change = (*stdInterp)(self, &interpState);
1349             break;
1350         case INTERP_DBG:
1351             LOGVV("threadid=%d: interp DBG\n", self->threadId);
1352             change = dvmInterpretDbg(self, &interpState);
1353             break;
1354         default:
1355             dvmAbort();
1356         }
1357     }
1358
1359     *pResult = interpState.retval;
1360 #if defined(WITH_JIT)
1361     dvmJitCalleeRestore(interpState.calleeSave);
1362 #endif
1363 }