Compiler.cpp revision 33672456e19bff9913b4a3459e6b8472f4c26c84
1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* 2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Copyright (C) 2009 The Android Open Source Project 3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * you may not use this file except in compliance with the License. 6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * You may obtain a copy of the License at 7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * http://www.apache.org/licenses/LICENSE-2.0 9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Unless required by applicable law or agreed to in writing, software 11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See the License for the specific language governing permissions and 14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * limitations under the License. 15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 17ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <sys/mman.h> 18ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <errno.h> 19ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "Dalvik.h" 21ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "interp/Jit.h" 22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "CompilerInternals.h" 23ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 24ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void) 25ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 26ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return gDvmJit.compilerQueueLength; 27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void) 30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind 32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng != kWorkOrderInvalid); 33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = 34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex]; 35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind = 36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng kWorkOrderInvalid; 37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) { 38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkDequeueIndex = 0; 39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength--; 41f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee if (gDvmJit.compilerQueueLength == 0) { 42f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee int cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 43f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee } 44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Remember the high water mark of the queue length */ 46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued) 47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength; 48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return work; 50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 53ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 54ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 55ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int i; 56ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int numWork; 5760c24f436d603c564d5351a6f81821f12635733cBen Cheng int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 5860c24f436d603c564d5351a6f81821f12635733cBen Cheng bool result = true; 59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 60ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 62ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Queue full */ 63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE || 64ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.codeCacheFull == true) { 6560c24f436d603c564d5351a6f81821f12635733cBen Cheng result = false; 6660c24f436d603c564d5351a6f81821f12635733cBen Cheng goto done; 67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 68ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 69ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 70ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 72ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 73ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 74ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkQueue[i++].pc == pc) 75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto done; 76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 81ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 82ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 83ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 84ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 85ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 86ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 87ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 8860c24f436d603c564d5351a6f81821f12635733cBen Cheng (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ? 8960c24f436d603c564d5351a6f81821f12635733cBen Cheng true : false; 9033672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 9133672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 92ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 93ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 94ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 95ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 98ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdone: 100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 10160c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmChangeStatus(NULL, oldStatus); 10260c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */ 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 108d726991ba52466cde88e37aba4de2395b62477faBill Buzbee int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) { 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock); 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 114d726991ba52466cde88e37aba4de2395b62477faBill Buzbee dvmChangeStatus(NULL, oldStatus); 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 11760c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 11860c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 11960c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 12060c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 12160c24f436d603c564d5351a6f81821f12635733cBen Cheng 12260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 12360c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE, 12460c24f436d603c564d5351a6f81821f12635733cBen Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 12560c24f436d603c564d5351a6f81821f12635733cBen Cheng MAP_PRIVATE | MAP_ANON, -1, 0); 12660c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 12760c24f436d603c564d5351a6f81821f12635733cBen Cheng LOGE("Failed to create the code cache: %s\n", strerror(errno)); 12860c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 12960c24f436d603c564d5351a6f81821f12635733cBen Cheng } 13060c24f436d603c564d5351a6f81821f12635733cBen Cheng 13160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 13260c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 13360c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 13460c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 13560c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 13660c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 13760c24f436d603c564d5351a6f81821f12635733cBen Cheng 13860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 13960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 14060c24f436d603c564d5351a6f81821f12635733cBen Cheng 14160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 14260c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 14360c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 14460c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 14560c24f436d603c564d5351a6f81821f12635733cBen Cheng} 14660c24f436d603c564d5351a6f81821f12635733cBen Cheng 14760c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 14860c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 14960c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* self = dvmThreadSelf(); 15060c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 15160c24f436d603c564d5351a6f81821f12635733cBen Cheng 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng LOGD("Reset the JIT code cache (%d bytes used)", gDvmJit.codeCacheByteUsed); 15360c24f436d603c564d5351a6f81821f12635733cBen Cheng 15460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Stop the world */ 15560c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET); 15660c24f436d603c564d5351a6f81821f12635733cBen Cheng 15760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Wipe out the returnAddr field that soon will point to stale code */ 15860c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 15960c24f436d603c564d5351a6f81821f12635733cBen Cheng if (thread == self) 16060c24f436d603c564d5351a6f81821f12635733cBen Cheng continue; 16160c24f436d603c564d5351a6f81821f12635733cBen Cheng 16260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Crawl the Dalvik stack frames */ 16360c24f436d603c564d5351a6f81821f12635733cBen Cheng StackSaveArea *ssaPtr = ((StackSaveArea *) thread->curFrame) - 1; 16460c24f436d603c564d5351a6f81821f12635733cBen Cheng while (ssaPtr != ((StackSaveArea *) NULL) - 1) { 16560c24f436d603c564d5351a6f81821f12635733cBen Cheng ssaPtr->returnAddr = NULL; 16660c24f436d603c564d5351a6f81821f12635733cBen Cheng ssaPtr = ((StackSaveArea *) ssaPtr->prevFrame) - 1; 16760c24f436d603c564d5351a6f81821f12635733cBen Cheng }; 16860c24f436d603c564d5351a6f81821f12635733cBen Cheng } 16960c24f436d603c564d5351a6f81821f12635733cBen Cheng 17060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 17160c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 17260c24f436d603c564d5351a6f81821f12635733cBen Cheng 17360c24f436d603c564d5351a6f81821f12635733cBen Cheng#if 0 17460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 17560c24f436d603c564d5351a6f81821f12635733cBen Cheng * Uncomment the following code when testing/debugging. 17660c24f436d603c564d5351a6f81821f12635733cBen Cheng * 17760c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 17860c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 17960c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 18060c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.codeCache, 18160c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 18260c24f436d603c564d5351a6f81821f12635733cBen Cheng 0); 18360c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 18460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 18560c24f436d603c564d5351a6f81821f12635733cBen Cheng#endif 18660c24f436d603c564d5351a6f81821f12635733cBen Cheng 18760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 18860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 18960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 19060c24f436d603c564d5351a6f81821f12635733cBen Cheng 19160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 19260c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 19360c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 19460c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 19560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 19660c24f436d603c564d5351a6f81821f12635733cBen Cheng 19760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 19860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 19960c24f436d603c564d5351a6f81821f12635733cBen Cheng 20060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Resume all threads */ 20160c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmResumeAllThreads(SUSPEND_FOR_CC_RESET); 20260c24f436d603c564d5351a6f81821f12635733cBen Cheng} 20360c24f436d603c564d5351a6f81821f12635733cBen Cheng 204ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 205ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 2065ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 2075ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 208b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 209b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * Wait a little before recieving translation requests on the assumption 210b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * that process start-up code isn't worth compiling. The trace 211b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * selector won't attempt to request a translation if the queue is 212b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * filled, so we'll prevent by keeping the high water mark at zero 213b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * for a shore time. 214b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 215b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee assert(gDvmJit.compilerHighWater == 0); 216b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee usleep(1000); 217b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee gDvmJit.compilerHighWater = 218b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 219b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 220ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 221ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 222ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 223ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 224ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 225ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 226ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 227ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 228ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 229ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 230ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 231ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 232ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 233ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 234ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 235ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 236ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 237ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 238ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Check whether there is a suspend request on me */ 239ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmCheckSuspendPending(NULL); 2402717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 2412717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 2422717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 2432717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 2442717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 245ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 246ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 247ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 248d726991ba52466cde88e37aba4de2395b62477faBill Buzbee /* If compilation failed, use interpret-template */ 249d726991ba52466cde88e37aba4de2395b62477faBill Buzbee if (!dvmCompilerDoWork(&work)) { 250d726991ba52466cde88e37aba4de2395b62477faBill Buzbee work.result.codeAddress = gDvmJit.interpretTemplate; 251ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 25260c24f436d603c564d5351a6f81821f12635733cBen Cheng if (!work.result.discardResult) { 25360c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 25460c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 25560c24f436d603c564d5351a6f81821f12635733cBen Cheng } 256ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 257ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 258ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 25960c24f436d603c564d5351a6f81821f12635733cBen Cheng 26060c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCacheFull == true) { 26160c24f436d603c564d5351a6f81821f12635733cBen Cheng resetCodeCache(); 26260c24f436d603c564d5351a6f81821f12635733cBen Cheng } 263ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 264ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 265ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 266ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 267ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 268ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 2695ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 2705ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 2715ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 2725ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 2735ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 2745ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 2755ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 276ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread shutting down\n"); 277ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 278ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 279ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 280ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 281ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 282ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Make sure the BBType enum is in sane state */ 2831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee assert(kChainingCellNormal == 0); 284ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 285ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Architecture-specific chores to initialize */ 286ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCompilerArchInit()) 287ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 288ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 289ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 290ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Setup the code cache if it is not done so already. For apps it should be 291ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * done by the Zygote already, but for command-line dalvikvm invocation we 292ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * need to do it here. 293ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 294ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.codeCache == NULL) { 295ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCompilerSetupCodeCache()) 296ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 297ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 298ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 299ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Allocate the initial arena block */ 300ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (dvmCompilerHeapInit() == false) { 301ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 302ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 303ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 304ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmInitMutex(&gDvmJit.compilerLock); 305ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 306ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 307ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 308ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 309ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 310ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = false; 311ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 312ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Reset the work queue */ 313ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng memset(gDvmJit.compilerWorkQueue, 0, 314ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 315ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 316ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength = 0; 317b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* Block new entries via HighWater until compiler thread is ready */ 318b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee gDvmJit.compilerHighWater = 0; 319ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 320ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerHighWater < COMPILER_WORK_QUEUE_SIZE); 321ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng compilerThreadStart, NULL)) { 323ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 324ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 325ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 326ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 3278b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng /* Track method-level compilation statistics */ 3288b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 3298b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng 330ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 331ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 332ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return true; 333ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 334ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengfail: 335ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return false; 336ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 337ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 338ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 339ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 340ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 341ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 342ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 344ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 345ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 347ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 348ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 349ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 350ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 351ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 352ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng else 353ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 354ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 355ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 356