Merge change Id726991b

* changes:
  Jit stress mode: translate everything we can and self verify.
diff --git a/vm/Init.c b/vm/Init.c
index 7f83bc5..f77dba6 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -114,8 +114,8 @@
     dvmFprintf(stderr, "  -Xjitop:hexopvalue[-endvalue]"
                        "[,hexopvalue[-endvalue]]*\n");
     dvmFprintf(stderr, "  -Xincludeselectedmethod\n");
-    dvmFprintf(stderr, "  -Xthreshold:decimalvalue\n");
-    dvmFprintf(stderr, "  -Xblocking\n");
+    dvmFprintf(stderr, "  -Xjitthreshold:decimalvalue\n");
+    dvmFprintf(stderr, "  -Xjitblocking\n");
     dvmFprintf(stderr, "  -Xjitmethod:signture[,signature]* "
                        "(eg Ljava/lang/String\\;replace)\n");
     dvmFprintf(stderr, "  -Xjitverbose\n");
@@ -899,10 +899,10 @@
             processXjitop(argv[i]);
         } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
             processXjitmethod(argv[i]);
-        } else if (strncmp(argv[i], "-Xblocking", 10) == 0) {
+        } else if (strncmp(argv[i], "-Xjitblocking", 13) == 0) {
           gDvmJit.blockingMode = true;
-        } else if (strncmp(argv[i], "-Xthreshold:", 12) == 0) {
-          gDvmJit.threshold = atoi(argv[i] + 12);
+        } else if (strncmp(argv[i], "-Xjitthreshold:", 15) == 0) {
+          gDvmJit.threshold = atoi(argv[i] + 15);
         } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
           gDvmJit.includeSelectedOp = true;
         } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index a44e1c3..b53ebf8 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -96,11 +96,13 @@
 /* Block until queue length is 0 */
 void dvmCompilerDrainQueue(void)
 {
+    int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
     dvmLockMutex(&gDvmJit.compilerLock);
     while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) {
         pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock);
     }
     dvmUnlockMutex(&gDvmJit.compilerLock);
+    dvmChangeStatus(NULL, oldStatus);
 }
 
 static void *compilerThreadStart(void *arg)
@@ -135,11 +137,12 @@
                 if (gDvmJit.haltCompilerThread) {
                     LOGD("Compiler shutdown in progress - discarding request");
                 } else {
-                    /* Compilation is successful */
-                    if (dvmCompilerDoWork(&work)) {
-                        dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
-                                          work.result.instructionSet);
+                    /* If compilation failed, use interpret-template */
+                    if (!dvmCompilerDoWork(&work)) {
+                        work.result.codeAddress = gDvmJit.interpretTemplate;
                     }
+                    dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
+                                      work.result.instructionSet);
                 }
                 free(work.info);
                 dvmLockMutex(&gDvmJit.compilerLock);
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
index 02b9b79..a2e4175 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -323,6 +323,7 @@
     if (isDouble) {
         rlSrc1 = loadValueWide(cUnit, rlSrc1, kFPReg);
         rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
+        clobberSReg(cUnit, rlDest.sRegLow);
         rlResult = evalLoc(cUnit, rlDest, kCoreReg, true);
         loadConstant(cUnit, rlResult.lowReg, defaultResult);
         newLIR2(cUnit, kThumb2Vcmpd, S2D(rlSrc1.lowReg, r1Src2.highReg),
@@ -330,6 +331,7 @@
     } else {
         rlSrc1 = loadValue(cUnit, rlSrc1, kFPReg);
         rlSrc2 = loadValue(cUnit, rlSrc2, kFPReg);
+        clobberSReg(cUnit, rlDest.sRegLow);
         rlResult = evalLoc(cUnit, rlDest, kCoreReg, true);
         loadConstant(cUnit, rlResult.lowReg, defaultResult);
         newLIR2(cUnit, kThumb2Vcmps, rlSrc1.lowReg, rlSrc2.lowReg);
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index 41a2bb8..744033e 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -150,7 +150,7 @@
     JitState           jitState;
     void*              jitResume;
     u2*                jitResumePC;
-    const u2*          jitTraceInProgress;
+    int                jitThreshold;
 #endif
 
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index d9b9caa..4c09979 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -348,6 +348,12 @@
     unsigned int i;
     bool res = true;  /* Assume success */
 
+#if defined(WITH_SELF_VERIFICATION)
+    // Force JIT into blocking, translate everything mode
+    gDvmJit.threshold = 1;
+    gDvmJit.blockingMode = true;
+#endif
+
     // Create the compiler thread and setup miscellaneous chores */
     res &= dvmCompilerStartup();
 
@@ -380,7 +386,7 @@
             res = false;
             goto done;
         }
-        memset(pJitProfTable,0,JIT_PROF_SIZE);
+        memset(pJitProfTable,gDvmJit.threshold,JIT_PROF_SIZE);
         for (i=0; i < gDvmJit.jitTableSize; i++) {
            pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
         }
@@ -514,6 +520,32 @@
     }
 }
 
+void setTraceConstruction(JitEntry *slot, bool value)
+{
+
+    JitEntryInfoUnion oldValue;
+    JitEntryInfoUnion newValue;
+    do {
+        oldValue = slot->u;
+        newValue = oldValue;
+        newValue.info.traceConstruction = value;
+    } while (!ATOMIC_CMP_SWAP( &slot->u.infoWord,
+             oldValue.infoWord, newValue.infoWord));
+}
+
+void resetTracehead(InterpState* interpState, JitEntry *slot)
+{
+    slot->codeAddress = gDvmJit.interpretTemplate;
+    setTraceConstruction(slot, false);
+}
+
+/* Clean up any pending trace builds */
+void dvmJitAbortTraceSelect(InterpState* interpState)
+{
+    if (interpState->jitState == kJitTSelect)
+        interpState->jitState = kJitTSelectAbort;
+}
+
 /*
  * Adds to the current trace request one instruction at a time, just
  * before that instruction is interpreted.  This is the primary trace
@@ -539,6 +571,7 @@
                           || gDvm.activeProfilers
 #endif
             );
+
     /* Prepare to handle last PC and stage the current PC */
     const u2 *lastPC = interpState->lastPC;
     interpState->lastPC = pc;
@@ -625,6 +658,8 @@
         case kJitTSelectEnd:
             {
                 if (interpState->totalTraceLen == 0) {
+                    /* Bad trace - mark as untranslatable */
+                    dvmJitAbortTraceSelect(interpState);
                     switchInterp = !debugOrProfile;
                     break;
                 }
@@ -635,6 +670,7 @@
                     LOGE("Out of memory in trace selection");
                     dvmJitStopTranslationRequests();
                     interpState->jitState = kJitTSelectAbort;
+                    dvmJitAbortTraceSelect(interpState);
                     switchInterp = !debugOrProfile;
                     break;
                 }
@@ -650,7 +686,8 @@
 #endif
                 dvmCompilerWorkEnqueue(
                        interpState->currTraceHead,kWorkOrderTrace,desc);
-                interpState->jitTraceInProgress = NULL;
+                setTraceConstruction(
+                     dvmJitLookupAndAdd(interpState->currTraceHead), false);
                 if (gDvmJit.blockingMode) {
                     dvmCompilerDrainQueue();
                 }
@@ -668,6 +705,7 @@
 #if defined(SHOW_TRACE)
             LOGD("TraceGen:  trace abort");
 #endif
+            dvmJitAbortTraceSelect(interpState);
             interpState->jitState = kJitNormal;
             switchInterp = !debugOrProfile;
             break;
@@ -864,7 +902,6 @@
  * otherwise.  NOTE: may be called even when trace selection is not being
  * requested
  */
-
 bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState)
 {
     bool res = false;         /* Assume success */
@@ -873,11 +910,6 @@
      * If previous trace-building attempt failed, force it's head to be
      * interpret-only.
      */
-    if (interpState->jitTraceInProgress) {
-        JitEntry *slot = dvmJitLookupAndAdd(interpState->jitTraceInProgress);
-        slot->codeAddress = gDvmJit.interpretTemplate;
-        interpState->jitTraceInProgress = NULL;
-    }
     if (gDvmJit.pJitEntryTable != NULL) {
         /* Two-level filtering scheme */
         for (i=0; i< JIT_TRACE_THRESH_FILTER_SIZE; i++) {
@@ -894,6 +926,10 @@
             interpState->threshFilter[i] = interpState->pc;
             res = true;
         }
+
+        /* If stress mode (threshold==1), always translate */
+        res &= (gDvmJit.threshold != 1);
+
         /*
          * If the compiler is backlogged, or if a debugger or profiler is
          * active, cancel any JIT actions
@@ -919,26 +955,38 @@
                 interpState->jitState = kJitTSelectAbort;
                 LOGD("JIT: JitTable full, disabling profiling");
                 dvmJitStopTranslationRequests();
-            } else if (slot->u.info.traceRequested) {
-                /* Trace already requested - revert to interpreter */
+            } else if (slot->u.info.traceConstruction) {
+                /*
+                 * Trace already request in progress, but most likely it
+                 * aborted without cleaning up.  Assume the worst and
+                 * mark trace head as untranslatable.  If we're wrong,
+                 * the compiler thread will correct the entry when the
+                 * translation is completed.  The downside here is that
+                 * some existing translation may chain to the interpret-only
+                 * template instead of the real translation during this
+                 * window.  Performance, but not correctness, issue.
+                 */
+                interpState->jitState = kJitTSelectAbort;
+                resetTracehead(interpState, slot);
+            } else if (slot->codeAddress) {
+                 /* Nothing to do here - just return */
                 interpState->jitState = kJitTSelectAbort;
             } else {
-                /* Mark request */
-                JitEntryInfoUnion oldValue;
-                JitEntryInfoUnion newValue;
-                do {
-                    oldValue = slot->u;
-                    newValue = oldValue;
-                    newValue.info.traceRequested = true;
-                } while (!ATOMIC_CMP_SWAP( &slot->u.infoWord,
-                         oldValue.infoWord, newValue.infoWord));
+                /*
+                 * Mark request.  Note, we are not guaranteed exclusivity
+                 * here.  A window exists for another thread to be
+                 * attempting to build this same trace.  Rather than
+                 * bear the cost of locking, we'll just allow that to
+                 * happen.  The compiler thread, if it chooses, can
+                 * discard redundant requests.
+                 */
+                setTraceConstruction(slot, true);
             }
         }
         switch (interpState->jitState) {
             case kJitTSelectRequest:
                  interpState->jitState = kJitTSelect;
                  interpState->currTraceHead = interpState->pc;
-                 interpState->jitTraceInProgress = interpState->pc;
                  interpState->currTraceRun = 0;
                  interpState->totalTraceLen = 0;
                  interpState->currRunHead = interpState->pc;
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index a69a1f0..b093164 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -89,13 +89,13 @@
  */
 
 typedef struct JitEntryInfo {
-    unsigned int           traceRequested:1;   /* already requested a translation */
+    unsigned int           traceConstruction:1;   /* build underway? */
     unsigned int           isMethodEntry:1;
     unsigned int           inlineCandidate:1;
     unsigned int           profileEnabled:1;
     JitInstructionSetType  instructionSet:4;
     unsigned int           unused:8;
-    u2                     chain;              /* Index of next in chain */
+    u2                     chain;                 /* Index of next in chain */
 } JitEntryInfo;
 
 typedef union JitEntryInfoUnion {
@@ -122,6 +122,8 @@
 s8 dvmJitd2l(double d);
 s8 dvmJitf2l(float f);
 void dvmJitSetCodeAddr(const u2* dPC, void *nPC, JitInstructionSetType set);
+void dvmJitAbortTraceSelect(InterpState* interpState);
+JitEntry *dvmJitLookupAndAdd(const u2* dPC);
 
 
 #endif /*_DALVIK_INTERP_JIT*/
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.c
index 053f544..dbae516 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.c
@@ -83,6 +83,7 @@
     glue->pSelfSuspendCount = &self->suspendCount;
 #if defined(WITH_JIT)
     glue->pJitProfTable = gDvmJit.pProfTable;
+    glue->jitThreshold = gDvmJit.threshold;
 #endif
 #if defined(WITH_DEBUGGER)
     glue->pDebuggerActive = &gDvm.debuggerActive;
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index e6c6cfc..317f151 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -209,7 +209,7 @@
  * is already a native translation in place (and, if so,
  * jump to it now).
  */
-    mov     r1,#255
+    GET_JIT_THRESHOLD(r1)
     strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
diff --git a/vm/mterp/armv5te/header.S b/vm/mterp/armv5te/header.S
index e129b15..78b2282 100644
--- a/vm/mterp/armv5te/header.S
+++ b/vm/mterp/armv5te/header.S
@@ -180,6 +180,7 @@
 #if defined(WITH_JIT)
 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
 #endif
 
 /*
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index 67b3299..1bf188f 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -532,6 +532,10 @@
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
             LOGVV("+++ returned into break frame\n");
+#if defined(WITH_JIT)
+            /* Let the Jit know the return is terminating normally */
+            CHECK_JIT();
+#endif
             GOTO_bail();
         }
 
@@ -578,9 +582,7 @@
 
 #if defined(WITH_JIT)
         // Something threw during trace selection - abort the current trace
-        if (interpState->jitState == kJitTSelect) {
-            interpState->jitState = kJitTSelectEnd;
-        }
+        dvmJitAbortTraceSelect(interpState);
 #endif
         /*
          * We save off the exception and clear the exception status.  While
@@ -892,6 +894,11 @@
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                 methodToCall->name, methodToCall->shorty);
 
+#if defined(WITH_JIT)
+            /* Allow the Jit to end any pending trace building */
+            CHECK_JIT();
+#endif
+
             /*
              * Jump through native call bridge.  Because we leave no
              * space for locals on native calls, "newFp" points directly
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index baf6af7..f982793 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -106,6 +106,7 @@
 MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 60)
 MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 64)
 MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 68)
+MTERP_OFFSET(offGlue_jitThreshold,      MterpGlue, jitThreshold, 72)
 #endif
 #elif defined(WITH_DEBUGGER)
 MTERP_OFFSET(offGlue_pDebuggerActive,   MterpGlue, pDebuggerActive, 40)
@@ -115,6 +116,7 @@
 MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
 MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
 MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
+MTERP_OFFSET(offGlue_jitThreshold,      MterpGlue, jitThreshold, 68)
 #endif
 #elif defined(WITH_PROFILER)
 MTERP_OFFSET(offGlue_pActiveProfilers,  MterpGlue, pActiveProfilers, 40)
@@ -124,6 +126,7 @@
 MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
 MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
 MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
+MTERP_OFFSET(offGlue_jitThreshold,      MterpGlue, jitThreshold, 68)
 #endif
 #else
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 40)
@@ -132,6 +135,7 @@
 MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 52)
 MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 56)
 MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 60)
+MTERP_OFFSET(offGlue_jitThreshold,      MterpGlue, jitThreshold, 64)
 #endif
 #endif
 /* make sure all JValue union members are stored at the same offset */
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index f1729eb..56d0a26 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -187,6 +187,7 @@
 #if defined(WITH_JIT)
 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
 #endif
 
 /*
@@ -9681,7 +9682,7 @@
  * is already a native translation in place (and, if so,
  * jump to it now).
  */
-    mov     r1,#255
+    GET_JIT_THRESHOLD(r1)
     strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 5cf8cca..c7926f6 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -187,6 +187,7 @@
 #if defined(WITH_JIT)
 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
 #endif
 
 /*
@@ -9199,7 +9200,7 @@
  * is already a native translation in place (and, if so,
  * jump to it now).
  */
-    mov     r1,#255
+    GET_JIT_THRESHOLD(r1)
     strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 5e1ed1c..3c5c496 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -187,6 +187,7 @@
 #if defined(WITH_JIT)
 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
 #endif
 
 /*
@@ -9675,7 +9676,7 @@
  * is already a native translation in place (and, if so,
  * jump to it now).
  */
-    mov     r1,#255
+    GET_JIT_THRESHOLD(r1)
     strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 7af0a79..aaf85d9 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -187,6 +187,7 @@
 #if defined(WITH_JIT)
 #define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
 #endif
 
 /*
@@ -9135,7 +9136,7 @@
  * is already a native translation in place (and, if so,
  * jump to it now).
  */
-    mov     r1,#255
+    GET_JIT_THRESHOLD(r1)
     strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 1d31227..04d7c32 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -3565,6 +3565,10 @@
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
             LOGVV("+++ returned into break frame\n");
+#if defined(WITH_JIT)
+            /* Let the Jit know the return is terminating normally */
+            CHECK_JIT();
+#endif
             GOTO_bail();
         }
 
@@ -3611,9 +3615,7 @@
 
 #if defined(WITH_JIT)
         // Something threw during trace selection - abort the current trace
-        if (interpState->jitState == kJitTSelect) {
-            interpState->jitState = kJitTSelectEnd;
-        }
+        dvmJitAbortTraceSelect(interpState);
 #endif
         /*
          * We save off the exception and clear the exception status.  While
@@ -3925,6 +3927,11 @@
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                 methodToCall->name, methodToCall->shorty);
 
+#if defined(WITH_JIT)
+            /* Allow the Jit to end any pending trace building */
+            CHECK_JIT();
+#endif
+
             /*
              * Jump through native call bridge.  Because we leave no
              * space for locals on native calls, "newFp" points directly
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 03fe00e..4d15b45 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -3863,6 +3863,10 @@
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
             LOGVV("+++ returned into break frame\n");
+#if defined(WITH_JIT)
+            /* Let the Jit know the return is terminating normally */
+            CHECK_JIT();
+#endif
             GOTO_bail();
         }
 
@@ -3909,9 +3913,7 @@
 
 #if defined(WITH_JIT)
         // Something threw during trace selection - abort the current trace
-        if (interpState->jitState == kJitTSelect) {
-            interpState->jitState = kJitTSelectEnd;
-        }
+        dvmJitAbortTraceSelect(interpState);
 #endif
         /*
          * We save off the exception and clear the exception status.  While
@@ -4223,6 +4225,11 @@
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                 methodToCall->name, methodToCall->shorty);
 
+#if defined(WITH_JIT)
+            /* Allow the Jit to end any pending trace building */
+            CHECK_JIT();
+#endif
+
             /*
              * Jump through native call bridge.  Because we leave no
              * space for locals on native calls, "newFp" points directly
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index a092da0..6ea6a56 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -3579,6 +3579,10 @@
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
             LOGVV("+++ returned into break frame\n");
+#if defined(WITH_JIT)
+            /* Let the Jit know the return is terminating normally */
+            CHECK_JIT();
+#endif
             GOTO_bail();
         }
 
@@ -3625,9 +3629,7 @@
 
 #if defined(WITH_JIT)
         // Something threw during trace selection - abort the current trace
-        if (interpState->jitState == kJitTSelect) {
-            interpState->jitState = kJitTSelectEnd;
-        }
+        dvmJitAbortTraceSelect(interpState);
 #endif
         /*
          * We save off the exception and clear the exception status.  While
@@ -3939,6 +3941,11 @@
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                 methodToCall->name, methodToCall->shorty);
 
+#if defined(WITH_JIT)
+            /* Allow the Jit to end any pending trace building */
+            CHECK_JIT();
+#endif
+
             /*
              * Jump through native call bridge.  Because we leave no
              * space for locals on native calls, "newFp" points directly
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index fa2dfa8..ed42355 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1720,6 +1720,10 @@
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
             LOGVV("+++ returned into break frame\n");
+#if defined(WITH_JIT)
+            /* Let the Jit know the return is terminating normally */
+            CHECK_JIT();
+#endif
             GOTO_bail();
         }
 
@@ -1766,9 +1770,7 @@
 
 #if defined(WITH_JIT)
         // Something threw during trace selection - abort the current trace
-        if (interpState->jitState == kJitTSelect) {
-            interpState->jitState = kJitTSelectEnd;
-        }
+        dvmJitAbortTraceSelect(interpState);
 #endif
         /*
          * We save off the exception and clear the exception status.  While
@@ -2080,6 +2082,11 @@
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
                 methodToCall->name, methodToCall->shorty);
 
+#if defined(WITH_JIT)
+            /* Allow the Jit to end any pending trace building */
+            CHECK_JIT();
+#endif
+
             /*
              * Jump through native call bridge.  Because we leave no
              * space for locals on native calls, "newFp" points directly