New threshold mechanism for trace selections. Intended to reduce number of junk traces.
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index c64d4d5..7d922bb 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -33,29 +33,6 @@
#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 @@
}
/* Is chain field wide enough for termination pattern? */
assert(pJitTable[0].chain == gDvm.maxJitTableEntries);
- resetProfileCounts();
done:
gDvmJit.pJitEntryTable = pJitTable;
@@ -151,7 +127,7 @@
#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 @@
if (p->codeAddress == NULL) {
LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
- return;
+ return 0;
}
pExecutionCount = (u4*) (traceBase);
@@ -182,6 +158,7 @@
*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 @@
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 @@
#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 @@
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);