Merge change Iccd6c010

* changes:
  Make the traige process for self-verification found divergence easier.
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 9db641e..018dc4a 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -73,9 +73,14 @@
             i = 0;
     }
 
-    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].pc = pc;
-    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].kind = kind;
-    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].info = info;
+    CompilerWorkOrder *newOrder =
+        &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex];
+    newOrder->pc = pc;
+    newOrder->kind = kind;
+    newOrder->info = info;
+    newOrder->result.codeAddress = NULL;
+    newOrder->result.discardResult =
+        (kind == kWorkOrderTraceDebug) ? true : false;
     gDvmJit.compilerWorkEnqueueIndex++;
     if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
         gDvmJit.compilerWorkEnqueueIndex = 0;
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 47de33d..06367a6 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -36,14 +36,16 @@
 
 /* Description of a compiled trace. */
 typedef struct JitTranslationInfo {
-    void     *codeAddress;
+    void *codeAddress;
     JitInstructionSetType instructionSet;
+    bool discardResult;          // Used for debugging divergence
 } JitTranslationInfo;
 
 typedef enum WorkOrderKind {
     kWorkOrderInvalid = 0,      // Should never see by the backend
     kWorkOrderMethod = 1,       // Work is to compile a whole method
     kWorkOrderTrace = 2,        // Work is to compile code fragment(s)
+    kWorkOrderTraceDebug = 3,   // Work is to compile/debug code fragment(s)
 } WorkOrderKind;
 
 typedef struct CompilerWorkOrder {
@@ -154,9 +156,11 @@
                                       struct BasicBlock *bb);
 void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
                                        struct BasicBlock *bb);
+char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn);
 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
                               struct SSARepresentation *ssaRep);
 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
                 void (*func)(struct CompilationUnit *, struct BasicBlock *));
+JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc);
 
 #endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c
index 9a2e5c0..f8e736b 100644
--- a/vm/compiler/Dataflow.c
+++ b/vm/compiler/Dataflow.c
@@ -17,6 +17,7 @@
 #include "Dalvik.h"
 #include "Dataflow.h"
 #include "Loop.h"
+#include "dexdump/OpCodeNames.h"
 
 /*
  * Main table containing data flow attributes for each bytecode. The first
@@ -817,6 +818,59 @@
  * and subscript pair. Each SSA register can be used to index the
  * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
  */
+char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn)
+{
+    char buffer[256];
+    int opcode = insn->opCode;
+    int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
+    char *ret;
+
+    buffer[0] = 0;
+    strcpy(buffer, getOpcodeName(opcode));
+
+    if (dfAttributes & DF_FORMAT_35C) {
+        unsigned int i;
+        for (i = 0; i < insn->vA; i++) {
+            if (i != 0) strcat(buffer, ",");
+            sprintf(buffer + strlen(buffer), " v%d", insn->arg[i]);
+        }
+    }
+    else if (dfAttributes & DF_FORMAT_3RC) {
+        sprintf(buffer + strlen(buffer),
+                " v%d..v%d", insn->vC, insn->vC + insn->vA - 1);
+    }
+    else {
+        if (dfAttributes & DF_A_IS_REG) {
+            sprintf(buffer + strlen(buffer), " v%d", insn->vA);
+        }
+        if (dfAttributes & DF_B_IS_REG) {
+            sprintf(buffer + strlen(buffer),
+                    ", v%d", insn->vB);
+        }
+        else {
+            sprintf(buffer + strlen(buffer),
+                    ", (#%d)", insn->vB);
+        }
+        if (dfAttributes & DF_C_IS_REG) {
+            sprintf(buffer + strlen(buffer),
+                    ", v%d", insn->vC);
+        }
+        else {
+            sprintf(buffer + strlen(buffer),
+                    ", (#%d)", insn->vC);
+        }
+    }
+    int length = strlen(buffer) + 1;
+    ret = dvmCompilerNew(length, false);
+    memcpy(ret, buffer, length);
+    return ret;
+}
+
+/*
+ * Utility function to convert encoded SSA register value into Dalvik register
+ * and subscript pair. Each SSA register can be used to index the
+ * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
+ */
 char *dvmCompilerGetSSAString(CompilationUnit *cUnit, SSARepresentation *ssaRep)
 {
     char buffer[256];
diff --git a/vm/compiler/Dataflow.h b/vm/compiler/Dataflow.h
index e4ae93d..384d430 100644
--- a/vm/compiler/Dataflow.h
+++ b/vm/compiler/Dataflow.h
@@ -68,6 +68,10 @@
                                  DF_NULL_N_RANGE_CHECK_1 | \
                                  DF_NULL_N_RANGE_CHECK_2)
 
+#define DF_A_IS_REG             (DF_UA | DF_UA_WIDE | DF_DA | DF_DA_WIDE)
+#define DF_B_IS_REG             (DF_UB | DF_UB_WIDE)
+#define DF_C_IS_REG             (DF_UC | DF_UC_WIDE)
+
 extern int dvmCompilerDataFlowAttributes[MIR_OP_LAST];
 
 typedef struct BasicBlockDataFlow {
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 163cdf8..959c99a 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -16,7 +16,6 @@
 
 #include "Dalvik.h"
 #include "libdex/OpCode.h"
-#include "dexdump/OpCodeNames.h"
 #include "interp/Jit.h"
 #include "CompilerInternals.h"
 
@@ -42,7 +41,8 @@
 
     dexDecodeInstruction(gDvm.instrFormat, codePtr, decInsn);
     if (printMe) {
-        LOGD("%p: %#06x %s\n", codePtr, opcode, getOpcodeName(opcode));
+        char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn);
+        LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
     }
     return insnWidth;
 }
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index d1f9870..57d5d74 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -276,7 +276,7 @@
             break;
         case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
             LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
-                   getOpcodeName(lir->operands[1]));
+                 (char *) lir->operands[1]);
             break;
         case ARM_PSEUDO_EXIT_BLOCK:
             LOGD("-------- exit offset: 0x%04x\n", dest);
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index e386fac..81dd0e3 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1027,7 +1027,6 @@
     ChainCellCounts chainCellCounts;
     int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
 
-    info->codeAddress = NULL;
     info->instructionSet = cUnit->instructionSet;
 
     /* Beginning offset needs to allow space for chain cell offset */
@@ -1109,6 +1108,8 @@
         return;
     }
 
+    /* Don't go all the way if the goal is just to get the verbose output */
+    if (info->discardResult) return;
 
     cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
     gDvmJit.codeCacheByteUsed += offset;
@@ -1137,7 +1138,6 @@
 
     /* Record code entry point and instruction set */
     info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
-    info->instructionSet = cUnit->instructionSet;
     /* If applicable, mark low bit to denote thumb */
     if (info->instructionSet != DALVIK_JIT_ARM)
         info->codeAddress = (char*)info->codeAddress + 1;
@@ -1477,6 +1477,31 @@
     return *pExecutionCount;
 }
 
+/* Create a copy of the trace descriptor of an existing compilation */
+JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc)
+{
+    JitEntry *jitEntry = dvmFindJitEntry(pc);
+    if (jitEntry == NULL) return NULL;
+
+    /* Find out the startint point */
+    char *traceBase = getTraceBase(jitEntry);
+
+    /* Then find out the starting point of the chaining cell */
+    u2 *pCellOffset = (u2*) (traceBase + 4);
+    ChainCellCounts *pCellCounts =
+        (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
+
+    /* From there we can find out the starting point of the trace descriptor */
+    JitTraceDescription *desc =
+        (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+
+    /* Now make a copy and return */
+    int descSize = jitTraceDescriptionSize(desc);
+    JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
+    memcpy(newCopy, desc, descSize);
+    return newCopy;
+}
+
 /* Handy function to retrieve the profile count */
 static inline int getProfileCount(const JitEntry *entry)
 {
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index 4a85fb2..c0729ab 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -3997,7 +3997,9 @@
                 dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
             ArmLIR *boundaryLIR =
                 newLIR2(cUnit, ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY,
-                        mir->offset, dalvikOpCode);
+                        mir->offset,
+                        (int) dvmCompilerGetDalvikDisassembly(&mir->dalvikInsn)
+                       );
             if (mir->ssaRep) {
                 char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
                 newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
@@ -4209,25 +4211,33 @@
 /* Accept the work and start compiling */
 bool dvmCompilerDoWork(CompilerWorkOrder *work)
 {
-   bool res;
+    bool res;
 
-   if (gDvmJit.codeCacheFull) {
-       return false;
-   }
+    if (gDvmJit.codeCacheFull) {
+        return false;
+    }
 
-   switch (work->kind) {
-       case kWorkOrderMethod:
-           res = dvmCompileMethod(work->info, &work->result);
-           break;
-       case kWorkOrderTrace:
-           /* Start compilation with maximally allowed trace length */
-           res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
-           break;
-       default:
-           res = false;
-           dvmAbort();
-   }
-   return res;
+    switch (work->kind) {
+        case kWorkOrderMethod:
+            res = dvmCompileMethod(work->info, &work->result);
+            break;
+        case kWorkOrderTrace:
+            /* Start compilation with maximally allowed trace length */
+            res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
+            break;
+        case kWorkOrderTraceDebug: {
+            bool oldPrintMe = gDvmJit.printMe;
+            gDvmJit.printMe = true;
+            /* Start compilation with maximally allowed trace length */
+            res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
+            gDvmJit.printMe = oldPrintMe;;
+            break;
+        }
+        default:
+            res = false;
+            dvmAbort();
+    }
+    return res;
 }
 
 /* Architectural-specific debugging helpers go here */
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index d8dcf1e..1d86657 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -60,11 +60,10 @@
  * Return a pointer to the shadow space for JIT to use.
  */
 void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
-                                   void* interpStatePtr)
+                                   InterpState* interpState)
 {
     Thread *self = dvmThreadSelf();
     ShadowSpace *shadowSpace = self->shadowSpace;
-    InterpState *interpState = (InterpState *) interpStatePtr;
     int preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
     int postBytes = interpState->method->registersSize*4;
 
@@ -75,7 +74,7 @@
         LOGD("~~~ Save: INCORRECT PREVIOUS STATE(%d): %d",
             self->threadId, shadowSpace->selfVerificationState);
         LOGD("********** SHADOW STATE DUMP **********");
-        LOGD("* PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
+        LOGD("PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
     }
     shadowSpace->selfVerificationState = kSVSStart;
 
@@ -90,12 +89,18 @@
     // Remember original state
     shadowSpace->startPC = pc;
     shadowSpace->fp = fp;
-    shadowSpace->glue = interpStatePtr;
+    shadowSpace->glue = interpState;
+    /*
+     * Store the original method here in case the trace ends with a
+     * return/invoke, the last method.
+     */
+    shadowSpace->method = interpState->method;
     shadowSpace->shadowFP = shadowSpace->registerSpace +
                             shadowSpace->registerSpaceSize - postBytes/4;
 
     // Create a copy of the InterpState
-    memcpy(&(shadowSpace->interpState), interpStatePtr, sizeof(InterpState));
+    //shadowSpace->interpState = *interpState;
+    memcpy(&(shadowSpace->interpState), interpState, sizeof(InterpState));
     shadowSpace->interpState.fp = shadowSpace->shadowFP;
     shadowSpace->interpState.interpStackEnd = (u1*)shadowSpace->registerSpace;
 
@@ -132,10 +137,10 @@
         LOGD("~~~ Restore: INCORRECT PREVIOUS STATE(%d): %d",
             self->threadId, shadowSpace->selfVerificationState);
         LOGD("********** SHADOW STATE DUMP **********");
-        LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+        LOGD("Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
             (int)shadowSpace->endPC);
-        LOGD("* Interp FP: 0x%x", (int)shadowSpace->fp);
-        LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+        LOGD("Interp FP: 0x%x", (int)shadowSpace->fp);
+        LOGD("Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
             (int)shadowSpace->endShadowFP);
     }
 
@@ -150,11 +155,12 @@
 }
 
 /* Print contents of virtual registers */
-static void selfVerificationPrintRegisters(int* addr, int numWords)
+static void selfVerificationPrintRegisters(int* addr, int* addrRef,
+                                           int numWords)
 {
     int i;
     for (i = 0; i < numWords; i++) {
-        LOGD("* 0x%x: (v%d) 0x%8x", (int)(addr+i), i, *(addr+i));
+        LOGD("(v%d) 0x%8x%s", i, addr[i], addr[i] != addrRef[i] ? " X" : "");
     }
 }
 
@@ -174,19 +180,19 @@
         frameBytes2 = (int) shadowSpace->fp - (int) self->curFrame - localRegs;
     }
     LOGD("********** SHADOW STATE DUMP **********");
-    LOGD("* CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
+    LOGD("CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
         (int)(pc - stackSave->method->insns));
-    LOGD("* Class: %s Method: %s", stackSave->method->clazz->descriptor,
-        stackSave->method->name);
-    LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+    LOGD("Class: %s", shadowSpace->method->clazz->descriptor);
+    LOGD("Method: %s", shadowSpace->method->name);
+    LOGD("Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
         (int)shadowSpace->endPC);
-    LOGD("* Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
+    LOGD("Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
         (int)self->curFrame);
-    LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+    LOGD("Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
         (int)shadowSpace->endShadowFP);
-    LOGD("* Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
+    LOGD("Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
         localRegs, frameBytes2);
-    LOGD("* Trace length: %d State: %d", shadowSpace->traceLength,
+    LOGD("Trace length: %d State: %d", shadowSpace->traceLength,
         shadowSpace->selfVerificationState);
 }
 
@@ -204,15 +210,18 @@
         offset =  (int)((u2*)addr - stackSave->method->insns);
         decInsn = &(shadowSpace->trace[i].decInsn);
         /* Not properly decoding instruction, some registers may be garbage */
-        LOGD("* 0x%x: (0x%04x) %s v%d, v%d, v%d", addr, offset,
-            getOpcodeName(decInsn->opCode), decInsn->vA, decInsn->vB,
-            decInsn->vC);
+        LOGD("0x%x: (0x%04x) %s", addr, offset, getOpcodeName(decInsn->opCode));
     }
 }
 
 /* Code is forced into this spin loop when a divergence is detected */
-static void selfVerificationSpinLoop()
+static void selfVerificationSpinLoop(ShadowSpace *shadowSpace)
 {
+    const u2 *startPC = shadowSpace->startPC;
+    JitTraceDescription* desc = dvmCopyTraceDescriptor(startPC);
+    if (desc) {
+        dvmCompilerWorkEnqueue(startPC, kWorkOrderTraceDebug, desc);
+    }
     gDvmJit.selfVerificationSpin = true;
     while(gDvmJit.selfVerificationSpin) sleep(10);
 }
@@ -254,17 +263,20 @@
                          shadowSpace->registerSpaceSize*4 -
                          (int) shadowSpace->shadowFP;
         if (memcmp(shadowSpace->fp, shadowSpace->shadowFP, frameBytes)) {
-            LOGD("~~~ DbgIntp(%d): REGISTERS UNEQUAL!", self->threadId);
+            LOGD("~~~ DbgIntp(%d): REGISTERS DIVERGENCE!", self->threadId);
             selfVerificationDumpState(pc, self);
             selfVerificationDumpTrace(pc, self);
             LOGD("*** Interp Registers: addr: 0x%x bytes: %d",
                 (int)shadowSpace->fp, frameBytes);
-            selfVerificationPrintRegisters((int*)shadowSpace->fp, frameBytes/4);
+            selfVerificationPrintRegisters((int*)shadowSpace->fp,
+                                           (int*)shadowSpace->shadowFP,
+                                           frameBytes/4);
             LOGD("*** Shadow Registers: addr: 0x%x bytes: %d",
                 (int)shadowSpace->shadowFP, frameBytes);
             selfVerificationPrintRegisters((int*)shadowSpace->shadowFP,
-                frameBytes/4);
-            selfVerificationSpinLoop();
+                                           (int*)shadowSpace->fp,
+                                           frameBytes/4);
+            selfVerificationSpinLoop(shadowSpace);
         }
         /* Check new frame if it exists (invokes only) */
         if (self->curFrame < shadowSpace->fp) {
@@ -275,19 +287,21 @@
                               (int) self->curFrame - localRegs;
             if (memcmp(((char*)self->curFrame)+localRegs,
                 ((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
-                LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) UNEQUAL!",
+                LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) DIVERGENCE!",
                     self->threadId);
                 selfVerificationDumpState(pc, self);
                 selfVerificationDumpTrace(pc, self);
                 LOGD("*** Interp Registers: addr: 0x%x l: %d bytes: %d",
                     (int)self->curFrame, localRegs, frameBytes2);
                 selfVerificationPrintRegisters((int*)self->curFrame,
-                    (frameBytes2+localRegs)/4);
+                                               (int*)shadowSpace->endShadowFP,
+                                               (frameBytes2+localRegs)/4);
                 LOGD("*** Shadow Registers: addr: 0x%x l: %d bytes: %d",
                     (int)shadowSpace->endShadowFP, localRegs, frameBytes2);
                 selfVerificationPrintRegisters((int*)shadowSpace->endShadowFP,
-                    (frameBytes2+localRegs)/4);
-                selfVerificationSpinLoop();
+                                               (int*)self->curFrame,
+                                               (frameBytes2+localRegs)/4);
+                selfVerificationSpinLoop(shadowSpace);
             }
         }
 
@@ -298,25 +312,25 @@
              heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
             int memData = *((unsigned int*) heapSpacePtr->addr);
             if (heapSpacePtr->data != memData) {
-                LOGD("~~~ DbgIntp(%d): MEMORY UNEQUAL!", self->threadId);
-                LOGD("* Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
+                LOGD("~~~ DbgIntp(%d): MEMORY DIVERGENCE!", self->threadId);
+                LOGD("Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
                     heapSpacePtr->addr, memData, heapSpacePtr->data);
                 selfVerificationDumpState(pc, self);
                 selfVerificationDumpTrace(pc, self);
                 memDiff = true;
             }
         }
-        if (memDiff) selfVerificationSpinLoop();
+        if (memDiff) selfVerificationSpinLoop(shadowSpace);
         return true;
 
     /* If end not been reached, make sure max length not exceeded */
     } else if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
         LOGD("~~~ DbgIntp(%d): CONTROL DIVERGENCE!", self->threadId);
-        LOGD("* startPC: 0x%x endPC: 0x%x currPC: 0x%x",
+        LOGD("startPC: 0x%x endPC: 0x%x currPC: 0x%x",
             (int)shadowSpace->startPC, (int)shadowSpace->endPC, (int)pc);
         selfVerificationDumpState(pc, self);
         selfVerificationDumpTrace(pc, self);
-        selfVerificationSpinLoop();
+        selfVerificationSpinLoop(shadowSpace);
 
         return true;
     }
@@ -656,7 +670,7 @@
     return switchInterp;
 }
 
-static inline JitEntry *findJitEntry(const u2* pc)
+JitEntry *dvmFindJitEntry(const u2* pc)
 {
     int idx = dvmJitHash(pc);
 
@@ -674,11 +688,6 @@
     return NULL;
 }
 
-JitEntry *dvmFindJitEntry(const u2* pc)
-{
-    return findJitEntry(pc);
-}
-
 /*
  * If a translated code address exists for the davik byte code
  * pointer return it.  This routine needs to be fast.
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index 70931b8..fe740e5 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -43,7 +43,7 @@
 typedef struct ShadowSpace {
     const u2* startPC;          /* starting pc of jitted region */
     const void* fp;             /* starting fp of jitted region */
-    void* glue;                 /* starting glue ptr of jitted region */
+    const void* glue;           /* starting glue of jitted region */
     SelfVerificationState selfVerificationState;  /* self verification state */
     const u2* endPC;            /* ending pc of jitted region */
     void* shadowFP;       /* pointer to fp in shadow space */
@@ -55,6 +55,7 @@
     const void* endShadowFP;    /* ending fp in shadow space */
     InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */
     int traceLength;            /* counter for current trace length */
+    const Method* method;       /* starting method of jitted region */
 } ShadowSpace;
 
 /*
@@ -63,7 +64,7 @@
 void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
 void dvmSelfVerificationShadowSpaceFree(Thread* self);
 void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
-                                   void* interpStatePtr);
+                                   InterpState* interpState);
 void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
                                       SelfVerificationState exitPoint);
 #endif
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 461cc66..bca89c1 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -229,17 +229,14 @@
  * before jumping to native translation.
  */
 dvmJitSelfVerificationStart:
-    sub     sp,sp,#4                    @ allocate stack space
-    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
-    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
-    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
-    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
-    add     sp,sp,#4                    @ restore stack
-    bx      r0                          @ jump to the translation
+    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+    bx      r10                         @ jump to the translation
 
 /*
  * Restore PC, registers, and interpState to original values
@@ -248,10 +245,10 @@
 dvmJitSelfVerificationEnd:
     mov    r1,rFP                        @ pass ending fp
     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
-    ldr    rPC,[r0,#0]                   @ restore PC
-    ldr    rFP,[r0,#4]                   @ restore FP
-    ldr    rGLUE,[r0,#8]                 @ restore InterpState
-    ldr    r1,[r0,#12]                   @ get exitPoint
+    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
+    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
+    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
     cmp    r1,#0                         @ check for punt condition
     beq    1f
     mov    r2,#kJitSelfVerification      @ ask for self verification
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index e157c37..9dbf6e8 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -169,6 +169,16 @@
 MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 20)
 #endif
 
+  /* ShadowSpace fields */
+#if defined(WITH_JIT) && defined(WITH_SELF_VERIFICATION)
+MTERP_OFFSET(offShadowSpace_startPC, ShadowSpace, startPC, 0)
+MTERP_OFFSET(offShadowSpace_fp, ShadowSpace, fp, 4)
+MTERP_OFFSET(offShadowSpace_glue, ShadowSpace, glue, 8)
+MTERP_OFFSET(offShadowSpace_svState, ShadowSpace, selfVerificationState, 12)
+MTERP_OFFSET(offShadowSpace_shadowFP, ShadowSpace, shadowFP, 20)
+MTERP_OFFSET(offShadowSpace_interpState, ShadowSpace, interpState, 24)
+#endif
+
 /* InstField fields */
 #ifdef PROFILE_FIELD_ACCESS
 MTERP_OFFSET(offInstField_byteOffset,   InstField, byteOffset, 24)
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 07075bb..6153010 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -9701,17 +9701,14 @@
  * before jumping to native translation.
  */
 dvmJitSelfVerificationStart:
-    sub     sp,sp,#4                    @ allocate stack space
-    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
-    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
-    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
-    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
-    add     sp,sp,#4                    @ restore stack
-    bx      r0                          @ jump to the translation
+    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+    bx      r10                         @ jump to the translation
 
 /*
  * Restore PC, registers, and interpState to original values
@@ -9720,10 +9717,10 @@
 dvmJitSelfVerificationEnd:
     mov    r1,rFP                        @ pass ending fp
     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
-    ldr    rPC,[r0,#0]                   @ restore PC
-    ldr    rFP,[r0,#4]                   @ restore FP
-    ldr    rGLUE,[r0,#8]                 @ restore InterpState
-    ldr    r1,[r0,#12]                   @ get exitPoint
+    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
+    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
+    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
     cmp    r1,#0                         @ check for punt condition
     beq    1f
     mov    r2,#kJitSelfVerification      @ ask for self verification
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 55ac716..dde4bd5 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -9219,17 +9219,14 @@
  * before jumping to native translation.
  */
 dvmJitSelfVerificationStart:
-    sub     sp,sp,#4                    @ allocate stack space
-    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
-    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
-    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
-    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
-    add     sp,sp,#4                    @ restore stack
-    bx      r0                          @ jump to the translation
+    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+    bx      r10                         @ jump to the translation
 
 /*
  * Restore PC, registers, and interpState to original values
@@ -9238,10 +9235,10 @@
 dvmJitSelfVerificationEnd:
     mov    r1,rFP                        @ pass ending fp
     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
-    ldr    rPC,[r0,#0]                   @ restore PC
-    ldr    rFP,[r0,#4]                   @ restore FP
-    ldr    rGLUE,[r0,#8]                 @ restore InterpState
-    ldr    r1,[r0,#12]                   @ get exitPoint
+    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
+    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
+    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
     cmp    r1,#0                         @ check for punt condition
     beq    1f
     mov    r2,#kJitSelfVerification      @ ask for self verification
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 55f6fee..b7d8a6c 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9695,17 +9695,14 @@
  * before jumping to native translation.
  */
 dvmJitSelfVerificationStart:
-    sub     sp,sp,#4                    @ allocate stack space
-    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
-    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
-    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
-    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
-    add     sp,sp,#4                    @ restore stack
-    bx      r0                          @ jump to the translation
+    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+    bx      r10                         @ jump to the translation
 
 /*
  * Restore PC, registers, and interpState to original values
@@ -9714,10 +9711,10 @@
 dvmJitSelfVerificationEnd:
     mov    r1,rFP                        @ pass ending fp
     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
-    ldr    rPC,[r0,#0]                   @ restore PC
-    ldr    rFP,[r0,#4]                   @ restore FP
-    ldr    rGLUE,[r0,#8]                 @ restore InterpState
-    ldr    r1,[r0,#12]                   @ get exitPoint
+    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
+    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
+    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
     cmp    r1,#0                         @ check for punt condition
     beq    1f
     mov    r2,#kJitSelfVerification      @ ask for self verification
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 3c896ae..ea9e713 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -9155,17 +9155,14 @@
  * before jumping to native translation.
  */
 dvmJitSelfVerificationStart:
-    sub     sp,sp,#4                    @ allocate stack space
-    str     r0,[sp,#0]                  @ save out dvmJitGetCodeAddr(rPC)
+    mov     r10, r0                     @ r10 <- dvmJitGetCodeAddr(rPC)
     mov     r0,rPC                      @ r0<- program counter
     mov     r1,rFP                      @ r1<- frame pointer
     mov     r2,rGLUE                    @ r2<- InterpState pointer
     bl      dvmSelfVerificationSaveState @ save registers to shadow space
-    ldr     rFP,[r0,#20]                @ rFP<- fp in shadow space
-    add     rGLUE,r0,#24                @ rGLUE<- pointer in shadow space
-    ldr     r0,[sp,#0]                  @ r0<- dvmJitGetCodeAddr(rPC)
-    add     sp,sp,#4                    @ restore stack
-    bx      r0                          @ jump to the translation
+    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
+    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
+    bx      r10                         @ jump to the translation
 
 /*
  * Restore PC, registers, and interpState to original values
@@ -9174,10 +9171,10 @@
 dvmJitSelfVerificationEnd:
     mov    r1,rFP                        @ pass ending fp
     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
-    ldr    rPC,[r0,#0]                   @ restore PC
-    ldr    rFP,[r0,#4]                   @ restore FP
-    ldr    rGLUE,[r0,#8]                 @ restore InterpState
-    ldr    r1,[r0,#12]                   @ get exitPoint
+    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
+    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
+    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
+    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
     cmp    r1,#0                         @ check for punt condition
     beq    1f
     mov    r2,#kJitSelfVerification      @ ask for self verification