Add counters to track JIT inline cache hit rate and code cache patch counts.

Also did some WITH_JIT_TUNING cleanup.

Change-Id: I8bb2d681a06b0f2af1f976a007326825a88cea38
diff --git a/vm/Android.mk b/vm/Android.mk
index ae78139..b42608a 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -57,7 +57,7 @@
 
     # Enable assertions and JIT-tuning
     LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT \
-				    -DWITH_JIT_TUNING -DJIT_STATS
+				    -DWITH_JIT_TUNING
     LOCAL_MODULE := libdvm_assert
     include $(BUILD_SHARED_LIBRARY)
 
diff --git a/vm/Globals.h b/vm/Globals.h
index 354970a..a58a8c9 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -732,20 +732,7 @@
 
     /* JIT internal stats */
     int                compilerMaxQueued;
-    int                addrLookupsFound;
-    int                addrLookupsNotFound;
-    int                noChainExit[kNoChainExitLast];
-    int                normalExit;
-    int                puntExit;
     int                translationChains;
-    int                invokeMonomorphic;
-    int                invokePolymorphic;
-    int                invokeNative;
-    int                returnOp;
-    int                icPatchFast;
-    int                icPatchQueued;
-    int                icPatchDropped;
-    u8                 jitTime;
 
     /* Compiled code cache */
     void* codeCache;
@@ -821,6 +808,24 @@
     u4 *signatureBreakpoint;            // Signature content
 #endif
 
+#if defined(WITH_JIT_TUNING)
+    /* Performance tuning counters */
+    int                addrLookupsFound;
+    int                addrLookupsNotFound;
+    int                noChainExit[kNoChainExitLast];
+    int                normalExit;
+    int                puntExit;
+    int                invokeMonomorphic;
+    int                invokePolymorphic;
+    int                invokeNative;
+    int                returnOp;
+    int                icPatchFast;
+    int                icPatchQueued;
+    int                icPatchDropped;
+    u8                 jitTime;
+    int                codeCachePatches;
+#endif
+
     /* Place arrays at the end to ease the display in gdb sessions */
 
     /* Work order queue for compilations */
@@ -832,6 +837,10 @@
 
 extern struct DvmJitGlobals gDvmJit;
 
+#if defined(WITH_JIT_TUNING)
+extern int gDvmICHitCount;
+#endif
+
 #endif
 
 #endif /*_DALVIK_GLOBALS*/
diff --git a/vm/Init.c b/vm/Init.c
index 2cb754c..9cfd67d 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -51,6 +51,15 @@
 /* JIT-specific global state */
 #if defined(WITH_JIT)
 struct DvmJitGlobals gDvmJit;
+
+#if defined(WITH_JIT_TUNING)
+/*
+ * Track the number of hits in the inline cache for predicted chaining.
+ * Use an ugly global variable here since it is accessed in assembly code.
+ */
+int gDvmICHitCount;
+#endif
+
 #endif
 
 /*
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 4b65e82..f003692 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -577,7 +577,7 @@
             do {
                 CompilerWorkOrder work = workDequeue();
                 dvmUnlockMutex(&gDvmJit.compilerLock);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
                 u8 startTime = dvmGetRelativeTimeUsec();
 #endif
                 /*
@@ -622,7 +622,7 @@
                     }
                 }
                 free(work.info);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
                 gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime;
 #endif
                 dvmLockMutex(&gDvmJit.compilerLock);
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
index cbafb79..cb5a702 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.c
@@ -203,11 +203,11 @@
     if (gDvmJit.methodStatsTable) {
         dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
                        &totalMethodStats);
+        LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
+             totalMethodStats.compiledDalvikSize,
+             totalMethodStats.dalvikSize,
+             totalMethodStats.nativeSize);
     }
-    LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
-         totalMethodStats.compiledDalvikSize,
-         totalMethodStats.dalvikSize,
-         totalMethodStats.nativeSize);
 }
 
 /*
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 419cc09..499e287 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -877,6 +877,13 @@
  */
 #define PADDING_MOV_R5_R5               0x1C2D
 
+/* Track the number of times that the code cache is patched */
+#if defined(WITH_JIT_TUNING)
+#define UPDATE_CODE_CACHE_PATCHES()    (gDvmJit.codeCachePatches++)
+#else
+#define UPDATE_CODE_CACHE_PATCHES()
+#endif
+
 /* Write the numbers in the literal pool to the codegen stream */
 static void installDataContent(CompilationUnit *cUnit)
 {
@@ -1311,6 +1318,7 @@
     /* Flush dcache and invalidate the icache to maintain coherence */
     cacheflush((long)cUnit->baseAddr,
                (long)((char *) cUnit->baseAddr + offset), 0);
+    UPDATE_CODE_CACHE_PATCHES();
 
     /* Record code entry point and instruction set */
     info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
@@ -1393,6 +1401,7 @@
 
         *branchAddr = newInst;
         cacheflush((long)branchAddr, (long)branchAddr + 4, 0);
+        UPDATE_CODE_CACHE_PATCHES();
         gDvmJit.hasNewChain = true;
     }
 
@@ -1428,6 +1437,7 @@
         MEM_BARRIER();
         cellAddr->clazz = newContent->clazz;
         cacheflush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0);
+        UPDATE_CODE_CACHE_PATCHES();
 #if defined(WITH_JIT_TUNING)
         gDvmJit.icPatchFast++;
 #endif
@@ -1490,6 +1500,7 @@
     if (dvmIsNativeMethod(method)) {
         cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
         cacheflush((long) cell, (long) (cell+1), 0);
+        UPDATE_CODE_CACHE_PATCHES();
         COMPILER_TRACE_CHAINING(
             LOGD("Jit Runtime: predicted chain %p to native method %s ignored",
                  cell, method->name));
@@ -1508,6 +1519,7 @@
          */
         cell->counter = PREDICTED_CHAIN_COUNTER_DELAY;
         cacheflush((long) cell, (long) (cell+1), 0);
+        UPDATE_CODE_CACHE_PATCHES();
         COMPILER_TRACE_CHAINING(
             LOGD("Jit Runtime: predicted chain %p to method %s%s delayed",
                  cell, method->clazz->descriptor, method->name));
@@ -1598,6 +1610,7 @@
 
     /* Then synchronize the I/D cache */
     cacheflush((long) minAddr, (long) (maxAddr+1), 0);
+    UPDATE_CODE_CACHE_PATCHES();
 
     gDvmJit.compilerICPatchIndex = 0;
     dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
@@ -1734,6 +1747,7 @@
             }
         }
         cacheflush((long)lowAddress, (long)highAddress, 0);
+        UPDATE_CODE_CACHE_PATCHES();
         dvmUnlockMutex(&gDvmJit.tableLock);
         gDvmJit.translationChains = 0;
     }
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 59df480..2cd16a1 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -872,7 +872,7 @@
 static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
 {
     genDispatchToHandler(cUnit, TEMPLATE_RETURN);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     gDvmJit.returnOp++;
 #endif
     int dPC = (int) (cUnit->method->insns + mir->offset);
@@ -1042,12 +1042,12 @@
      */
     if (dvmIsNativeMethod(calleeMethod)) {
         genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
         gDvmJit.invokeNative++;
 #endif
     } else {
         genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
         gDvmJit.invokeMonomorphic++;
 #endif
         /* Branch to the chaining cell */
@@ -1169,7 +1169,7 @@
      * r4PC = callsiteDPC,
      */
     genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     gDvmJit.invokePolymorphic++;
 #endif
     /* Handle exceptions using the interpreter */
@@ -2978,7 +2978,7 @@
              * r4PC = callsiteDPC,
              */
             genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
             gDvmJit.invokePolymorphic++;
 #endif
             /* Handle exceptions using the interpreter */
@@ -4027,7 +4027,7 @@
                      jitToInterpEntries.dvmJitToInterpNoChain), r2);
         opRegReg(cUnit, kOpAdd, r1, r1);
         opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
         loadConstant(cUnit, r0, kSwitchOverflow);
 #endif
         opReg(cUnit, kOpBlx, r2);
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
index 6f655bf..d452a7f 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -64,7 +64,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
index 6da78c9..5be6978 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -48,7 +48,7 @@
     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
 
     @ Start executing the callee
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kInlineCacheMiss
 #endif
     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
index 9ee49a8..a7cb781 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
@@ -27,6 +27,12 @@
     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
     ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
     cmp     r3, r8          @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+    ldr     r7, .LdvmICHitCount
+    ldreq   r10, [r7, #0]
+    add     r10, r10, #1
+    streq   r10, [r7, #0]
+#endif
     beq     .LinvokeChain   @ predicted chain is valid
     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
     sub     r1, r9, #1      @ count--
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S
index b1ab44e..8d01131 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER.S
@@ -19,7 +19,7 @@
     ldr     r2, .LdvmJitToInterpNoChain
     str     r0, [rGLUE, #offGlue_pJitProfTable]
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     bx      r2
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S
index 6acf992..5cf26e7 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_MONITOR_ENTER_DEBUG.S
@@ -26,7 +26,7 @@
     bx      r2
 1:
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     ldr     pc, .LdvmJitToInterpNoChain
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
index 502c493..70044c2 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -38,7 +38,7 @@
     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
     cmp     r9, #0                      @ chaining cell exists?
     blxne   r9                          @ jump to the chaining cell
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1                      @ callsite is interpreted
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index b93eee3..8e66ac6 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -50,7 +50,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -86,6 +86,10 @@
     .word   dvmMterpCommonExceptionThrown
 .LdvmLockObject:
     .word   dvmLockObject
+#if defined(WITH_JIT_TUNING)
+.LdvmICHitCount:
+    .word   gDvmICHitCount
+#endif
 #if defined(WITH_SELF_VERIFICATION)
 .LdvmSelfVerificationMemOpDecode:
     .word   dvmSelfVerificationMemOpDecode
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 60e33f1..b2a4998 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -212,7 +212,7 @@
     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
     cmp     r9, #0                      @ chaining cell exists?
     blxne   r9                          @ jump to the chaining cell
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1                      @ callsite is interpreted
@@ -278,7 +278,7 @@
     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
 
     @ Start executing the callee
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kInlineCacheMiss
 #endif
     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
@@ -370,6 +370,12 @@
     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
     ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
     cmp     r3, r8          @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+    ldr     r7, .LdvmICHitCount
+    ldreq   r10, [r7, #0]
+    add     r10, r10, #1
+    streq   r10, [r7, #0]
+#endif
     beq     .LinvokeChain   @ predicted chain is valid
     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
     sub     r1, r9, #1      @ count--
@@ -455,7 +461,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1393,7 +1399,7 @@
     ldr     r2, .LdvmJitToInterpNoChain
     str     r0, [rGLUE, #offGlue_pJitProfTable]
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     bx      r2
@@ -1432,7 +1438,7 @@
     bx      r2
 1:
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     ldr     pc, .LdvmJitToInterpNoChain
@@ -1491,7 +1497,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1527,6 +1533,10 @@
     .word   dvmMterpCommonExceptionThrown
 .LdvmLockObject:
     .word   dvmLockObject
+#if defined(WITH_JIT_TUNING)
+.LdvmICHitCount:
+    .word   gDvmICHitCount
+#endif
 #if defined(WITH_SELF_VERIFICATION)
 .LdvmSelfVerificationMemOpDecode:
     .word   dvmSelfVerificationMemOpDecode
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 1801e6a..cc7455f 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -212,7 +212,7 @@
     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
     cmp     r9, #0                      @ chaining cell exists?
     blxne   r9                          @ jump to the chaining cell
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1                      @ callsite is interpreted
@@ -278,7 +278,7 @@
     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
 
     @ Start executing the callee
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kInlineCacheMiss
 #endif
     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
@@ -370,6 +370,12 @@
     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
     ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
     cmp     r3, r8          @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+    ldr     r7, .LdvmICHitCount
+    ldreq   r10, [r7, #0]
+    add     r10, r10, #1
+    streq   r10, [r7, #0]
+#endif
     beq     .LinvokeChain   @ predicted chain is valid
     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
     sub     r1, r9, #1      @ count--
@@ -455,7 +461,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1121,7 +1127,7 @@
     ldr     r2, .LdvmJitToInterpNoChain
     str     r0, [rGLUE, #offGlue_pJitProfTable]
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     bx      r2
@@ -1160,7 +1166,7 @@
     bx      r2
 1:
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     ldr     pc, .LdvmJitToInterpNoChain
@@ -1219,7 +1225,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1255,6 +1261,10 @@
     .word   dvmMterpCommonExceptionThrown
 .LdvmLockObject:
     .word   dvmLockObject
+#if defined(WITH_JIT_TUNING)
+.LdvmICHitCount:
+    .word   gDvmICHitCount
+#endif
 #if defined(WITH_SELF_VERIFICATION)
 .LdvmSelfVerificationMemOpDecode:
     .word   dvmSelfVerificationMemOpDecode
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
index 85eb31e..5692b11 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
@@ -212,7 +212,7 @@
     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
     cmp     r9, #0                      @ chaining cell exists?
     blxne   r9                          @ jump to the chaining cell
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1                      @ callsite is interpreted
@@ -278,7 +278,7 @@
     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
 
     @ Start executing the callee
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kInlineCacheMiss
 #endif
     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
@@ -370,6 +370,12 @@
     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
     ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
     cmp     r3, r8          @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+    ldr     r7, .LdvmICHitCount
+    ldreq   r10, [r7, #0]
+    add     r10, r10, #1
+    streq   r10, [r7, #0]
+#endif
     beq     .LinvokeChain   @ predicted chain is valid
     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
     sub     r1, r9, #1      @ count--
@@ -455,7 +461,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1393,7 +1399,7 @@
     ldr     r2, .LdvmJitToInterpNoChain
     str     r0, [rGLUE, #offGlue_pJitProfTable]
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     bx      r2
@@ -1432,7 +1438,7 @@
     bx      r2
 1:
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     ldr     pc, .LdvmJitToInterpNoChain
@@ -1491,7 +1497,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1527,6 +1533,10 @@
     .word   dvmMterpCommonExceptionThrown
 .LdvmLockObject:
     .word   dvmLockObject
+#if defined(WITH_JIT_TUNING)
+.LdvmICHitCount:
+    .word   gDvmICHitCount
+#endif
 #if defined(WITH_SELF_VERIFICATION)
 .LdvmSelfVerificationMemOpDecode:
     .word   dvmSelfVerificationMemOpDecode
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 6755c20..b75471f 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -212,7 +212,7 @@
     str     r9, [r3, #offThread_inJitCodeCache] @ in code cache or not
     cmp     r9, #0                      @ chaining cell exists?
     blxne   r9                          @ jump to the chaining cell
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1                      @ callsite is interpreted
@@ -278,7 +278,7 @@
     str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
 
     @ Start executing the callee
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kInlineCacheMiss
 #endif
     mov     pc, r10                         @ dvmJitToInterpTraceSelectNoChain
@@ -370,6 +370,12 @@
     ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
     ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
     cmp     r3, r8          @ predicted class == actual class?
+#if defined(WITH_JIT_TUNING)
+    ldr     r7, .LdvmICHitCount
+    ldreq   r10, [r7, #0]
+    add     r10, r10, #1
+    streq   r10, [r7, #0]
+#endif
     beq     .LinvokeChain   @ predicted chain is valid
     ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
     sub     r1, r9, #1      @ count--
@@ -455,7 +461,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1393,7 +1399,7 @@
     ldr     r2, .LdvmJitToInterpNoChain
     str     r0, [rGLUE, #offGlue_pJitProfTable]
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     bx      r2
@@ -1432,7 +1438,7 @@
     bx      r2
 1:
     @ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kHeavyweightMonitor
 #endif
     ldr     pc, .LdvmJitToInterpNoChain
@@ -1491,7 +1497,7 @@
     @ continue executing the next instruction through the interpreter
     ldr     r1, .LdvmJitToInterpTraceSelectNoChain @ defined in footer.S
     add     rPC, r0, #6                 @ reconstruct new rPC (advance 6 bytes)
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     mov     r0, #kCallsiteInterpreted
 #endif
     mov     pc, r1
@@ -1527,6 +1533,10 @@
     .word   dvmMterpCommonExceptionThrown
 .LdvmLockObject:
     .word   dvmLockObject
+#if defined(WITH_JIT_TUNING)
+.LdvmICHitCount:
+    .word   gDvmICHitCount
+#endif
 #if defined(WITH_SELF_VERIFICATION)
 .LdvmSelfVerificationMemOpDecode:
     .word   dvmSelfVerificationMemOpDecode
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index f475773..e3096df 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -404,7 +404,7 @@
     gDvmJit.pProfTable = NULL;
 }
 
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
 /* Convenience function to increment counter from assembly code */
 void dvmBumpNoChain(int from)
 {
@@ -452,11 +452,15 @@
              hit, not_hit + hit, chains, gDvmJit.threshold,
              gDvmJit.blockingMode ? "Blocking" : "Non-blocking");
 
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
+        LOGD("JIT: Code cache patches: %d", gDvmJit.codeCachePatches);
+
         LOGD("JIT: Lookups: %d hits, %d misses; %d normal, %d punt",
              gDvmJit.addrLookupsFound, gDvmJit.addrLookupsNotFound,
              gDvmJit.normalExit, gDvmJit.puntExit);
 
+        LOGD("JIT: ICHits: %d", gDvmICHitCount);
+
         LOGD("JIT: noChainExit: %d IC miss, %d interp callsite, "
              "%d switch overflow",
              gDvmJit.noChainExit[kInlineCacheMiss],
@@ -843,7 +847,7 @@
                                (gDvmJit.pProfTable == NULL);
 
         if (npc == dPC) {
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
             gDvmJit.addrLookupsFound++;
 #endif
             return hideTranslation ?
@@ -853,7 +857,7 @@
             while (gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) {
                 idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
                 if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
                     gDvmJit.addrLookupsFound++;
 #endif
                     return hideTranslation ?
@@ -862,7 +866,7 @@
             }
         }
     }
-#if defined(JIT_STATS)
+#if defined(WITH_JIT_TUNING)
     gDvmJit.addrLookupsNotFound++;
 #endif
     return NULL;
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 4e935cd..aba3443 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -83,7 +83,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -124,7 +124,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -190,7 +190,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -212,7 +212,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 2888ec5..5262f44 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -9805,7 +9805,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -9846,7 +9846,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -9912,7 +9912,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -9934,7 +9934,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 773d0d4..4d70bbb 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -9325,7 +9325,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -9366,7 +9366,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -9432,7 +9432,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -9454,7 +9454,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index f79049f..f5bca57 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9801,7 +9801,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -9842,7 +9842,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -9908,7 +9908,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -9930,7 +9930,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index efad56a..6bf9928 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -9251,7 +9251,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -9292,7 +9292,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -9358,7 +9358,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -9380,7 +9380,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 657f5f0..8a5d41a 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -9251,7 +9251,7 @@
 dvmJitToInterpPunt:
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     mov    rPC, r0
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     mov    r0,lr
     bl     dvmBumpPunt;
 #endif
@@ -9292,7 +9292,7 @@
  */
     .global dvmJitToInterpTraceSelectNoChain
 dvmJitToInterpTraceSelectNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
@@ -9358,7 +9358,7 @@
     ldr    rPC,[lr, #-1]           @ get our target PC
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
     add    rINST,lr,#-5            @ save start of chain branch
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNormal
 #endif
     mov    r0,rPC
@@ -9380,7 +9380,7 @@
  */
     .global dvmJitToInterpNoChain
 dvmJitToInterpNoChain:
-#ifdef JIT_STATS
+#if defined(WITH_JIT_TUNING)
     bl     dvmBumpNoChain
 #endif
     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self