Make the traige process for self-verification found divergence easier.

1. Automatically replay the code compilation with verbose mode turned on for
   the offending compilation.
3. Mark the registers with divergence explicitly.
2. Print accurate operand names using the dataflow attributes. Constant values
   are still printed for reference only.
3. Fixed a few correctness/style issues in self-verification code.
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