OSDN Git Service

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