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