summaryrefslogtreecommitdiffstats
path: root/vm/compiler/Compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/Compiler.c')
-rw-r--r--vm/compiler/Compiler.c139
1 files changed, 103 insertions, 36 deletions
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 45d8317d0..014013db6 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -54,14 +54,16 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
int cc;
int i;
int numWork;
+ int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
+ bool result = true;
dvmLockMutex(&gDvmJit.compilerLock);
/* Queue full */
if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE ||
gDvmJit.codeCacheFull == true) {
- dvmUnlockMutex(&gDvmJit.compilerLock);
- return false;
+ result = false;
+ goto done;
}
for (numWork = gDvmJit.compilerQueueLength,
@@ -83,7 +85,8 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
newOrder->info = info;
newOrder->result.codeAddress = NULL;
newOrder->result.discardResult =
- (kind == kWorkOrderTraceDebug) ? true : false;
+ (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ?
+ true : false;
gDvmJit.compilerWorkEnqueueIndex++;
if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
gDvmJit.compilerWorkEnqueueIndex = 0;
@@ -93,7 +96,8 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
done:
dvmUnlockMutex(&gDvmJit.compilerLock);
- return true;
+ dvmChangeStatus(NULL, oldStatus);
+ return result;
}
/* Block until queue length is 0 */
@@ -108,6 +112,93 @@ void dvmCompilerDrainQueue(void)
dvmChangeStatus(NULL, oldStatus);
}
+bool dvmCompilerSetupCodeCache(void)
+{
+ extern void dvmCompilerTemplateStart(void);
+ extern void dmvCompilerTemplateEnd(void);
+
+ /* Allocate the code cache */
+ gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ if (gDvmJit.codeCache == MAP_FAILED) {
+ LOGE("Failed to create the code cache: %s\n", strerror(errno));
+ return false;
+ }
+
+ /* Copy the template code into the beginning of the code cache */
+ int templateSize = (intptr_t) dmvCompilerTemplateEnd -
+ (intptr_t) dvmCompilerTemplateStart;
+ memcpy((void *) gDvmJit.codeCache,
+ (void *) dvmCompilerTemplateStart,
+ templateSize);
+
+ gDvmJit.templateSize = templateSize;
+ gDvmJit.codeCacheByteUsed = templateSize;
+
+ /* Only flush the part in the code cache that is being used now */
+ cacheflush((intptr_t) gDvmJit.codeCache,
+ (intptr_t) gDvmJit.codeCache + templateSize, 0);
+ return true;
+}
+
+static void resetCodeCache(void)
+{
+ Thread* self = dvmThreadSelf();
+ Thread* thread;
+
+ LOGD("Reset the JIT code cache (%d bytes used)", gDvmJit.codeCacheByteUsed);
+
+ /* Stop the world */
+ dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET);
+
+ /* Wipe out the returnAddr field that soon will point to stale code */
+ for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
+ if (thread == self)
+ continue;
+
+ /* Crawl the Dalvik stack frames */
+ StackSaveArea *ssaPtr = ((StackSaveArea *) thread->curFrame) - 1;
+ while (ssaPtr != ((StackSaveArea *) NULL) - 1) {
+ ssaPtr->returnAddr = NULL;
+ ssaPtr = ((StackSaveArea *) ssaPtr->prevFrame) - 1;
+ };
+ }
+
+ /* Reset the JitEntry table contents to the initial unpopulated state */
+ dvmJitResetTable();
+
+#if 0
+ /*
+ * Uncomment the following code when testing/debugging.
+ *
+ * Wipe out the code cache content to force immediate crashes if
+ * stale JIT'ed code is invoked.
+ */
+ memset(gDvmJit.codeCache,
+ (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed,
+ 0);
+ cacheflush((intptr_t) gDvmJit.codeCache,
+ (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0);
+#endif
+
+ /* Reset the current mark of used bytes to the end of template code */
+ gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
+ gDvmJit.numCompilations = 0;
+
+ /* Reset the work queue */
+ memset(gDvmJit.compilerWorkQueue, 0,
+ sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
+ gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
+ gDvmJit.compilerQueueLength = 0;
+
+ /* All clear now */
+ gDvmJit.codeCacheFull = false;
+
+ /* Resume all threads */
+ dvmResumeAllThreads(SUSPEND_FOR_CC_RESET);
+}
+
static void *compilerThreadStart(void *arg)
{
dvmChangeStatus(NULL, THREAD_VMWAIT);
@@ -156,11 +247,17 @@ static void *compilerThreadStart(void *arg)
if (!dvmCompilerDoWork(&work)) {
work.result.codeAddress = gDvmJit.interpretTemplate;
}
- dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
- work.result.instructionSet);
+ if (!work.result.discardResult) {
+ dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
+ work.result.instructionSet);
+ }
}
free(work.info);
dvmLockMutex(&gDvmJit.compilerLock);
+
+ if (gDvmJit.codeCacheFull == true) {
+ resetCodeCache();
+ }
} while (workQueueLength() != 0);
}
}
@@ -178,36 +275,6 @@ static void *compilerThreadStart(void *arg)
return NULL;
}
-bool dvmCompilerSetupCodeCache(void)
-{
- extern void dvmCompilerTemplateStart(void);
- extern void dmvCompilerTemplateEnd(void);
-
- /* Allocate the code cache */
- gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANON, -1, 0);
- if (gDvmJit.codeCache == MAP_FAILED) {
- LOGE("Failed to create the code cache: %s\n", strerror(errno));
- return false;
- }
-
- /* Copy the template code into the beginning of the code cache */
- int templateSize = (intptr_t) dmvCompilerTemplateEnd -
- (intptr_t) dvmCompilerTemplateStart;
- memcpy((void *) gDvmJit.codeCache,
- (void *) dvmCompilerTemplateStart,
- templateSize);
-
- gDvmJit.templateSize = templateSize;
- gDvmJit.codeCacheByteUsed = templateSize;
-
- /* Only flush the part in the code cache that is being used now */
- cacheflush((intptr_t) gDvmJit.codeCache,
- (intptr_t) gDvmJit.codeCache + templateSize, 0);
- return true;
-}
-
bool dvmCompilerStartup(void)
{
/* Make sure the BBType enum is in sane state */