OSDN Git Service

New threshold mechanism for trace selections. Intended to reduce number of junk...
authorBill Buzbee <buzbee@google.com>
Fri, 19 Jun 2009 23:02:27 +0000 (16:02 -0700)
committerBill Buzbee <buzbee@google.com>
Mon, 22 Jun 2009 20:49:58 +0000 (13:49 -0700)
vm/interp/Interp.c
vm/interp/InterpDefs.h
vm/interp/Jit.c
vm/interp/Jit.h
vm/mterp/armv5te/footer.S
vm/mterp/out/InterpAsm-armv4t.S
vm/mterp/out/InterpAsm-armv5te-vfp.S
vm/mterp/out/InterpAsm-armv5te.S

index db86e78..fbf0f09 100644 (file)
@@ -838,6 +838,13 @@ void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
 
     /* Setup the Jit-to-interpreter entry points */
     interpState.jitToInterpEntries = jitToInterpEntries;
+
+    /*
+     * Initialize the threshold filter [don't bother to zero out the
+     * actual table.  We're looking for matches, and an occasional
+     * false positive is acceptible.
+     */
+    interpState.lastThreshFilter = 0;
 #endif
 
     /*
index cbb78f0..23f1fe8 100644 (file)
@@ -47,7 +47,7 @@ typedef enum InterpEntry {
  *    for handling 1-to-many mappings like virtual method call and
  *    packed switch.
  * 3) dvmJitToInterpPunt: use the fast interpreter to execute the next
- *    instruction(s) and stay there as long as it is appropriate to return 
+ *    instruction(s) and stay there as long as it is appropriate to return
  *    to the compiled land. This is used when the jit'ed code is about to
  *    throw an exception.
  * 4) dvmJitToInterpSingleStep: use the portable interpreter to execute the
@@ -70,6 +70,8 @@ struct JitToInterpEntries {
     void *dvmJitToInterpSingleStep;
     void *dvmJitToTraceSelect;
 };
+
+#define JIT_TRACE_THRESH_FILTER_SIZE  16
 #endif
 
 /*
@@ -143,6 +145,8 @@ typedef struct InterpState {
     const u2* currTraceHead;        // Start of the trace we're building
     const u2* currRunHead;          // Start of run we're building
     int currRunLen;           // Length of run in 16-bit words
+    int lastThreshFilter;
+    u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
     JitTraceRun trace[MAX_JIT_RUN_LEN];
 #endif
 
index c64d4d5..7d922bb 100644 (file)
 #include "compiler/CompilerIR.h"
 #include <errno.h>
 
-/*
- * Reset profile counts.  Note that we could easily lose
- * one or more of these write because of threading.  Because these
- * counts are considered hints, absolute correctness is not a
- * problem and the cost of synchronizing would be prohibitive.
- * NOTE: Experimental - 5/21/09.  Keep rough track of the last
- * time the counts were reset to allow trace builder to ignore
- * stale thresholds.  This is just a hint, and the only penalty
- * for getting it wrong is a slight performance hit (far less than
- * the cost of synchronization).
- */
-static u8 lastProfileResetTimeUsec;
-static void resetProfileCounts() {
-    int i;
-    unsigned char *pJitProfTable = gDvmJit.pProfTable;
-    lastProfileResetTimeUsec = dvmGetRelativeTimeUsec();
-    if (pJitProfTable != NULL) {
-        for (i=0; i < JIT_PROF_SIZE; i++) {
-           pJitProfTable[i] = gDvmJit.threshold;
-        }
-    }
-}
-
 int dvmJitStartup(void)
 {
     unsigned int i;
@@ -98,7 +75,6 @@ int dvmJitStartup(void)
         }
         /* Is chain field wide enough for termination pattern? */
         assert(pJitTable[0].chain == gDvm.maxJitTableEntries);
-        resetProfileCounts();
 
 done:
         gDvmJit.pJitEntryTable = pJitTable;
@@ -151,7 +127,7 @@ void dvmBumpPunt(int from)
 #endif
 
 /* Dumps profile info for a single trace */
-void dvmCompilerDumpTraceProfile(struct JitEntry *p)
+int dvmCompilerDumpTraceProfile(struct JitEntry *p)
 {
     ChainCellCounts* pCellCounts;
     char* traceBase;
@@ -170,7 +146,7 @@ void dvmCompilerDumpTraceProfile(struct JitEntry *p)
 
     if (p->codeAddress == NULL) {
         LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
-        return;
+        return 0;
     }
 
     pExecutionCount = (u4*) (traceBase);
@@ -182,6 +158,7 @@ void dvmCompilerDumpTraceProfile(struct JitEntry *p)
           *pExecutionCount, method->clazz->descriptor, method->name,
           desc->trace[0].frag.startOffset,
           desc->trace[0].frag.numInsts);
+    return *pExecutionCount;
 }
 
 /* Dumps debugging & tuning stats to the log */
@@ -218,11 +195,17 @@ void dvmJitStats()
           gDvmJit.invokeNoOpt, gDvmJit.invokeChain, gDvmJit.returnOp);
 #endif
        if (gDvmJit.profile) {
+           int numTraces = 0;
+           long counts = 0;
            for (i=0; i < (int) gDvmJit.jitTableSize; i++) {
               if (gDvmJit.pJitEntryTable[i].dPC != 0) {
-                  dvmCompilerDumpTraceProfile( &gDvmJit.pJitEntryTable[i] );
+                  counts += dvmCompilerDumpTraceProfile( &gDvmJit.pJitEntryTable[i] );
+                  numTraces++;
               }
            }
+        if (numTraces == 0)
+              numTraces = 1;
+        LOGD("JIT: Average execution count -> %d",(int)(counts / numTraces));
         }
     }
 }
@@ -509,14 +492,29 @@ void dvmJitSetCodeAddr(const u2* dPC, void *nPC) {
 #define PROFILE_STALENESS_THRESHOLD 100000LL
 bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState)
 {
-    bool res = false;    /* Assume success */
+    bool res = false;         /* Assume success */
+    int i;
     if (gDvmJit.pJitEntryTable != NULL) {
-        u8 delta = dvmGetRelativeTimeUsec() - lastProfileResetTimeUsec;
+        /* Two-level filtering scheme */
+        for (i=0; i< JIT_TRACE_THRESH_FILTER_SIZE; i++) {
+            if (interpState->pc == interpState->threshFilter[i]) {
+                break;
+            }
+        }
+        if (i == JIT_TRACE_THRESH_FILTER_SIZE) {
+            /*
+             * Use random replacement policy - otherwise we could miss a large
+             * loop that contains more traces than the size of our filter array.
+             */
+            i = rand() % JIT_TRACE_THRESH_FILTER_SIZE;
+            interpState->threshFilter[i] = interpState->pc;
+            res = true;
+        }
         /*
          * If the compiler is backlogged, or if a debugger or profiler is
          * active, cancel any JIT actions
          */
-        if ( (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater) ||
+        if ( res || (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater) ||
               gDvm.debuggerActive || self->suspendCount
 #if defined(WITH_PROFILER)
                  || gDvm.activeProfilers
@@ -525,9 +523,6 @@ bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState)
             if (interpState->jitState != kJitOff) {
                 interpState->jitState = kJitNormal;
             }
-        } else if (delta > PROFILE_STALENESS_THRESHOLD) {
-            resetProfileCounts();
-            res = true;   /* Stale profile - abort */
         } else if (interpState->jitState == kJitTSelectRequest) {
             u4 chainEndMarker = gDvmJit.jitTableSize;
             u4 idx = dvmJitHash(interpState->pc);
index 560a4db..5d748d5 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "InterpDefs.h"
 
-#define JIT_PROF_SIZE 4096
+#define JIT_PROF_SIZE 512
 
 #define JIT_MAX_TRACE_LEN 100
 
index 129760d..004ee13 100644 (file)
@@ -154,11 +154,11 @@ common_testUpdateProfile:
 
 common_updateProfile:
     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
-    lsl     r3,r3,#20          @ shift out excess 4095
-    ldrb    r1,[r0,r3,lsr #20] @ get counter
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
     GET_INST_OPCODE(ip)
     subs    r1,r1,#1           @ decrement counter
-    strb    r1,[r0,r3,lsr #20] @ and store it
+    strb    r1,[r0,r3,lsr #23] @ and store it
     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
 
 /*
@@ -168,7 +168,7 @@ common_updateProfile:
  * jump to it now).
  */
     mov     r1,#255
-    strb    r1,[r0,r3,lsr #20] @ reset counter
+    strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
index 3b3d0a9..b0aa69b 100644 (file)
@@ -9626,11 +9626,11 @@ common_testUpdateProfile:
 
 common_updateProfile:
     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
-    lsl     r3,r3,#20          @ shift out excess 4095
-    ldrb    r1,[r0,r3,lsr #20] @ get counter
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
     GET_INST_OPCODE(ip)
     subs    r1,r1,#1           @ decrement counter
-    strb    r1,[r0,r3,lsr #20] @ and store it
+    strb    r1,[r0,r3,lsr #23] @ and store it
     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
 
 /*
@@ -9640,7 +9640,7 @@ common_updateProfile:
  * jump to it now).
  */
     mov     r1,#255
-    strb    r1,[r0,r3,lsr #20] @ reset counter
+    strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
index 860c3e7..5a8ae4c 100644 (file)
@@ -9144,11 +9144,11 @@ common_testUpdateProfile:
 
 common_updateProfile:
     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
-    lsl     r3,r3,#20          @ shift out excess 4095
-    ldrb    r1,[r0,r3,lsr #20] @ get counter
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
     GET_INST_OPCODE(ip)
     subs    r1,r1,#1           @ decrement counter
-    strb    r1,[r0,r3,lsr #20] @ and store it
+    strb    r1,[r0,r3,lsr #23] @ and store it
     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
 
 /*
@@ -9158,7 +9158,7 @@ common_updateProfile:
  * jump to it now).
  */
     mov     r1,#255
-    strb    r1,[r0,r3,lsr #20] @ reset counter
+    strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
index 5ba2523..3f2069c 100644 (file)
@@ -9620,11 +9620,11 @@ common_testUpdateProfile:
 
 common_updateProfile:
     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
-    lsl     r3,r3,#20          @ shift out excess 4095
-    ldrb    r1,[r0,r3,lsr #20] @ get counter
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
     GET_INST_OPCODE(ip)
     subs    r1,r1,#1           @ decrement counter
-    strb    r1,[r0,r3,lsr #20] @ and store it
+    strb    r1,[r0,r3,lsr #23] @ and store it
     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
 
 /*
@@ -9634,7 +9634,7 @@ common_updateProfile:
  * jump to it now).
  */
     mov     r1,#255
-    strb    r1,[r0,r3,lsr #20] @ reset counter
+    strb    r1,[r0,r3,lsr #23] @ reset counter
     EXPORT_PC()
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)