diff options
author | Ben Cheng <bccheng@google.com> | 2010-01-04 12:29:56 -0800 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2010-01-07 13:42:30 -0800 |
commit | 60c24f436d603c564d5351a6f81821f12635733c (patch) | |
tree | a7891b72a6390aed9692803e84642e6bcc61dc50 /vm/compiler/Compiler.c | |
parent | 81315cc4a0209073e0ae4946a6400b2cb571e616 (diff) | |
download | android_dalvik-60c24f436d603c564d5351a6f81821f12635733c.tar.gz android_dalvik-60c24f436d603c564d5351a6f81821f12635733c.tar.bz2 android_dalvik-60c24f436d603c564d5351a6f81821f12635733c.zip |
Tear down the code cache when it is full and restart from scratch.
Because the code cache may be wiped out after safe points now the patching of
inline cache for predicted chains is done through the compiler thread's work
queue.
Diffstat (limited to 'vm/compiler/Compiler.c')
-rw-r--r-- | vm/compiler/Compiler.c | 139 |
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 */ |