Jit: MethodTrace + Jit fix
Add checks for debug & trace mode to avoid re-entering Jit'd code.
This is the conversative solution - we'll eventually want the Jit
to integrate support for tracing and debug into Jit'd code.
diff --git a/vm/Debugger.c b/vm/Debugger.c
index be6fa66..2f57046 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.c
@@ -418,6 +418,9 @@
LOGI("Debugger is active\n");
dvmInitBreakpoints();
gDvm.debuggerActive = true;
+#if defined(WITH_JIT)
+ dvmCompilerStateRefresh();
+#endif
}
/*
@@ -445,6 +448,9 @@
dvmHashTableClear(gDvm.dbgRegistry);
dvmHashTableUnlock(gDvm.dbgRegistry);
+#if defined(WITH_JIT)
+ dvmCompilerStateRefresh();
+#endif
}
/*
@@ -3045,4 +3051,3 @@
dvmJdwpDdmSendChunkV(gDvm.jdwpState, type, iov, iovcnt);
}
-
diff --git a/vm/Globals.h b/vm/Globals.h
index bac28f6..6d9455e 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -685,6 +685,9 @@
/* Array of profile threshold counters */
unsigned char *pProfTable;
+ /* Copy of pProfTable used for temporarily disabling the Jit */
+ unsigned char *pProfTableCopy;
+
/* Size of JIT hash table in entries. Must be a power of 2 */
unsigned int jitTableSize;
diff --git a/vm/Profile.c b/vm/Profile.c
index dcfad71..b079988 100644
--- a/vm/Profile.c
+++ b/vm/Profile.c
@@ -230,6 +230,9 @@
} while (!ATOMIC_CMP_SWAP(&gDvm.activeProfilers, oldValue, newValue));
LOGD("+++ active profiler count now %d\n", newValue);
+#if defined(WITH_JIT)
+ dvmCompilerStateRefresh();
+#endif
}
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 39b42cd..dfcd88f 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -344,6 +344,7 @@
gDvmJit.compilerHighWater =
COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
gDvmJit.pProfTable = pJitProfTable;
+ gDvmJit.pProfTableCopy = pJitProfTable;
dvmUnlockMutex(&gDvmJit.tableLock);
/* Signal running threads to refresh their cached pJitTable pointers */
@@ -511,3 +512,23 @@
LOGD("Compiler thread has shut down\n");
}
}
+
+
+void dvmCompilerStateRefresh()
+{
+ bool jitActive;
+ bool jitActivate;
+
+ dvmLockMutex(&gDvmJit.tableLock);
+ jitActive = gDvmJit.pProfTable != NULL;
+ jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0));
+
+ if (jitActivate && !jitActive) {
+ gDvmJit.pProfTable = gDvmJit.pProfTableCopy;
+ dvmUnlockMutex(&gDvmJit.tableLock);
+ } else if (!jitActivate && jitActive) {
+ gDvmJit.pProfTable = NULL;
+ dvmUnlockMutex(&gDvmJit.tableLock);
+ dvmJitUnchainAll();
+ }
+}
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 71eed5d..6b4d414 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -165,6 +165,7 @@
struct SSARepresentation *ssaRep);
void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
void (*func)(struct CompilationUnit *, struct BasicBlock *));
+void dvmCompilerStateRefresh(void);
JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc);
#endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 6a59c7e..998c955 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1328,7 +1328,7 @@
u4 newInst;
bool thumbTarget;
- if (gDvm.sumThreadSuspendCount == 0) {
+ if ((gDvmJit.pProfTable != NULL) && gDvm.sumThreadSuspendCount == 0) {
assert((branchOffset >= -(1<<22)) && (branchOffset <= ((1<<22)-2)));
gDvmJit.translationChains++;
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index 34a7736..6adbf3d 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -776,6 +776,7 @@
interpState->entryPoint = kInterpEntryResume;
switchInterp = !debugOrProfile;
break;
+ case kJitTSelectRequest:
case kJitTSelectAbort:
#if defined(SHOW_TRACE)
LOGD("TraceGen: trace abort");
@@ -833,7 +834,8 @@
void* dvmJitGetCodeAddr(const u2* dPC)
{
int idx = dvmJitHash(dPC);
- const u2* npc = gDvmJit.pJitEntryTable[idx].dPC;
+ const u2* npc = (gDvmJit.pProfTable == NULL) ? NULL :
+ gDvmJit.pJitEntryTable[idx].dPC;
if (npc != NULL) {
if (npc == dPC) {
@@ -1130,5 +1132,4 @@
return (s8)f;
}
-
#endif /* WITH_JIT */
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 5b984e3..5abdff5 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -1477,25 +1477,21 @@
interpState->pc,
interpState->method->name);
#endif
-
#if INTERP_TYPE == INTERP_DBG
- /* Check to see if we've got a trace selection request. If we do,
- * but something is amiss, revert to the fast interpreter.
- */
-#if !defined(WITH_SELF_VERIFICATION)
- if (dvmJitCheckTraceRequest(self,interpState)) {
+ /* Check to see if we've got a trace selection request. */
+ if (
+#if defined(WITH_SELF_VERIFICATION)
+ (interpState->jitState != kJitSelfVerification) &&
+#endif
+ !gDvm.debuggerActive &&
+#if defined(WITH_PROFILER)
+ (gDvm.activeProfilers == 0) &&
+#endif
+ dvmJitCheckTraceRequest(self, interpState)) {
interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
+ //LOGD("Invalid trace request, exiting\n");
return true;
}
-#else
- if (interpState->jitState != kJitSelfVerification &&
- dvmJitCheckTraceRequest(self,interpState)) {
- interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
- return true;
- }
-#endif /* WITH_SELF_VERIFICATION */
#endif /* INTERP_TYPE == INTERP_DBG */
#endif /* WITH_JIT */
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index bfda671..8b30bd6 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -1217,25 +1217,21 @@
interpState->pc,
interpState->method->name);
#endif
-
#if INTERP_TYPE == INTERP_DBG
- /* Check to see if we've got a trace selection request. If we do,
- * but something is amiss, revert to the fast interpreter.
- */
-#if !defined(WITH_SELF_VERIFICATION)
- if (dvmJitCheckTraceRequest(self,interpState)) {
+ /* Check to see if we've got a trace selection request. */
+ if (
+#if defined(WITH_SELF_VERIFICATION)
+ (interpState->jitState != kJitSelfVerification) &&
+#endif
+ !gDvm.debuggerActive &&
+#if defined(WITH_PROFILER)
+ (gDvm.activeProfilers == 0) &&
+#endif
+ dvmJitCheckTraceRequest(self, interpState)) {
interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
+ //LOGD("Invalid trace request, exiting\n");
return true;
}
-#else
- if (interpState->jitState != kJitSelfVerification &&
- dvmJitCheckTraceRequest(self,interpState)) {
- interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
- return true;
- }
-#endif /* WITH_SELF_VERIFICATION */
#endif /* INTERP_TYPE == INTERP_DBG */
#endif /* WITH_JIT */
diff --git a/vm/mterp/portable/entry.c b/vm/mterp/portable/entry.c
index 4a6ed4e..8ea4bdc 100644
--- a/vm/mterp/portable/entry.c
+++ b/vm/mterp/portable/entry.c
@@ -42,25 +42,21 @@
interpState->pc,
interpState->method->name);
#endif
-
#if INTERP_TYPE == INTERP_DBG
- /* Check to see if we've got a trace selection request. If we do,
- * but something is amiss, revert to the fast interpreter.
- */
-#if !defined(WITH_SELF_VERIFICATION)
- if (dvmJitCheckTraceRequest(self,interpState)) {
+ /* Check to see if we've got a trace selection request. */
+ if (
+#if defined(WITH_SELF_VERIFICATION)
+ (interpState->jitState != kJitSelfVerification) &&
+#endif
+ !gDvm.debuggerActive &&
+#if defined(WITH_PROFILER)
+ (gDvm.activeProfilers == 0) &&
+#endif
+ dvmJitCheckTraceRequest(self, interpState)) {
interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
+ //LOGD("Invalid trace request, exiting\n");
return true;
}
-#else
- if (interpState->jitState != kJitSelfVerification &&
- dvmJitCheckTraceRequest(self,interpState)) {
- interpState->nextMode = INTERP_STD;
- //LOGD("** something wrong, exiting\n");
- return true;
- }
-#endif /* WITH_SELF_VERIFICATION */
#endif /* INTERP_TYPE == INTERP_DBG */
#endif /* WITH_JIT */