New stuff includes breakdown of callsite types (ie monomorphic vs polymorphic
vs monoporphic resolved to native), total time spent in JIT'ing, and average
JIT time per compilation.
Example output:
D/dalvikvm( 840): 4042 compilations using 1976 + 329108 bytes
D/dalvikvm( 840): Compiler arena uses 10 blocks (8100 bytes each)
D/dalvikvm( 840): Compiler work queue length is 0/36
D/dalvikvm( 840): size if 8192, entries used is 4137
D/dalvikvm( 840): JIT: 4137 traces, 8192 slots, 1099 chains, 40 thresh, Non-blocking
D/dalvikvm( 840): JIT: Lookups:
1128780 hits, 168564 misses; 179520 normal, 6 punt
D/dalvikvm( 840): JIT: noChainExit: 528464 IC miss, 194708 interp callsite, 0 switch overflow
D/dalvikvm( 840): JIT: Invoke: 507 mono, 988 poly, 72 native, 1038 return
D/dalvikvm( 840): JIT: Total compilation time: 2342 ms
D/dalvikvm( 840): JIT: Avg unit compilation time: 579 us
D/dalvikvm( 840): JIT: 3357 Translation chains, 97 interp stubs
D/dalvikvm( 840): dalvik.vm.jit.op = 0-2,4-5,7-8,a-c,e-16,19-1a,1c-23,26,28-29,2b-2f,31-3d,44-4b,4d-51,60,62-63,68-69,70-72,76-78,7b,81-82,84,87,89,8d-93,95-98,a1,a3,a6,a8-a9,b0-b3,b5-b6,bb-bf,c6-c8,d0,d2-d6,d8,da-e2,ee-f0,f2-fb,
D/dalvikvm( 840): Code size stats: 50666/105126 (compiled/total Dalvik), 329108 (native)
# Enable assertions and JIT-tuning
LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT \
- -DWITH_JIT_TUNING -DEXIT_STATS
+ -DWITH_JIT_TUNING -DJIT_STATS
LOCAL_MODULE := libdvm_assert
include $(BUILD_SHARED_LIBRARY)
int normalExit;
int puntExit;
int translationChains;
- int invokeChain;
- int invokePredictedChain;
+ int invokeMonomorphic;
+ int invokePolymorphic;
int invokeNative;
int returnOp;
+ u8 jitTime;
/* Compiled code cache */
void* codeCache;
do {
CompilerWorkOrder work = workDequeue();
dvmUnlockMutex(&gDvmJit.compilerLock);
+#if defined(JIT_STATS)
+ u8 startTime = dvmGetRelativeTimeUsec();
+#endif
/*
* Check whether there is a suspend request on me. This
* is necessary to allow a clean shutdown.
}
}
free(work.info);
+#if defined(JIT_STATS)
+ gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime;
+#endif
dvmLockMutex(&gDvmJit.compilerLock);
} while (workQueueLength() != 0);
}
static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
{
genDispatchToHandler(cUnit, TEMPLATE_RETURN);
-#if defined(INVOKE_STATS)
+#if defined(JIT_STATS)
gDvmJit.returnOp++;
#endif
int dPC = (int) (cUnit->method->insns + mir->offset);
*/
if (dvmIsNativeMethod(calleeMethod)) {
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
-#if defined(INVOKE_STATS)
+#if defined(JIT_STATS)
gDvmJit.invokeNative++;
#endif
} else {
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
-#if defined(INVOKE_STATS)
- gDvmJit.invokeChain++;
+#if defined(JIT_STATS)
+ gDvmJit.invokeMonomorphic++;
#endif
/* Branch to the chaining cell */
genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
* r4PC = callsiteDPC,
*/
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
-#if defined(INVOKE_STATS)
- gDvmJit.invokePredictedChain++;
+#if defined(JIT_STATS)
+ gDvmJit.invokePolymorphic++;
#endif
/* Handle exceptions using the interpreter */
genTrap(cUnit, mir->offset, pcrLabel);
* r4PC = callsiteDPC,
*/
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
-#if defined(INVOKE_STATS)
- gDvmJit.invokePredictedChain++;
+#if defined(JIT_STATS)
+ gDvmJit.invokePolymorphic++;
#endif
/* Handle exceptions using the interpreter */
genTrap(cUnit, mir->offset, pcrLabel);
jitToInterpEntries.dvmJitToInterpNoChain), r2);
opRegReg(cUnit, kOpAdd, r1, r1);
opRegRegReg(cUnit, kOpAdd, r4PC, r0, r1);
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
loadConstant(cUnit, r0, kSwitchOverflow);
#endif
opReg(cUnit, kOpBlx, r2);
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
@ Start executing the callee
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kInlineCacheMiss
#endif
mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
ldr r2, .LdvmJitToInterpNoChain
str r0, [rGLUE, #offGlue_pJitProfTable]
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
bx r2
bx r2
1:
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
ldr pc, .LdvmJitToInterpNoChain
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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1 @ callsite is interpreted
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1 @ callsite is interpreted
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
@ Start executing the callee
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kInlineCacheMiss
#endif
mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
ldr r2, .LdvmJitToInterpNoChain
str r0, [rGLUE, #offGlue_pJitProfTable]
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
bx r2
bx r2
1:
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
ldr pc, .LdvmJitToInterpNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1 @ callsite is interpreted
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
@ Start executing the callee
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kInlineCacheMiss
#endif
mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
ldr r2, .LdvmJitToInterpNoChain
str r0, [rGLUE, #offGlue_pJitProfTable]
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
bx r2
bx r2
1:
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
ldr pc, .LdvmJitToInterpNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1 @ callsite is interpreted
str rFP, [r2, #offThread_curFrame] @ self->curFrame = newFp
@ Start executing the callee
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kInlineCacheMiss
#endif
mov pc, r10 @ dvmJitToInterpTraceSelectNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
ldr r2, .LdvmJitToInterpNoChain
str r0, [rGLUE, #offGlue_pJitProfTable]
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
bx r2
bx r2
1:
@ Bail to interpreter - no chain [note - r4 still contains rPC]
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kHeavyweightMonitor
#endif
ldr pc, .LdvmJitToInterpNoChain
@ 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(EXIT_STATS)
+#if defined(JIT_STATS)
mov r0, #kCallsiteInterpreted
#endif
mov pc, r1
gDvmJit.pProfTable = NULL;
}
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
/* Convenience function to increment counter from assembly code */
void dvmBumpNoChain(int from)
{
if (gDvmJit.pJitEntryTable[i].u.info.chain != gDvmJit.jitTableSize)
chains++;
}
+ LOGD("size if %d, entries used is %d",
+ gDvmJit.jitTableSize, gDvmJit.jitTableEntriesUsed);
LOGD(
- "JIT: %d traces, %d slots, %d chains, %d maxQ, %d thresh, %s",
- hit, not_hit + hit, chains, gDvmJit.compilerMaxQueued,
- gDvmJit.threshold, gDvmJit.blockingMode ? "Blocking" : "Non-blocking");
-#if defined(EXIT_STATS)
+ "JIT: %d traces, %d slots, %d chains, %d thresh, %s",
+ hit, not_hit + hit, chains, gDvmJit.threshold,
+ gDvmJit.blockingMode ? "Blocking" : "Non-blocking");
+
+#if defined(JIT_STATS)
LOGD(
"JIT: Lookups: %d hits, %d misses; %d normal, %d punt",
gDvmJit.addrLookupsFound, gDvmJit.addrLookupsNotFound,
gDvmJit.noChainExit[kInlineCacheMiss],
gDvmJit.noChainExit[kCallsiteInterpreted],
gDvmJit.noChainExit[kSwitchOverflow]);
+
+ LOGD("JIT: Invoke: %d mono, %d poly, %d native, %d return",
+ gDvmJit.invokeMonomorphic, gDvmJit.invokePolymorphic,
+ gDvmJit.invokeNative, gDvmJit.returnOp);
+ LOGD("JIT: Total compilation time: %llu ms", gDvmJit.jitTime / 1000);
+ LOGD("JIT: Avg unit compilation time: %llu us",
+ gDvmJit.jitTime / gDvmJit.numCompilations);
#endif
+
LOGD("JIT: %d Translation chains, %d interp stubs",
gDvmJit.translationChains, stubs);
-#if defined(INVOKE_STATS)
- LOGD("JIT: Invoke: %d chainable, %d pred. chain, %d native, "
- "%d return",
- gDvmJit.invokeChain, gDvmJit.invokePredictedChain,
- gDvmJit.invokeNative, gDvmJit.returnOp);
-#endif
if (gDvmJit.profile) {
dvmCompilerSortAndPrintTraceProfiles();
}
(gDvmJit.pProfTable == NULL);
if (npc == dPC) {
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
gDvmJit.addrLookupsFound++;
#endif
return hideTranslation ?
while (gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) {
idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
gDvmJit.addrLookupsFound++;
#endif
return hideTranslation ?
}
}
}
-#if defined(EXIT_STATS)
+#if defined(JIT_STATS)
gDvmJit.addrLookupsNotFound++;
#endif
return NULL;
if (res || (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater)
|| gDvm.debuggerActive || self->suspendCount
#if defined(WITH_PROFILER)
- || gDvm.activeProfilers
+ || gDvm.activeProfilers
#endif
- ) {
+ ) {
if (interpState->jitState != kJitOff) {
interpState->jitState = kJitNormal;
}
dvmJitToInterpPunt:
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
mov rPC, r0
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
mov r0,lr
bl dvmBumpPunt;
#endif
*/
.global dvmJitToInterpTraceSelectNoChain
dvmJitToInterpTraceSelectNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
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 EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNormal
#endif
mov r0,rPC
*/
.global dvmJitToInterpNoChain
dvmJitToInterpNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
dvmJitToInterpPunt:
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
mov rPC, r0
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
mov r0,lr
bl dvmBumpPunt;
#endif
*/
.global dvmJitToInterpTraceSelectNoChain
dvmJitToInterpTraceSelectNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
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 EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNormal
#endif
mov r0,rPC
*/
.global dvmJitToInterpNoChain
dvmJitToInterpNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
dvmJitToInterpPunt:
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
mov rPC, r0
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
mov r0,lr
bl dvmBumpPunt;
#endif
*/
.global dvmJitToInterpTraceSelectNoChain
dvmJitToInterpTraceSelectNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
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 EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNormal
#endif
mov r0,rPC
*/
.global dvmJitToInterpNoChain
dvmJitToInterpNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
dvmJitToInterpPunt:
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
mov rPC, r0
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
mov r0,lr
bl dvmBumpPunt;
#endif
*/
.global dvmJitToInterpTraceSelectNoChain
dvmJitToInterpTraceSelectNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
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 EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNormal
#endif
mov r0,rPC
*/
.global dvmJitToInterpNoChain
dvmJitToInterpNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
dvmJitToInterpPunt:
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
mov rPC, r0
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
mov r0,lr
bl dvmBumpPunt;
#endif
*/
.global dvmJitToInterpTraceSelectNoChain
dvmJitToInterpTraceSelectNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
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 EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNormal
#endif
mov r0,rPC
*/
.global dvmJitToInterpNoChain
dvmJitToInterpNoChain:
-#ifdef EXIT_STATS
+#ifdef JIT_STATS
bl dvmBumpNoChain
#endif
ldr r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self