Jit stress mode: translate everything we can and self verify.

This represents a general clean-up of some existing command-line
options: -Xjitthreshold:num and -Xjitblocking.  The jit threshold
controls how quickly we treat a Dalvik address as a potential trace
head.  Normally this is set around 200 (and the range is 0..255, where
0 is in effect 256 and 1 means begin trace selection on first visit).

-Xjitblocking forces the system to pause execution whenever a translation
request is made and resume when that translation is complete.  Normally
the system make a request but continues execution (to avoid jitter).

Additionally, if WITH_SELF_VERIFICATION is defined, we force blocking
to be true, and set the threshold to 1.  And finally, we treat
threshold==1 as a special case and disable the 2nd-level trace-building
filter - which causes the system to immediately start trace selection.
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*/