Commits

RomanGol committed ed033a5

Add Dex to class.dlist tool

Linux version

  • Participants
  • Parent commits 6ebf37c

Comments (0)

Files changed (7)

dex2lst/linux/dexdeps

+#!/bin/bash
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=dexdeps.jar
+libdir="$progdir"
+if [ ! -r "$libdir/$jarfile" ]
+then
+    libdir=`dirname "$progdir"`/tools/lib
+fi
+if [ ! -r "$libdir/$jarfile" ]
+then
+    libdir=`dirname "$progdir"`/framework
+fi
+if [ ! -r "$libdir/$jarfile" ]
+then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+javaOpts=""
+
+# Alternatively, this will extract any parameter "-Jxxx" from the command line
+# and pass them to Java (instead of to dexdeps).
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+if [ "$OSTYPE" = "cygwin" ] ; then
+    jarpath=`cygpath -w  "$libdir/$jarfile"`
+else
+    jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -jar "$jarpath" "$@"

dex2lst/linux/dexdump

Binary file added.

dia/Interp.cpp

-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Main interpreter entry point and support functions.
- *
- * The entry point selects the "standard" or "debug" interpreter and
- * facilitates switching between them.  The standard interpreter may
- * use the "fast" or "portable" implementation.
- *
- * Some debugger support functions are included here.
- */
-#include "Dalvik.h"
-#include "interp/InterpDefs.h"
-#if defined(WITH_JIT)
-#include "interp/Jit.h"
-#endif
-
-#if defined(LOCCS_DIAOS)
-#include "diaos.h"
-#endif
-
-/*
- * ===========================================================================
- *      Debugger support
- * ===========================================================================
- */
-//#define LOG_INSTR
-// fwd
-static BreakpointSet* dvmBreakpointSetAlloc();
-static void dvmBreakpointSetFree(BreakpointSet* pSet);
-
-#if defined(WITH_JIT)
-/* Target-specific save/restore */
-extern "C" void dvmJitCalleeSave(double *saveArea);
-extern "C" void dvmJitCalleeRestore(double *saveArea);
-/* Interpreter entry points from compiled code */
-extern "C" void dvmJitToInterpNormal();
-extern "C" void dvmJitToInterpNoChain();
-extern "C" void dvmJitToInterpPunt();
-extern "C" void dvmJitToInterpSingleStep();
-extern "C" void dvmJitToInterpTraceSelect();
-#if defined(WITH_SELF_VERIFICATION)
-extern "C" void dvmJitToInterpBackwardBranch();
-#endif
-#endif
-
-/*
- * Initialize global breakpoint structures.
- */
-bool dvmBreakpointStartup()
-{
-    gDvm.breakpointSet = dvmBreakpointSetAlloc();
-    return (gDvm.breakpointSet != NULL);
-}
-
-/*
- * Free resources.
- */
-void dvmBreakpointShutdown()
-{
-    dvmBreakpointSetFree(gDvm.breakpointSet);
-}
-
-
-/*
- * This represents a breakpoint inserted in the instruction stream.
- *
- * The debugger may ask us to create the same breakpoint multiple times.
- * We only remove the breakpoint when the last instance is cleared.
- */
-struct Breakpoint {
-    Method*     method;                 /* method we're associated with */
-    u2*         addr;                   /* absolute memory address */
-    u1          originalOpcode;         /* original 8-bit opcode value */
-    int         setCount;               /* #of times this breakpoint was set */
-};
-
-/*
- * Set of breakpoints.
- */
-struct BreakpointSet {
-    /* grab lock before reading or writing anything else in here */
-    pthread_mutex_t lock;
-
-    /* vector of breakpoint structures */
-    int         alloc;
-    int         count;
-    Breakpoint* breakpoints;
-};
-
-/*
- * Initialize a BreakpointSet.  Initially empty.
- */
-static BreakpointSet* dvmBreakpointSetAlloc()
-{
-    BreakpointSet* pSet = (BreakpointSet*) calloc(1, sizeof(*pSet));
-
-    dvmInitMutex(&pSet->lock);
-    /* leave the rest zeroed -- will alloc on first use */
-
-    return pSet;
-}
-
-/*
- * Free storage associated with a BreakpointSet.
- */
-static void dvmBreakpointSetFree(BreakpointSet* pSet)
-{
-    if (pSet == NULL)
-        return;
-
-    free(pSet->breakpoints);
-    free(pSet);
-}
-
-/*
- * Lock the breakpoint set.
- *
- * It's not currently necessary to switch to VMWAIT in the event of
- * contention, because nothing in here can block.  However, it's possible
- * that the bytecode-updater code could become fancier in the future, so
- * we do the trylock dance as a bit of future-proofing.
- */
-static void dvmBreakpointSetLock(BreakpointSet* pSet)
-{
-    if (dvmTryLockMutex(&pSet->lock) != 0) {
-        Thread* self = dvmThreadSelf();
-        ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
-        dvmLockMutex(&pSet->lock);
-        dvmChangeStatus(self, oldStatus);
-    }
-}
-
-/*
- * Unlock the breakpoint set.
- */
-static void dvmBreakpointSetUnlock(BreakpointSet* pSet)
-{
-    dvmUnlockMutex(&pSet->lock);
-}
-
-/*
- * Return the #of breakpoints.
- */
-static int dvmBreakpointSetCount(const BreakpointSet* pSet)
-{
-    return pSet->count;
-}
-
-/*
- * See if we already have an entry for this address.
- *
- * The BreakpointSet's lock must be acquired before calling here.
- *
- * Returns the index of the breakpoint entry, or -1 if not found.
- */
-static int dvmBreakpointSetFind(const BreakpointSet* pSet, const u2* addr)
-{
-    int i;
-
-    for (i = 0; i < pSet->count; i++) {
-        Breakpoint* pBreak = &pSet->breakpoints[i];
-        if (pBreak->addr == addr)
-            return i;
-    }
-
-    return -1;
-}
-
-/*
- * Retrieve the opcode that was originally at the specified location.
- *
- * The BreakpointSet's lock must be acquired before calling here.
- *
- * Returns "true" with the opcode in *pOrig on success.
- */
-static bool dvmBreakpointSetOriginalOpcode(const BreakpointSet* pSet,
-    const u2* addr, u1* pOrig)
-{
-    int idx = dvmBreakpointSetFind(pSet, addr);
-    if (idx < 0)
-        return false;
-
-    *pOrig = pSet->breakpoints[idx].originalOpcode;
-    return true;
-}
-
-/*
- * Check the opcode.  If it's a "magic" NOP, indicating the start of
- * switch or array data in the instruction stream, we don't want to set
- * a breakpoint.
- *
- * This can happen because the line number information dx generates
- * associates the switch data with the switch statement's line number,
- * and some debuggers put breakpoints at every address associated with
- * a given line.  The result is that the breakpoint stomps on the NOP
- * instruction that doubles as a data table magic number, and an explicit
- * check in the interpreter results in an exception being thrown.
- *
- * We don't want to simply refuse to add the breakpoint to the table,
- * because that confuses the housekeeping.  We don't want to reject the
- * debugger's event request, and we want to be sure that there's exactly
- * one un-set operation for every set op.
- */
-static bool instructionIsMagicNop(const u2* addr)
-{
-    u2 curVal = *addr;
-    return ((GET_OPCODE(curVal)) == OP_NOP && (curVal >> 8) != 0);
-}
-
-/*
- * Add a breakpoint at a specific address.  If the address is already
- * present in the table, this just increments the count.
- *
- * For a new entry, this will extract and preserve the current opcode from
- * the instruction stream, and replace it with a breakpoint opcode.
- *
- * The BreakpointSet's lock must be acquired before calling here.
- *
- * Returns "true" on success.
- */
-static bool dvmBreakpointSetAdd(BreakpointSet* pSet, Method* method,
-    unsigned int instrOffset)
-{
-    const int kBreakpointGrowth = 10;
-    const u2* addr = method->insns + instrOffset;
-    int idx = dvmBreakpointSetFind(pSet, addr);
-    Breakpoint* pBreak;
-
-    if (idx < 0) {
-        if (pSet->count == pSet->alloc) {
-            int newSize = pSet->alloc + kBreakpointGrowth;
-            Breakpoint* newVec;
-
-            ALOGV("+++ increasing breakpoint set size to %d", newSize);
-
-            /* pSet->breakpoints will be NULL on first entry */
-            newVec = (Breakpoint*)realloc(pSet->breakpoints, newSize * sizeof(Breakpoint));
-            if (newVec == NULL)
-                return false;
-
-            pSet->breakpoints = newVec;
-            pSet->alloc = newSize;
-        }
-
-        pBreak = &pSet->breakpoints[pSet->count++];
-        pBreak->method = method;
-        pBreak->addr = (u2*)addr;
-        pBreak->originalOpcode = *(u1*)addr;
-        pBreak->setCount = 1;
-
-        /*
-         * Change the opcode.  We must ensure that the BreakpointSet
-         * updates happen before we change the opcode.
-         *
-         * If the method has not been verified, we do NOT insert the
-         * breakpoint yet, since that will screw up the verifier.  The
-         * debugger is allowed to insert breakpoints in unverified code,
-         * but since we don't execute unverified code we don't need to
-         * alter the bytecode yet.
-         *
-         * The class init code will "flush" all pending opcode writes
-         * before verification completes.
-         */
-        assert(*(u1*)addr != OP_BREAKPOINT);
-        if (dvmIsClassVerified(method->clazz)) {
-            ALOGV("Class %s verified, adding breakpoint at %p",
-                method->clazz->descriptor, addr);
-            if (instructionIsMagicNop(addr)) {
-                ALOGV("Refusing to set breakpoint on %04x at %s.%s + %#x",
-                    *addr, method->clazz->descriptor, method->name,
-                    instrOffset);
-            } else {
-                ANDROID_MEMBAR_FULL();
-                dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
-                    OP_BREAKPOINT);
-            }
-        } else {
-            ALOGV("Class %s NOT verified, deferring breakpoint at %p",
-                method->clazz->descriptor, addr);
-        }
-    } else {
-        /*
-         * Breakpoint already exists, just increase the count.
-         */
-        pBreak = &pSet->breakpoints[idx];
-        pBreak->setCount++;
-    }
-
-    return true;
-}
-
-/*
- * Remove one instance of the specified breakpoint.  When the count
- * reaches zero, the entry is removed from the table, and the original
- * opcode is restored.
- *
- * The BreakpointSet's lock must be acquired before calling here.
- */
-static void dvmBreakpointSetRemove(BreakpointSet* pSet, Method* method,
-    unsigned int instrOffset)
-{
-    const u2* addr = method->insns + instrOffset;
-    int idx = dvmBreakpointSetFind(pSet, addr);
-
-    if (idx < 0) {
-        /* breakpoint not found in set -- unexpected */
-        if (*(u1*)addr == OP_BREAKPOINT) {
-            ALOGE("Unable to restore breakpoint opcode (%s.%s +%#x)",
-                method->clazz->descriptor, method->name, instrOffset);
-            dvmAbort();
-        } else {
-            ALOGW("Breakpoint was already restored? (%s.%s +%#x)",
-                method->clazz->descriptor, method->name, instrOffset);
-        }
-    } else {
-        Breakpoint* pBreak = &pSet->breakpoints[idx];
-        if (pBreak->setCount == 1) {
-            /*
-             * Must restore opcode before removing set entry.
-             *
-             * If the breakpoint was never flushed, we could be ovewriting
-             * a value with the same value.  Not a problem, though we
-             * could end up causing a copy-on-write here when we didn't
-             * need to.  (Not worth worrying about.)
-             */
-            dvmDexChangeDex1(method->clazz->pDvmDex, (u1*)addr,
-                pBreak->originalOpcode);
-            ANDROID_MEMBAR_FULL();
-
-            if (idx != pSet->count-1) {
-                /* shift down */
-                memmove(&pSet->breakpoints[idx], &pSet->breakpoints[idx+1],
-                    (pSet->count-1 - idx) * sizeof(pSet->breakpoints[0]));
-            }
-            pSet->count--;
-            pSet->breakpoints[pSet->count].addr = (u2*) 0xdecadead; // debug
-        } else {
-            pBreak->setCount--;
-            assert(pBreak->setCount > 0);
-        }
-    }
-}
-
-/*
- * Flush any breakpoints associated with methods in "clazz".  We want to
- * change the opcode, which might not have happened when the breakpoint
- * was initially set because the class was in the process of being
- * verified.
- *
- * The BreakpointSet's lock must be acquired before calling here.
- */
-static void dvmBreakpointSetFlush(BreakpointSet* pSet, ClassObject* clazz)
-{
-    int i;
-    for (i = 0; i < pSet->count; i++) {
-        Breakpoint* pBreak = &pSet->breakpoints[i];
-        if (pBreak->method->clazz == clazz) {
-            /*
-             * The breakpoint is associated with a method in this class.
-             * It might already be there or it might not; either way,
-             * flush it out.
-             */
-            ALOGV("Flushing breakpoint at %p for %s",
-                pBreak->addr, clazz->descriptor);
-            if (instructionIsMagicNop(pBreak->addr)) {
-                ALOGV("Refusing to flush breakpoint on %04x at %s.%s + %#x",
-                    *pBreak->addr, pBreak->method->clazz->descriptor,
-                    pBreak->method->name, pBreak->addr - pBreak->method->insns);
-            } else {
-                dvmDexChangeDex1(clazz->pDvmDex, (u1*)pBreak->addr,
-                    OP_BREAKPOINT);
-            }
-        }
-    }
-}
-
-
-/*
- * Do any debugger-attach-time initialization.
- */
-void dvmInitBreakpoints()
-{
-    /* quick sanity check */
-    BreakpointSet* pSet = gDvm.breakpointSet;
-    dvmBreakpointSetLock(pSet);
-    if (dvmBreakpointSetCount(pSet) != 0) {
-        ALOGW("WARNING: %d leftover breakpoints", dvmBreakpointSetCount(pSet));
-        /* generally not good, but we can keep going */
-    }
-    dvmBreakpointSetUnlock(pSet);
-}
-
-/*
- * Add an address to the list, putting it in the first non-empty slot.
- *
- * Sometimes the debugger likes to add two entries for one breakpoint.
- * We add two entries here, so that we get the right behavior when it's
- * removed twice.
- *
- * This will only be run from the JDWP thread, and it will happen while
- * we are updating the event list, which is synchronized.  We're guaranteed
- * to be the only one adding entries, and the lock ensures that nobody
- * will be trying to remove them while we're in here.
- *
- * "addr" is the absolute address of the breakpoint bytecode.
- */
-void dvmAddBreakAddr(Method* method, unsigned int instrOffset)
-{
-    BreakpointSet* pSet = gDvm.breakpointSet;
-    dvmBreakpointSetLock(pSet);
-    dvmBreakpointSetAdd(pSet, method, instrOffset);
-    dvmBreakpointSetUnlock(pSet);
-}
-
-/*
- * Remove an address from the list by setting the entry to NULL.
- *
- * This can be called from the JDWP thread (because the debugger has
- * cancelled the breakpoint) or from an event thread (because it's a
- * single-shot breakpoint, e.g. "run to line").  We only get here as
- * the result of removing an entry from the event list, which is
- * synchronized, so it should not be possible for two threads to be
- * updating breakpoints at the same time.
- */
-void dvmClearBreakAddr(Method* method, unsigned int instrOffset)
-{
-    BreakpointSet* pSet = gDvm.breakpointSet;
-    dvmBreakpointSetLock(pSet);
-    dvmBreakpointSetRemove(pSet, method, instrOffset);
-    dvmBreakpointSetUnlock(pSet);
-}
-
-/*
- * Get the original opcode from under a breakpoint.
- *
- * On SMP hardware it's possible one core might try to execute a breakpoint
- * after another core has cleared it.  We need to handle the case where
- * there's no entry in the breakpoint set.  (The memory barriers in the
- * locks and in the breakpoint update code should ensure that, once we've
- * observed the absence of a breakpoint entry, we will also now observe
- * the restoration of the original opcode.  The fact that we're holding
- * the lock prevents other threads from confusing things further.)
- */
-u1 dvmGetOriginalOpcode(const u2* addr)
-{
-    BreakpointSet* pSet = gDvm.breakpointSet;
-    u1 orig = 0;
-
-    dvmBreakpointSetLock(pSet);
-    if (!dvmBreakpointSetOriginalOpcode(pSet, addr, &orig)) {
-        orig = *(u1*)addr;
-        if (orig == OP_BREAKPOINT) {
-            ALOGE("GLITCH: can't find breakpoint, opcode is still set");
-            dvmAbort();
-        }
-    }
-    dvmBreakpointSetUnlock(pSet);
-
-    return orig;
-}
-
-/*
- * Flush any breakpoints associated with methods in "clazz".
- *
- * We don't want to modify the bytecode of a method before the verifier
- * gets a chance to look at it, so we postpone opcode replacement until
- * after verification completes.
- */
-void dvmFlushBreakpoints(ClassObject* clazz)
-{
-    BreakpointSet* pSet = gDvm.breakpointSet;
-
-    if (pSet == NULL)
-        return;
-
-    assert(dvmIsClassVerified(clazz));
-    dvmBreakpointSetLock(pSet);
-    dvmBreakpointSetFlush(pSet, clazz);
-    dvmBreakpointSetUnlock(pSet);
-}
-
-/*
- * Add a single step event.  Currently this is a global item.
- *
- * We set up some initial values based on the thread's current state.  This
- * won't work well if the thread is running, so it's up to the caller to
- * verify that it's suspended.
- *
- * This is only called from the JDWP thread.
- */
-bool dvmAddSingleStep(Thread* thread, int size, int depth)
-{
-    StepControl* pCtrl = &gDvm.stepControl;
-
-    if (pCtrl->active && thread != pCtrl->thread) {
-        ALOGW("WARNING: single-step active for %p; adding %p",
-            pCtrl->thread, thread);
-
-        /*
-         * Keep going, overwriting previous.  This can happen if you
-         * suspend a thread in Object.wait, hit the single-step key, then
-         * switch to another thread and do the same thing again.
-         * The first thread's step is still pending.
-         *
-         * TODO: consider making single-step per-thread.  Adds to the
-         * overhead, but could be useful in rare situations.
-         */
-    }
-
-    pCtrl->size = static_cast<JdwpStepSize>(size);
-    pCtrl->depth = static_cast<JdwpStepDepth>(depth);
-    pCtrl->thread = thread;
-
-    /*
-     * We may be stepping into or over method calls, or running until we
-     * return from the current method.  To make this work we need to track
-     * the current line, current method, and current stack depth.  We need
-     * to be checking these after most instructions, notably those that
-     * call methods, return from methods, or are on a different line from the
-     * previous instruction.
-     *
-     * We have to start with a snapshot of the current state.  If we're in
-     * an interpreted method, everything we need is in the current frame.  If
-     * we're in a native method, possibly with some extra JNI frames pushed
-     * on by PushLocalFrame, we want to use the topmost native method.
-     */
-    const StackSaveArea* saveArea;
-    u4* fp;
-    u4* prevFp = NULL;
-
-    for (fp = thread->interpSave.curFrame; fp != NULL;
-         fp = saveArea->prevFrame) {
-        const Method* method;
-
-        saveArea = SAVEAREA_FROM_FP(fp);
-        method = saveArea->method;
-
-        if (!dvmIsBreakFrame((u4*)fp) && !dvmIsNativeMethod(method))
-            break;
-        prevFp = fp;
-    }
-    if (fp == NULL) {
-        ALOGW("Unexpected: step req in native-only threadid=%d",
-            thread->threadId);
-        return false;
-    }
-    if (prevFp != NULL) {
-        /*
-         * First interpreted frame wasn't the one at the bottom.  Break
-         * frames are only inserted when calling from native->interp, so we
-         * don't need to worry about one being here.
-         */
-        ALOGV("##### init step while in native method");
-        fp = prevFp;
-        assert(!dvmIsBreakFrame((u4*)fp));
-        assert(dvmIsNativeMethod(SAVEAREA_FROM_FP(fp)->method));
-        saveArea = SAVEAREA_FROM_FP(fp);
-    }
-
-    /*
-     * Pull the goodies out.  "xtra.currentPc" should be accurate since
-     * we update it on every instruction while the debugger is connected.
-     */
-    pCtrl->method = saveArea->method;
-    // Clear out any old address set
-    if (pCtrl->pAddressSet != NULL) {
-        // (discard const)
-        free((void *)pCtrl->pAddressSet);
-        pCtrl->pAddressSet = NULL;
-    }
-    if (dvmIsNativeMethod(pCtrl->method)) {
-        pCtrl->line = -1;
-    } else {
-        pCtrl->line = dvmLineNumFromPC(saveArea->method,
-                        saveArea->xtra.currentPc - saveArea->method->insns);
-        pCtrl->pAddressSet
-                = dvmAddressSetForLine(saveArea->method, pCtrl->line);
-    }
-    pCtrl->frameDepth =
-        dvmComputeVagueFrameDepth(thread, thread->interpSave.curFrame);
-    pCtrl->active = true;
-
-    ALOGV("##### step init: thread=%p meth=%p '%s' line=%d frameDepth=%d depth=%s size=%s",
-        pCtrl->thread, pCtrl->method, pCtrl->method->name,
-        pCtrl->line, pCtrl->frameDepth,
-        dvmJdwpStepDepthStr(pCtrl->depth),
-        dvmJdwpStepSizeStr(pCtrl->size));
-
-    return true;
-}
-
-/*
- * Disable a single step event.
- */
-void dvmClearSingleStep(Thread* thread)
-{
-    UNUSED_PARAMETER(thread);
-
-    gDvm.stepControl.active = false;
-}
-
-/*
- * The interpreter just threw.  Handle any special subMode requirements.
- * All interpSave state must be valid on entry.
- */
-void dvmReportExceptionThrow(Thread* self, Object* exception)
-{
-    const Method* curMethod = self->interpSave.method;
-#if defined(WITH_JIT)
-    if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
-        dvmJitEndTraceSelect(self, self->interpSave.pc);
-    }
-    if (self->interpBreak.ctl.breakFlags & kInterpSingleStep) {
-        /* Discard any single-step native returns to translation */
-        self->jitResumeNPC = NULL;
-    }
-#endif
-    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
-        void *catchFrame;
-        int offset = self->interpSave.pc - curMethod->insns;
-        int catchRelPc = dvmFindCatchBlock(self, offset, exception,
-                                           true, &catchFrame);
-        dvmDbgPostException(self->interpSave.curFrame, offset, catchFrame,
-                            catchRelPc, exception);
-    }
-}
-
-/*
- * The interpreter is preparing to do an invoke (both native & normal).
- * Handle any special subMode requirements.  All interpSave state
- * must be valid on entry.
- */
-void dvmReportInvoke(Thread* self, const Method* methodToCall)
-{
-    TRACE_METHOD_ENTER(self, methodToCall);
-}
-
-/*
- * The interpreter is preparing to do a native invoke. Handle any
- * special subMode requirements.  NOTE: for a native invoke,
- * dvmReportInvoke() and dvmReportPreNativeInvoke() will both
- * be called prior to the invoke.  fp is the Dalvik FP of the calling
- * method.
- */
-void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
-{
-#if defined(WITH_JIT)
-    /*
-     * Actively building a trace?  If so, end it now.   The trace
-     * builder can't follow into or through a native method.
-     */
-    if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
-        dvmCheckJit(self->interpSave.pc, self);
-    }
-#endif
-    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
-        Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
-        assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr));
-        dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_ENTRY);
-    }
-}
-
-/*
- * The interpreter has returned from a native invoke. Handle any
- * special subMode requirements.  fp is the Dalvik FP of the calling
- * method.
- */
-void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp)
-{
-    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
-        Object* thisPtr = dvmGetThisPtr(self->interpSave.method, fp);
-        assert(thisPtr == NULL || dvmIsHeapAddress(thisPtr));
-        dvmDbgPostLocationEvent(methodToCall, -1, thisPtr, DBG_METHOD_EXIT);
-    }
-    if (self->interpBreak.ctl.subMode & kSubModeMethodTrace) {
-        dvmFastNativeMethodTraceExit(methodToCall, self);
-    }
-}
-
-/*
- * The interpreter has returned from a normal method.  Handle any special
- * subMode requirements.  All interpSave state must be valid on entry.
- */
-void dvmReportReturn(Thread* self)
-{
-    TRACE_METHOD_EXIT(self, self->interpSave.method);
-#if defined(WITH_JIT)
-    if (dvmIsBreakFrame(self->interpSave.curFrame) &&
-        (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild)) {
-        dvmCheckJit(self->interpSave.pc, self);
-    }
-#endif
-}
-
-/*
- * Update the debugger on interesting events, such as hitting a breakpoint
- * or a single-step point.  This is called from the top of the interpreter
- * loop, before the current instruction is processed.
- *
- * Set "methodEntry" if we've just entered the method.  This detects
- * method exit by checking to see if the next instruction is "return".
- *
- * This can't catch native method entry/exit, so we have to handle that
- * at the point of invocation.  We also need to catch it in dvmCallMethod
- * if we want to capture native->native calls made through JNI.
- *
- * Notes to self:
- * - Don't want to switch to VMWAIT while posting events to the debugger.
- *   Let the debugger code decide if we need to change state.
- * - We may want to check for debugger-induced thread suspensions on
- *   every instruction.  That would make a "suspend all" more responsive
- *   and reduce the chances of multiple simultaneous events occurring.
- *   However, it could change the behavior some.
- *
- * TODO: method entry/exit events are probably less common than location
- * breakpoints.  We may be able to speed things up a bit if we don't query
- * the event list unless we know there's at least one lurking within.
- */
-static void updateDebugger(const Method* method, const u2* pc, const u4* fp,
-                           Thread* self)
-{
-    int eventFlags = 0;
-
-    /*
-     * Update xtra.currentPc on every instruction.  We need to do this if
-     * there's a chance that we could get suspended.  This can happen if
-     * eventFlags != 0 here, or somebody manually requests a suspend
-     * (which gets handled at PERIOD_CHECKS time).  One place where this
-     * needs to be correct is in dvmAddSingleStep().
-     */
-    dvmExportPC(pc, fp);
-
-    if (self->debugIsMethodEntry) {
-        eventFlags |= DBG_METHOD_ENTRY;
-        self->debugIsMethodEntry = false;
-    }
-
-    /*
-     * See if we have a breakpoint here.
-     *
-     * Depending on the "mods" associated with event(s) on this address,
-     * we may or may not actually send a message to the debugger.
-     */
-    if (GET_OPCODE(*pc) == OP_BREAKPOINT) {
-        ALOGV("+++ breakpoint hit at %p", pc);
-        eventFlags |= DBG_BREAKPOINT;
-    }
-
-    /*
-     * If the debugger is single-stepping one of our threads, check to
-     * see if we're that thread and we've reached a step point.
-     */
-    const StepControl* pCtrl = &gDvm.stepControl;
-    if (pCtrl->active && pCtrl->thread == self) {
-        int frameDepth;
-        bool doStop = false;
-        const char* msg = NULL;
-
-        assert(!dvmIsNativeMethod(method));
-
-        if (pCtrl->depth == SD_INTO) {
-            /*
-             * Step into method calls.  We break when the line number
-             * or method pointer changes.  If we're in SS_MIN mode, we
-             * always stop.
-             */
-            if (pCtrl->method != method) {
-                doStop = true;
-                msg = "new method";
-            } else if (pCtrl->size == SS_MIN) {
-                doStop = true;
-                msg = "new instruction";
-            } else if (!dvmAddressSetGet(
-                    pCtrl->pAddressSet, pc - method->insns)) {
-                doStop = true;
-                msg = "new line";
-            }
-        } else if (pCtrl->depth == SD_OVER) {
-            /*
-             * Step over method calls.  We break when the line number is
-             * different and the frame depth is <= the original frame
-             * depth.  (We can't just compare on the method, because we
-             * might get unrolled past it by an exception, and it's tricky
-             * to identify recursion.)
-             */
-            frameDepth = dvmComputeVagueFrameDepth(self, fp);
-            if (frameDepth < pCtrl->frameDepth) {
-                /* popped up one or more frames, always trigger */
-                doStop = true;
-                msg = "method pop";
-            } else if (frameDepth == pCtrl->frameDepth) {
-                /* same depth, see if we moved */
-                if (pCtrl->size == SS_MIN) {
-                    doStop = true;
-                    msg = "new instruction";
-                } else if (!dvmAddressSetGet(pCtrl->pAddressSet,
-                            pc - method->insns)) {
-                    doStop = true;
-                    msg = "new line";
-                }
-            }
-        } else {
-            assert(pCtrl->depth == SD_OUT);
-            /*
-             * Return from the current method.  We break when the frame
-             * depth pops up.
-             *
-             * This differs from the "method exit" break in that it stops
-             * with the PC at the next instruction in the returned-to
-             * function, rather than the end of the returning function.
-             */
-            frameDepth = dvmComputeVagueFrameDepth(self, fp);
-            if (frameDepth < pCtrl->frameDepth) {
-                doStop = true;
-                msg = "method pop";
-            }
-        }
-
-        if (doStop) {
-            ALOGV("#####S %s", msg);
-            eventFlags |= DBG_SINGLE_STEP;
-        }
-    }
-
-    /*
-     * Check to see if this is a "return" instruction.  JDWP says we should
-     * send the event *after* the code has been executed, but it also says
-     * the location we provide is the last instruction.  Since the "return"
-     * instruction has no interesting side effects, we should be safe.
-     * (We can't just move this down to the returnFromMethod label because
-     * we potentially need to combine it with other events.)
-     *
-     * We're also not supposed to generate a method exit event if the method
-     * terminates "with a thrown exception".
-     */
-    u2 opcode = GET_OPCODE(*pc);
-    if (opcode == OP_RETURN_VOID || opcode == OP_RETURN ||
-        opcode == OP_RETURN_WIDE ||opcode == OP_RETURN_OBJECT)
-    {
-        eventFlags |= DBG_METHOD_EXIT;
-    }
-
-    /*
-     * If there's something interesting going on, see if it matches one
-     * of the debugger filters.
-     */
-    if (eventFlags != 0) {
-        Object* thisPtr = dvmGetThisPtr(method, fp);
-        if (thisPtr != NULL && !dvmIsHeapAddress(thisPtr)) {
-            /*
-             * TODO: remove this check if we're confident that the "this"
-             * pointer is where it should be -- slows us down, especially
-             * during single-step.
-             */
-            char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-            ALOGE("HEY: invalid 'this' ptr %p (%s.%s %s)", thisPtr,
-                method->clazz->descriptor, method->name, desc);
-            free(desc);
-            dvmAbort();
-        }
-        dvmDbgPostLocationEvent(method, pc - method->insns, thisPtr,
-            eventFlags);
-    }
-}
-
-/*
- * Recover the "this" pointer from the current interpreted method.  "this"
- * is always in "in0" for non-static methods.
- *
- * The "ins" start at (#of registers - #of ins).  Note in0 != v0.
- *
- * This works because "dx" guarantees that it will work.  It's probably
- * fairly common to have a virtual method that doesn't use its "this"
- * pointer, in which case we're potentially wasting a register.  However,
- * the debugger doesn't treat "this" as just another argument.  For
- * example, events (such as breakpoints) can be enabled for specific
- * values of "this".  There is also a separate StackFrame.ThisObject call
- * in JDWP that is expected to work for any non-native non-static method.
- *
- * Because we need it when setting up debugger event filters, we want to
- * be able to do this quickly.
- */
-Object* dvmGetThisPtr(const Method* method, const u4* fp)
-{
-    if (dvmIsStaticMethod(method))
-        return NULL;
-    return (Object*)fp[method->registersSize - method->insSize];
-}
-
-
-#if defined(WITH_TRACKREF_CHECKS)
-/*
- * Verify that all internally-tracked references have been released.  If
- * they haven't, print them and abort the VM.
- *
- * "debugTrackedRefStart" indicates how many refs were on the list when
- * we were first invoked.
- */
-void dvmInterpCheckTrackedRefs(Thread* self, const Method* method,
-    int debugTrackedRefStart)
-{
-    if (dvmReferenceTableEntries(&self->internalLocalRefTable)
-        != (size_t) debugTrackedRefStart)
-    {
-        char* desc;
-        Object** top;
-        int count;
-
-        count = dvmReferenceTableEntries(&self->internalLocalRefTable);
-
-        ALOGE("TRACK: unreleased internal reference (prev=%d total=%d)",
-            debugTrackedRefStart, count);
-        desc = dexProtoCopyMethodDescriptor(&method->prototype);
-        ALOGE("       current method is %s.%s %s", method->clazz->descriptor,
-            method->name, desc);
-        free(desc);
-        top = self->internalLocalRefTable.table + debugTrackedRefStart;
-        while (top < self->internalLocalRefTable.nextEntry) {
-            ALOGE("  %p (%s)",
-                 *top,
-                 ((*top)->clazz != NULL) ? (*top)->clazz->descriptor : "");
-            top++;
-        }
-        dvmDumpThread(self, false);
-
-        dvmAbort();
-    }
-    //ALOGI("TRACK OK");
-}
-#endif
-
-
-#ifdef LOG_INSTR
-/*
- * Dump the v-registers.  Sent to the ILOG log tag.
- */
-void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly)
-{
-    int i, localCount;
-
-    localCount = method->registersSize - method->insSize;
-
-    ALOG(LOG_VERBOSE, LOG_TAG"i", "Registers (fp=%p):", framePtr);
-    for (i = method->registersSize-1; i >= 0; i--) {
-        if (i >= localCount) {
-            ALOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d in%-2d : 0x%08x",
-                i, i-localCount, framePtr[i]);
-        } else {
-            if (inOnly) {
-                ALOG(LOG_VERBOSE, LOG_TAG"i", "  [...]");
-                break;
-            }
-            const char* name = "";
-#if 0   // "locals" structure has changed -- need to rewrite this
-            int j;
-            DexFile* pDexFile = method->clazz->pDexFile;
-            const DexCode* pDexCode = dvmGetMethodCode(method);
-            int localsSize = dexGetLocalsSize(pDexFile, pDexCode);
-            const DexLocal* locals = dvmDexGetLocals(pDexFile, pDexCode);
-            for (j = 0; j < localsSize, j++) {
-                if (locals[j].registerNum == (u4) i) {
-                    name = dvmDexStringStr(locals[j].pName);
-                    break;
-                }
-            }
-#endif
-            ALOG(LOG_VERBOSE, LOG_TAG"i", "  v%-2d      : 0x%08x %s",
-                i, framePtr[i], name);
-        }
-    }
-}
-#endif
-
-
-/*
- * ===========================================================================
- *      Entry point and general support functions
- * ===========================================================================
- */
-
-/*
- * Construct an s4 from two consecutive half-words of switch data.
- * This needs to check endianness because the DEX optimizer only swaps
- * half-words in instruction stream.
- *
- * "switchData" must be 32-bit aligned.
- */
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-static inline s4 s4FromSwitchData(const void* switchData) {
-    return *(s4*) switchData;
-}
-#else
-static inline s4 s4FromSwitchData(const void* switchData) {
-    u2* data = switchData;
-    return data[0] | (((s4) data[1]) << 16);
-}
-#endif
-
-/*
- * Find the matching case.  Returns the offset to the handler instructions.
- *
- * Returns 3 if we don't find a match (it's the size of the packed-switch
- * instruction).
- */
-s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal)
-{
-    const int kInstrLen = 3;
-    u2 size;
-    s4 firstKey;
-    const s4* entries;
-
-    /*
-     * Packed switch data format:
-     *  ushort ident = 0x0100   magic value
-     *  ushort size             number of entries in the table
-     *  int first_key           first (and lowest) switch case value
-     *  int targets[size]       branch targets, relative to switch opcode
-     *
-     * Total size is (4+size*2) 16-bit code units.
-     */
-    if (*switchData++ != kPackedSwitchSignature) {
-        /* should have been caught by verifier */
-        dvmThrowInternalError("bad packed switch magic");
-        return kInstrLen;
-    }
-
-    size = *switchData++;
-    assert(size > 0);
-
-    firstKey = *switchData++;
-    firstKey |= (*switchData++) << 16;
-
-    if (testVal < firstKey || testVal >= firstKey + size) {
-        LOGVV("Value %d not found in switch (%d-%d)",
-            testVal, firstKey, firstKey+size-1);
-        return kInstrLen;
-    }
-
-    /* The entries are guaranteed to be aligned on a 32-bit boundary;
-     * we can treat them as a native int array.
-     */
-    entries = (const s4*) switchData;
-    assert(((u4)entries & 0x3) == 0);
-
-    assert(testVal - firstKey >= 0 && testVal - firstKey < size);
-    LOGVV("Value %d found in slot %d (goto 0x%02x)",
-        testVal, testVal - firstKey,
-        s4FromSwitchData(&entries[testVal - firstKey]));
-    return s4FromSwitchData(&entries[testVal - firstKey]);
-}
-
-/*
- * Find the matching case.  Returns the offset to the handler instructions.
- *
- * Returns 3 if we don't find a match (it's the size of the sparse-switch
- * instruction).
- */
-s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal)
-{
-    const int kInstrLen = 3;
-    u2 size;
-    const s4* keys;
-    const s4* entries;
-
-    /*
-     * Sparse switch data format:
-     *  ushort ident = 0x0200   magic value
-     *  ushort size             number of entries in the table; > 0
-     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
-     *  int targets[size]       branch targets, relative to switch opcode
-     *
-     * Total size is (2+size*4) 16-bit code units.
-     */
-
-    if (*switchData++ != kSparseSwitchSignature) {
-        /* should have been caught by verifier */
-        dvmThrowInternalError("bad sparse switch magic");
-        return kInstrLen;
-    }
-
-    size = *switchData++;
-    assert(size > 0);
-
-    /* The keys are guaranteed to be aligned on a 32-bit boundary;
-     * we can treat them as a native int array.
-     */
-    keys = (const s4*) switchData;
-    assert(((u4)keys & 0x3) == 0);
-
-    /* The entries are guaranteed to be aligned on a 32-bit boundary;
-     * we can treat them as a native int array.
-     */
-    entries = keys + size;
-    assert(((u4)entries & 0x3) == 0);
-
-    /*
-     * Binary-search through the array of keys, which are guaranteed to
-     * be sorted low-to-high.
-     */
-    int lo = 0;
-    int hi = size - 1;
-    while (lo <= hi) {
-        int mid = (lo + hi) >> 1;
-
-        s4 foundVal = s4FromSwitchData(&keys[mid]);
-        if (testVal < foundVal) {
-            hi = mid - 1;
-        } else if (testVal > foundVal) {
-            lo = mid + 1;
-        } else {
-            LOGVV("Value %d found in entry %d (goto 0x%02x)",
-                testVal, mid, s4FromSwitchData(&entries[mid]));
-            return s4FromSwitchData(&entries[mid]);
-        }
-    }
-
-    LOGVV("Value %d not found in switch", testVal);
-    return kInstrLen;
-}
-
-/*
- * Copy data for a fill-array-data instruction.  On a little-endian machine
- * we can just do a memcpy(), on a big-endian system we have work to do.
- *
- * The trick here is that dexopt has byte-swapped each code unit, which is
- * exactly what we want for short/char data.  For byte data we need to undo
- * the swap, and for 4- or 8-byte values we need to swap pieces within
- * each word.
- */
-static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
-{
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-    memcpy(dest, src, size*width);
-#else
-    int i;
-
-    switch (width) {
-    case 1:
-        /* un-swap pairs of bytes as we go */
-        for (i = (size-1) & ~1; i >= 0; i -= 2) {
-            ((u1*)dest)[i] = ((u1*)src)[i+1];
-            ((u1*)dest)[i+1] = ((u1*)src)[i];
-        }
-        /*
-         * "src" is padded to end on a two-byte boundary, but we don't want to
-         * assume "dest" is, so we handle odd length specially.
-         */
-        if ((size & 1) != 0) {
-            ((u1*)dest)[size-1] = ((u1*)src)[size];
-        }
-        break;
-    case 2:
-        /* already swapped correctly */
-        memcpy(dest, src, size*width);
-        break;
-    case 4:
-        /* swap word halves */
-        for (i = 0; i < (int) size; i++) {
-            ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
-        }
-        break;
-    case 8:
-        /* swap word halves and words */
-        for (i = 0; i < (int) (size << 1); i += 2) {
-            ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
-            ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
-        }
-        break;
-    default:
-        ALOGE("Unexpected width %d in copySwappedArrayData", width);
-        dvmAbort();
-        break;
-    }
-#endif
-}
-
-/*
- * Fill the array with predefined constant values.
- *
- * Returns true if job is completed, otherwise false to indicate that
- * an exception has been thrown.
- */
-bool dvmInterpHandleFillArrayData(ArrayObject* arrayObj, const u2* arrayData)
-{
-    u2 width;
-    u4 size;
-
-    if (arrayObj == NULL) {
-        dvmThrowNullPointerException(NULL);
-        return false;
-    }
-    assert (!IS_CLASS_FLAG_SET(((Object *)arrayObj)->clazz,
-                               CLASS_ISOBJECTARRAY));
-
-    /*
-     * Array data table format:
-     *  ushort ident = 0x0300   magic value
-     *  ushort width            width of each element in the table
-     *  uint   size             number of elements in the table
-     *  ubyte  data[size*width] table of data values (may contain a single-byte
-     *                          padding at the end)
-     *
-     * Total size is 4+(width * size + 1)/2 16-bit code units.
-     */
-    if (arrayData[0] != kArrayDataSignature) {
-        dvmThrowInternalError("bad array data magic");
-        return false;
-    }
-
-    width = arrayData[1];
-    size = arrayData[2] | (((u4)arrayData[3]) << 16);
-
-    if (size > arrayObj->length) {
-        dvmThrowArrayIndexOutOfBoundsException(arrayObj->length, size);
-        return false;
-    }
-    copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
-    return true;
-}
-
-/*
- * Find the concrete method that corresponds to "methodIdx".  The code in
- * "method" is executing invoke-method with "thisClass" as its first argument.
- *
- * Returns NULL with an exception raised on failure.
- */
-Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx,
-    const Method* method, DvmDex* methodClassDex)
-{
-    Method* absMethod;
-    Method* methodToCall;
-    int i, vtableIndex;
-
-    /*
-     * Resolve the method.  This gives us the abstract method from the
-     * interface class declaration.
-     */
-    absMethod = dvmDexGetResolvedMethod(methodClassDex, methodIdx);
-    if (absMethod == NULL) {
-        absMethod = dvmResolveInterfaceMethod(method->clazz, methodIdx);
-        if (absMethod == NULL) {
-            ALOGV("+ unknown method");
-            return NULL;
-        }
-    }
-
-    /* make sure absMethod->methodIndex means what we think it means */
-    assert(dvmIsAbstractMethod(absMethod));
-
-    /*
-     * Run through the "this" object's iftable.  Find the entry for
-     * absMethod's class, then use absMethod->methodIndex to find
-     * the method's entry.  The value there is the offset into our
-     * vtable of the actual method to execute.
-     *
-     * The verifier does not guarantee that objects stored into
-     * interface references actually implement the interface, so this
-     * check cannot be eliminated.
-     */
-    for (i = 0; i < thisClass->iftableCount; i++) {
-        if (thisClass->iftable[i].clazz == absMethod->clazz)
-            break;
-    }
-    if (i == thisClass->iftableCount) {
-        /* impossible in verified DEX, need to check for it in unverified */
-        dvmThrowIncompatibleClassChangeError("interface not implemented");
-        return NULL;
-    }
-
-    assert(absMethod->methodIndex <
-        thisClass->iftable[i].clazz->virtualMethodCount);
-
-    vtableIndex =
-        thisClass->iftable[i].methodIndexArray[absMethod->methodIndex];
-    assert(vtableIndex >= 0 && vtableIndex < thisClass->vtableCount);
-    methodToCall = thisClass->vtable[vtableIndex];
-
-#if 0
-    /* this can happen when there's a stale class file */
-    if (dvmIsAbstractMethod(methodToCall)) {
-        dvmThrowAbstractMethodError("interface method not implemented");
-        return NULL;
-    }
-#else
-    assert(!dvmIsAbstractMethod(methodToCall) ||
-        methodToCall->nativeFunc != NULL);
-#endif
-
-    LOGVV("+++ interface=%s.%s concrete=%s.%s",
-        absMethod->clazz->descriptor, absMethod->name,
-        methodToCall->clazz->descriptor, methodToCall->name);
-    assert(methodToCall != NULL);
-
-    return methodToCall;
-}
-
-
-
-/*
- * Helpers for dvmThrowVerificationError().
- *
- * Each returns a newly-allocated string.
- */
-#define kThrowShow_accessFromClass     1
-static std::string classNameFromIndex(const Method* method, int ref,
-    VerifyErrorRefType refType, int flags)
-{
-    const DvmDex* pDvmDex = method->clazz->pDvmDex;
-    if (refType == VERIFY_ERROR_REF_FIELD) {
-        /* get class ID from field ID */
-        const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
-        ref = pFieldId->classIdx;
-    } else if (refType == VERIFY_ERROR_REF_METHOD) {
-        /* get class ID from method ID */
-        const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
-        ref = pMethodId->classIdx;
-    }
-
-    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
-    std::string dotClassName(dvmHumanReadableDescriptor(className));
-    if (flags == 0) {
-        return dotClassName;
-    }
-
-    std::string result;
-    if ((flags & kThrowShow_accessFromClass) != 0) {
-        result += "tried to access class " + dotClassName;
-        result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor);
-    } else {
-        assert(false);      // should've been caught above
-    }
-
-    return result;
-}
-static std::string fieldNameFromIndex(const Method* method, int ref,
-    VerifyErrorRefType refType, int flags)
-{
-    if (refType != VERIFY_ERROR_REF_FIELD) {
-        ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_FIELD, refType);
-        return NULL;    /* no message */
-    }
-
-    const DvmDex* pDvmDex = method->clazz->pDvmDex;
-    const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
-    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
-    const char* fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
-
-    std::string dotName(dvmHumanReadableDescriptor(className));
-
-    if ((flags & kThrowShow_accessFromClass) != 0) {
-        std::string result;
-        result += "tried to access field ";
-        result += dotName + "." + fieldName;
-        result += " from class ";
-        result += dvmHumanReadableDescriptor(method->clazz->descriptor);
-        return result;
-    }
-    return dotName + "." + fieldName;
-}
-static std::string methodNameFromIndex(const Method* method, int ref,
-    VerifyErrorRefType refType, int flags)
-{
-    if (refType != VERIFY_ERROR_REF_METHOD) {
-        ALOGW("Expected ref type %d, got %d", VERIFY_ERROR_REF_METHOD,refType);
-        return NULL;    /* no message */
-    }
-
-    const DvmDex* pDvmDex = method->clazz->pDvmDex;
-    const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
-    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
-    const char* methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
-
-    std::string dotName(dvmHumanReadableDescriptor(className));
-
-    if ((flags & kThrowShow_accessFromClass) != 0) {
-        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-        std::string result;
-        result += "tried to access method ";
-        result += dotName + "." + methodName + ":" + desc;
-        result += " from class " + dvmHumanReadableDescriptor(method->clazz->descriptor);
-        free(desc);
-        return result;
-    }
-    return dotName + "." + methodName;
-}
-
-/*
- * Throw an exception for a problem identified by the verifier.
- *
- * This is used by the invoke-verification-error instruction.  It always
- * throws an exception.
- *
- * "kind" indicates the kind of failure encountered by the verifier.  It
- * has two parts, an error code and an indication of the reference type.
- */
-void dvmThrowVerificationError(const Method* method, int kind, int ref)
-{
-    int errorPart = kind & ~(0xff << kVerifyErrorRefTypeShift);
-    int errorRefPart = kind >> kVerifyErrorRefTypeShift;
-    VerifyError errorKind = static_cast<VerifyError>(errorPart);
-    VerifyErrorRefType refType = static_cast<VerifyErrorRefType>(errorRefPart);
-    ClassObject* exceptionClass = gDvm.exVerifyError;
-    std::string msg;
-
-    switch ((VerifyError) errorKind) {
-    case VERIFY_ERROR_NO_CLASS:
-        exceptionClass = gDvm.exNoClassDefFoundError;
-        msg = classNameFromIndex(method, ref, refType, 0);
-        break;
-    case VERIFY_ERROR_NO_FIELD:
-        exceptionClass = gDvm.exNoSuchFieldError;
-        msg = fieldNameFromIndex(method, ref, refType, 0);
-        break;
-    case VERIFY_ERROR_NO_METHOD:
-        exceptionClass = gDvm.exNoSuchMethodError;
-        msg = methodNameFromIndex(method, ref, refType, 0);
-        break;
-    case VERIFY_ERROR_ACCESS_CLASS:
-        exceptionClass = gDvm.exIllegalAccessError;
-        msg = classNameFromIndex(method, ref, refType,
-            kThrowShow_accessFromClass);
-        break;
-    case VERIFY_ERROR_ACCESS_FIELD:
-        exceptionClass = gDvm.exIllegalAccessError;
-        msg = fieldNameFromIndex(method, ref, refType,
-            kThrowShow_accessFromClass);
-        break;
-    case VERIFY_ERROR_ACCESS_METHOD:
-        exceptionClass = gDvm.exIllegalAccessError;
-        msg = methodNameFromIndex(method, ref, refType,
-            kThrowShow_accessFromClass);
-        break;
-    case VERIFY_ERROR_CLASS_CHANGE:
-        exceptionClass = gDvm.exIncompatibleClassChangeError;
-        msg = classNameFromIndex(method, ref, refType, 0);
-        break;
-    case VERIFY_ERROR_INSTANTIATION:
-        exceptionClass = gDvm.exInstantiationError;
-        msg = classNameFromIndex(method, ref, refType, 0);
-        break;
-
-    case VERIFY_ERROR_GENERIC:
-        /* generic VerifyError; use default exception, no message */
-        break;
-    case VERIFY_ERROR_NONE:
-        /* should never happen; use default exception */
-        assert(false);
-        msg = strdup("weird - no error specified");
-        break;
-
-    /* no default clause -- want warning if enum updated */
-    }
-
-    dvmThrowException(exceptionClass, msg.c_str());
-}
-
-/*
- * Update interpBreak for a single thread.
- */
-void updateInterpBreak(Thread* thread, ExecutionSubModes subMode, bool enable)
-{
-    InterpBreak oldValue, newValue;
-    do {
-        oldValue = newValue = thread->interpBreak;
-        newValue.ctl.breakFlags = kInterpNoBreak;  // Assume full reset
-        if (enable)
-            newValue.ctl.subMode |= subMode;
-        else
-            newValue.ctl.subMode &= ~subMode;
-        if (newValue.ctl.subMode & SINGLESTEP_BREAK_MASK)
-            newValue.ctl.breakFlags |= kInterpSingleStep;
-        if (newValue.ctl.subMode & SAFEPOINT_BREAK_MASK)
-            newValue.ctl.breakFlags |= kInterpSafePoint;
-        newValue.ctl.curHandlerTable = (newValue.ctl.breakFlags) ?
-            thread->altHandlerTable : thread->mainHandlerTable;
-    } while (dvmQuasiAtomicCas64(oldValue.all, newValue.all,
-             &thread->interpBreak.all) != 0);
-}
-
-/*
- * Update interpBreak for all threads.
- */
-void updateAllInterpBreak(ExecutionSubModes subMode, bool enable)
-{
-    Thread* self = dvmThreadSelf();
-    Thread* thread;
-
-    dvmLockThreadList(self);
-    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
-        updateInterpBreak(thread, subMode, enable);
-    }
-    dvmUnlockThreadList();
-}
-
-/*
- * Update the normal and debugger suspend counts for a thread.
- * threadSuspendCount must be acquired before calling this to
- * ensure a clean update of suspendCount, dbgSuspendCount and
- * sumThreadSuspendCount.
- *
- * CLEANUP TODO: Currently only the JIT is using sumThreadSuspendCount.
- * Move under WITH_JIT ifdefs.
-*/
-void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta)
-{
-    thread->suspendCount += delta;
-    thread->dbgSuspendCount += dbgDelta;
-    updateInterpBreak(thread, kSubModeSuspendPending,
-                      (thread->suspendCount != 0));
-    // Update the global suspend count total
-    gDvm.sumThreadSuspendCount += delta;
-}
-
-
-void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode)
-{
-    updateInterpBreak(thread, subMode, false);
-}
-
-void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode)
-{
-    updateInterpBreak(thread, subMode, true);
-}
-
-void dvmEnableAllSubMode(ExecutionSubModes subMode)
-{
-    updateAllInterpBreak(subMode, true);
-}
-
-void dvmDisableAllSubMode(ExecutionSubModes subMode)
-{
-    updateAllInterpBreak(subMode, false);
-}
-
-/*
- * Do a sanity check on interpreter state saved to Thread.
- * A failure here doesn't necessarily mean that something is wrong,
- * so this code should only be used during development to suggest
- * a possible problem.
- */
-void dvmCheckInterpStateConsistency()
-{
-    Thread* self = dvmThreadSelf();
-    Thread* thread;
-    uint8_t breakFlags;
-    uint8_t subMode;
-    void* handlerTable;
-
-    dvmLockThreadList(self);
-    breakFlags = self->interpBreak.ctl.breakFlags;
-    subMode = self->interpBreak.ctl.subMode;
-    handlerTable = self->interpBreak.ctl.curHandlerTable;
-    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
-        if (subMode != thread->interpBreak.ctl.subMode) {
-            ALOGD("Warning: subMode mismatch - %#x:%#x, tid[%d]",
-                subMode,thread->interpBreak.ctl.subMode,thread->threadId);
-         }
-        if (breakFlags != thread->interpBreak.ctl.breakFlags) {
-            ALOGD("Warning: breakFlags mismatch - %#x:%#x, tid[%d]",
-                breakFlags,thread->interpBreak.ctl.breakFlags,thread->threadId);
-         }
-        if (handlerTable != thread->interpBreak.ctl.curHandlerTable) {
-            ALOGD("Warning: curHandlerTable mismatch - %#x:%#x, tid[%d]",
-                (int)handlerTable,(int)thread->interpBreak.ctl.curHandlerTable,
-                thread->threadId);
-         }
-#if defined(WITH_JIT)
-         if (thread->pJitProfTable != gDvmJit.pProfTable) {
-             ALOGD("Warning: pJitProfTable mismatch - %#x:%#x, tid[%d]",
-                  (int)thread->pJitProfTable,(int)gDvmJit.pProfTable,
-                  thread->threadId);
-         }
-         if (thread->jitThreshold != gDvmJit.threshold) {
-             ALOGD("Warning: jitThreshold mismatch - %#x:%#x, tid[%d]",
-                  (int)thread->jitThreshold,(int)gDvmJit.threshold,
-                  thread->threadId);
-         }
-#endif
-    }
-    dvmUnlockThreadList();
-}
-
-/*
- * Arm a safepoint callback for a thread.  If funct is null,
- * clear any pending callback.
- * TODO: only gc is currently using this feature, and will have
- * at most a single outstanding callback request.  Until we need
- * something more capable and flexible, enforce this limit.
- */
-void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
-                             void* arg)
-{
-    dvmLockMutex(&thread->callbackMutex);
-    if ((funct == NULL) || (thread->callback == NULL)) {
-        thread->callback = funct;
-        thread->callbackArg = arg;
-        if (funct != NULL) {
-            dvmEnableSubMode(thread, kSubModeCallbackPending);
-        } else {
-            dvmDisableSubMode(thread, kSubModeCallbackPending);
-        }
-    } else {
-        // Already armed.  Different?
-        if ((funct != thread->callback) ||
-            (arg != thread->callbackArg)) {
-            // Yes - report failure and die
-            ALOGE("ArmSafePointCallback failed, thread %d", thread->threadId);
-            dvmUnlockMutex(&thread->callbackMutex);
-            dvmAbort();
-        }
-    }
-    dvmUnlockMutex(&thread->callbackMutex);
-}
-
-/*
- * One-time initialization at thread creation.  Here we initialize
- * useful constants.
- */
-void dvmInitInterpreterState(Thread* self)
-{
-#if defined(WITH_JIT)
-    /*
-     * Reserve a static entity here to quickly setup runtime contents as
-     * gcc will issue block copy instructions.
-     */
-    static struct JitToInterpEntries jitToInterpEntries = {
-        dvmJitToInterpNormal,
-        dvmJitToInterpNoChain,
-        dvmJitToInterpPunt,
-        dvmJitToInterpSingleStep,
-        dvmJitToInterpTraceSelect,
-#if defined(WITH_SELF_VERIFICATION)
-        dvmJitToInterpBackwardBranch,
-#else
-        NULL,
-#endif
-    };
-#endif
-
-    // Begin initialization
-    self->cardTable = gDvm.biasedCardTableBase;
-#if defined(WITH_JIT)
-    // One-time initializations
-    self->jitToInterpEntries = jitToInterpEntries;
-    self->icRechainCount = PREDICTED_CHAIN_COUNTER_RECHAIN;
-    self->pProfileCountdown = &gDvmJit.profileCountdown;
-    // Jit state that can change
-    dvmJitUpdateThreadStateSingle(self);
-#endif
-    dvmInitializeInterpBreak(self);
-}
-
-/*
- * For a newly-created thread, we need to start off with interpBreak
- * set to any existing global modes.  The caller must hold the
- * thread list lock.
- */
-void dvmInitializeInterpBreak(Thread* thread)
-{
-    if (gDvm.instructionCountEnableCount > 0) {
-        dvmEnableSubMode(thread, kSubModeInstCounting);
-    }
-    if (dvmIsMethodTraceActive()) {
-        dvmEnableSubMode(thread, kSubModeMethodTrace);
-    }
-    if (gDvm.emulatorTraceEnableCount > 0) {
-        dvmEnableSubMode(thread, kSubModeEmulatorTrace);
-    }
-    if (gDvm.debuggerActive) {
-        dvmEnableSubMode(thread, kSubModeDebuggerActive);
-    }
-#if 0
-    // Debugging stress mode - force checkBefore
-    dvmEnableSubMode(thread, kSubModeCheckAlways);
-#endif
-}
-
-/*
- * Inter-instruction handler invoked in between instruction interpretations
- * to handle exceptional events such as debugging housekeeping, instruction
- * count profiling, JIT trace building, etc.  Dalvik PC has been exported
- * prior to call, but Thread copy of dPC & fp are not current.
- */
-void dvmCheckBefore(const u2 *pc, u4 *fp, Thread* self)
-{
-    const Method* method = self->interpSave.method;
-    assert(pc >= method->insns && pc <
-           method->insns + dvmGetMethodInsnsSize(method));
-
-#if 0
-    /*
-     * When we hit a specific method, enable verbose instruction logging.
-     * Sometimes it's helpful to use the debugger attach as a trigger too.
-     */
-    if (*pIsMethodEntry) {
-        static const char* cd = "Landroid/test/Arithmetic;";
-        static const char* mn = "shiftTest2";
-        static const char* sg = "()V";
-
-        if (/*self->interpBreak.ctl.subMode & kSubModeDebuggerActive &&*/
-            strcmp(method->clazz->descriptor, cd) == 0 &&
-            strcmp(method->name, mn) == 0 &&
-            strcmp(method->shorty, sg) == 0)
-        {
-            ALOGW("Reached %s.%s, enabling verbose mode",
-                method->clazz->descriptor, method->name);
-            android_setMinPriority(LOG_TAG"i", ANDROID_LOG_VERBOSE);
-            dumpRegs(method, fp, true);
-        }
-
-        if (!gDvm.debuggerActive)
-            *pIsMethodEntry = false;
-    }
-#endif
-
-    /* Safe point handling */
-    if (self->suspendCount ||
-        (self->interpBreak.ctl.subMode & kSubModeCallbackPending)) {
-        // Are we are a safe point?
-        int flags;
-        flags = dexGetFlagsFromOpcode(dexOpcodeFromCodeUnit(*pc));
-        if (flags & (VERIFY_GC_INST_MASK & ~kInstrCanThrow)) {
-            // Yes, at a safe point.  Pending callback?
-            if (self->interpBreak.ctl.subMode & kSubModeCallbackPending) {
-                SafePointCallback callback;
-                void* arg;
-                // Get consistent funct/arg pair
-                dvmLockMutex(&self->callbackMutex);
-                callback = self->callback;
-                arg = self->callbackArg;
-                dvmUnlockMutex(&self->callbackMutex);
-                // Update Thread structure
-                self->interpSave.pc = pc;
-                self->interpSave.curFrame = fp;
-                if (callback != NULL) {
-                    // Do the callback
-                    if (!callback(self,arg)) {
-                        // disarm
-                        dvmArmSafePointCallback(self, NULL, NULL);
-                    }
-                }
-            }
-            // Need to suspend?
-            if (self->suspendCount) {
-                dvmExportPC(pc, fp);
-                dvmCheckSuspendPending(self);
-            }
-        }
-    }
-
-    if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
-        updateDebugger(method, pc, fp, self);
-    }
-    if (gDvm.instructionCountEnableCount != 0) {
-        /*
-         * Count up the #of executed instructions.  This isn't synchronized
-         * for thread-safety; if we need that we should make this
-         * thread-local and merge counts into the global area when threads
-         * exit (perhaps suspending all other threads GC-style and pulling
-         * the data out of them).
-         */
-        gDvm.executedInstrCounts[GET_OPCODE(*pc)]++;
-    }
-
-
-#if defined(WITH_TRACKREF_CHECKS)
-    dvmInterpCheckTrackedRefs(self, method,
-                              self->interpSave.debugTrackedRefStart);
-#endif
-
-#if defined(WITH_JIT)
-    // Does the JIT need anything done now?
-    if (self->interpBreak.ctl.subMode &
-            (kSubModeJitTraceBuild | kSubModeJitSV)) {
-        // Are we building a trace?
-        if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {
-            dvmCheckJit(pc, self);
-        }
-
-#if defined(WITH_SELF_VERIFICATION)
-        // Are we replaying a trace?
-        if (self->interpBreak.ctl.subMode & kSubModeJitSV) {
-            dvmCheckSelfVerification(pc, self);
-        }
-#endif
-    }
-#endif
-
-    /*
-     * CountedStep processing.  NOTE: must be the last here to allow
-     * preceeding special case handler to manipulate single-step count.
-     */
-    if (self->interpBreak.ctl.subMode & kSubModeCountedStep) {
-        if (self->singleStepCount == 0) {
-            // We've exhausted our single step count
-            dvmDisableSubMode(self, kSubModeCountedStep);
-#if defined(WITH_JIT)
-#if 0
-            /*
-             * For debugging.  If jitResumeDPC is non-zero, then
-             * we expect to return to a trace in progress.   There
-             * are valid reasons why we wouldn't (such as an exception
-             * throw), but here we can keep track.
-             */
-            if (self->jitResumeDPC != NULL) {
-                if (self->jitResumeDPC == pc) {
-                    if (self->jitResumeNPC != NULL) {
-                        ALOGD("SS return to trace - pc:%#x to 0x:%x",
-                             (int)pc, (int)self->jitResumeNPC);
-                    } else {
-                        ALOGD("SS return to interp - pc:%#x",(int)pc);
-                    }
-                } else {
-                    ALOGD("SS failed to return.  Expected %#x, now at %#x",
-                         (int)self->jitResumeDPC, (int)pc);
-                }
-            }
-#endif
-#if 0
-            // TODO - fix JIT single-stepping resume mode (b/5551114)
-            // self->jitResumeNPC needs to be cleared in callPrep
-
-            // If we've got a native return and no other reasons to
-            // remain in singlestep/break mode, do a long jump
-            if (self->jitResumeNPC != NULL &&
-                self->interpBreak.ctl.breakFlags == 0) {
-                assert(self->jitResumeDPC == pc);
-                self->jitResumeDPC = NULL;
-                dvmJitResumeTranslation(self, pc, fp);
-                // Doesn't return
-                dvmAbort();
-            }
-            // In case resume is blocked by non-zero breakFlags, clear
-            // jitResumeNPC here.
-            self->jitResumeNPC = NULL;
-            self->jitResumeDPC = NULL;
-            self->inJitCodeCache = NULL;
-#endif
-#endif
-        } else {
-            self->singleStepCount--;
-#if defined(WITH_JIT)
-            if ((self->singleStepCount > 0) && (self->jitResumeNPC != NULL)) {
-                /*
-                 * Direct return to an existing translation following a
-                 * single step is valid only if we step once.  If we're
-                 * here, an additional step was added so we need to invalidate
-                 * the return to translation.
-                 */
-                self->jitResumeNPC = NULL;
-                self->inJitCodeCache = NULL;
-            }
-#endif
-        }
-    }
-}
-
-/*
- * Main interpreter loop entry point.
- *
- * This begins executing code at the start of "method".  On exit, "pResult"
- * holds the return value of the method (or, if "method" returns NULL, it
- * holds an undefined value).
- *
- * The interpreted stack frame, which holds the method arguments, has
- * already been set up.
- */
-void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
-{
-    InterpSaveState interpSaveState;
-    ExecutionSubModes savedSubModes;
-
-#if defined(WITH_JIT)
-    /* Target-specific save/restore */
-    double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
-    /*
-     * If the previous VM left the code cache through single-stepping the
-     * inJitCodeCache flag will be set when the VM is re-entered (for example,
-     * in self-verification mode we single-step NEW_INSTANCE which may re-enter
-     * the VM through findClassFromLoaderNoInit). Because of that, we cannot
-     * assert that self->inJitCodeCache is NULL here.
-     */
-#endif
-
-    /*
-     * Save interpreter state from previous activation, linking
-     * new to last.
-     */
-    interpSaveState = self->interpSave;
-    self->interpSave.prev = &interpSaveState;
-    /*
-     * Strip out and save any flags that should not be inherited by
-     * nested interpreter activation.
-     */
-    savedSubModes = (ExecutionSubModes)(
-              self->interpBreak.ctl.subMode & LOCAL_SUBMODE);
-    if (savedSubModes != kSubModeNormal) {
-        dvmDisableSubMode(self, savedSubModes);
-    }
-#if defined(WITH_JIT)
-    dvmJitCalleeSave(calleeSave);
-#endif
-
-
-#if defined(WITH_TRACKREF_CHECKS)
-    self->interpSave.debugTrackedRefStart =
-        dvmReferenceTableEntries(&self->internalLocalRefTable);
-#endif
-    self->debugIsMethodEntry = true;
-#if defined(WITH_JIT)
-    dvmJitCalleeSave(calleeSave);
-    /* Initialize the state to kJitNot */
-    self->jitState = kJitNot;
-#endif
-
-    /*
-     * Initialize working state.
-     *
-     * No need to initialize "retval".
-     */
-    self->interpSave.method = method;
-    self->interpSave.curFrame = (u4*) self->interpSave.curFrame;
-    self->interpSave.pc = method->insns;
-
-    assert(!dvmIsNativeMethod(method));
-
-    /*
-     * Make sure the class is ready to go.  Shouldn't be possible to get
-     * here otherwise.
-     */
-    if (method->clazz->status < CLASS_INITIALIZING ||
-        method->clazz->status == CLASS_ERROR)
-    {
-        ALOGE("ERROR: tried to execute code in unprepared class '%s' (%d)",
-            method->clazz->descriptor, method->clazz->status);
-        dvmDumpThread(self, false);
-        dvmAbort();
-    }
-
-    typedef void (*Interpreter)(Thread*);
-    Interpreter stdInterp;
-    if (gDvm.executionMode == kExecutionModeInterpFast)
-        stdInterp = dvmMterpStd;
-#if defined(WITH_JIT)
-    else if (gDvm.executionMode == kExecutionModeJit)
-        stdInterp = dvmMterpStd;
-#endif
-    else
-        stdInterp = dvmMterpStd;
-
-#if defined(LOCCS_DIAOS)
-
-	char procName[ProcNameMaxLen] = {0};
-	if ( get_proc_name_from_pid( getpid(), procName ) )
-	{	
-		// get class.dlist path
-		char classFilterFilename[MaxLineLen] = {0};
-		snprintf ( classFilterFilename, MaxLineLen, "/data/data/%s/class.dlist", procName );
-
-		if ( access( classFilterFilename, 0 ) == 0 ) // access(filename, 0) == 0 means file do exist.
-		{
-			stdInterp = dvmInterpretPortable;
-
-		}
-	}
-#endif
-
-    // Call the interpreter
-    (*stdInterp)(self);
-
-    *pResult = self->interpSave.retval;
-
-    /* Restore interpreter state from previous activation */
-    self->interpSave = interpSaveState;
-#if defined(WITH_JIT)
-    dvmJitCalleeRestore(calleeSave);
-#endif
-    if (savedSubModes != kSubModeNormal) {
-        dvmEnableSubMode(self, savedSubModes);
-    }
-}

dia/Interp.h

-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Dalvik interpreter public definitions.
- */
-#ifndef DALVIK_INTERP_INTERP_H_
-#define DALVIK_INTERP_INTERP_H_
-
-/*
- * Stash the dalvik PC in the frame.  Called  during interpretation.
- */
-INLINE void dvmExportPC(const u2* pc, const u4* fp)
-{
-    SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc;
-}
-
-/*
- * Extract the Dalvik opcode
- */
-#define GET_OPCODE(_inst) (_inst & 0xff)
-
-/*
- * Interpreter entry point.  Call here after setting up the interpreted
- * stack (most code will want to get here via dvmCallMethod().)
- */
-void dvmInterpret(Thread* thread, const Method* method, JValue* pResult);
-
-/*
- * Throw an exception for a problem detected by the verifier.
- *
- * This is called from the handler for the throw-verification-error
- * instruction.  "method" is the method currently being executed.
- */
-extern "C" void dvmThrowVerificationError(const Method* method,
-                                          int kind, int ref);
-
-/*
- * One-time initialization and shutdown.
- */
-bool dvmBreakpointStartup(void);
-void dvmBreakpointShutdown(void);
-void dvmInitInterpreterState(Thread* self);
-
-/*
- * Breakpoint implementation.
- */
-void dvmInitBreakpoints();
-void dvmAddBreakAddr(Method* method, unsigned int instrOffset);
-void dvmClearBreakAddr(Method* method, unsigned int instrOffset);
-bool dvmAddSingleStep(Thread* thread, int size, int depth);
-void dvmClearSingleStep(Thread* thread);
-
-/*
- * Recover the opcode that was replaced by a breakpoint.
- */
-extern "C" u1 dvmGetOriginalOpcode(const u2* addr);
-
-/*
- * Flush any breakpoints associated with methods in "clazz".
- */
-void dvmFlushBreakpoints(ClassObject* clazz);
-
-/*
- * Debugger support
- */
-extern "C" void dvmCheckBefore(const u2 *dPC, u4 *fp, Thread* self);
-extern "C" void dvmReportExceptionThrow(Thread* self, Object* exception);
-extern "C" void dvmReportPreNativeInvoke(const Method* methodToCall, Thread* self, u4* fp);
-extern "C" void dvmReportPostNativeInvoke(const Method* methodToCall, Thread* self, u4* fp);
-extern "C" void dvmReportInvoke(Thread* self, const Method* methodToCall);
-extern "C" void dvmReportReturn(Thread* self);
-
-/*
- * InterpBreak & subMode control
- */
-void dvmDisableSubMode(Thread* thread, ExecutionSubModes subMode);
-extern "C" void dvmEnableSubMode(Thread* thread, ExecutionSubModes subMode);
-void dvmDisableAllSubMode(ExecutionSubModes subMode);
-void dvmEnableAllSubMode(ExecutionSubModes subMode);
-void dvmAddToSuspendCounts(Thread* thread, int delta, int dbgDelta);
-void dvmCheckInterpStateConsistency();
-void dvmInitializeInterpBreak(Thread* thread);
-
-/*
- * Register a callback to occur at the next safe point for a single thread.
- * If funct is NULL, the previous registration is cancelled.
- *
- * The callback prototype is:
- *        bool funct(Thread* thread, void* arg)
- *
- *  If funct returns false, the callback will be disarmed.  If true,
- *  it will stay in effect.
- */
-void dvmArmSafePointCallback(Thread* thread, SafePointCallback funct,
-                             void* arg);
-
-
-#ifndef DVM_NO_ASM_INTERP
-extern void* dvmAsmInstructionStart[];
-extern void* dvmAsmAltInstructionStart[];
-#endif
-
-#endif  // DALVIK_INTERP_INTERP_H_

dia/InterpC-portable.cpp

-/*
- * This file was generated automatically by gen-mterp.py for 'portable'.
- *
- * --> DO NOT EDIT <--
- */
-
-/* File: c/header.cpp */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,