[JIT] Close code cache race window
See http://b/issue?id=4271784 for details.
Three fixes:
1. Verify the code cache version hasn't changed between completion
of the translation and registering it in JitTable
2. When code cache full detected during translating a trace, mark
the "discard" flag on the work order.
3. [The actual cause of the bug] When doing a code cache flush,
traverse the thread least and cancel any trace selections in
progress.
Change-Id: Ifea70416d7d91637fb742fc8de11044a89358caa
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index dfa6589..4f2261b 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -266,7 +266,8 @@
int inJit = 0;
int byteUsed = gDvmJit.codeCacheByteUsed;
- /* If any thread is found stuck in the JIT state, don't reset the cache */
+ /* If any thread is found stuck in the JIT state, don't reset the cache */
+ dvmLockThreadList(NULL);
for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
/*
* Crawl the stack to wipe out the returnAddr field so that
@@ -278,7 +279,11 @@
if (thread->inJitCodeCache) {
inJit++;
}
+ /* Cancel any ongoing trace selection */
+ dvmUpdateInterpBreak(thread, kInterpJitBreak, kSubModeJitTraceBuild,
+ false /* clear */);
}
+ dvmUnlockThreadList();
if (inJit) {
LOGD("JIT code cache reset delayed (%d bytes %d/%d)",
@@ -675,13 +680,23 @@
bool aborted = setjmp(jmpBuf);
if (!aborted) {
bool codeCompiled = dvmCompilerDoWork(&work);
- if (codeCompiled && !work.result.discardResult &&
- work.result.codeAddress) {
+ /*
+ * Make sure we are still operating with the
+ * same translation cache version. See
+ * Issue 4271784 for details.
+ */
+ dvmLockMutex(&gDvmJit.compilerLock);
+ if ((work.result.cacheVersion ==
+ gDvmJit.cacheVersion) &&
+ codeCompiled &&
+ !work.result.discardResult &&
+ work.result.codeAddress) {
dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
work.result.instructionSet,
false, /* not method entry */
work.result.profileCodeSize);
}
+ dvmUnlockMutex(&gDvmJit.compilerLock);
}
dvmCompilerArenaReset();
}