Compiler.cpp revision 6999d84e2c55dc4a46a6c311b55bd5811336d9c4
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 52964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/* 53964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful. 54964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * This routine will not block, but simply return if it couldn't 55964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * aquire the lock or if the queue is full. 56964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 57ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 58ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 60ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int i; 61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int numWork; 6260c24f436d603c564d5351a6f81821f12635733cBen Cheng bool result = true; 63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 64964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmTryLockMutex(&gDvmJit.compilerLock)) { 65964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; // Couldn't aquire the lock 66964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 696999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Return if queue or code cache is full. 707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE || 726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull == true) { 7360c24f436d603c564d5351a6f81821f12635733cBen Cheng result = false; 74964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkQueue[i++].pc == pc) 83964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 89ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 90ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 91ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 92ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 93ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 94ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 95ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 966999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng (kind == kWorkOrderTraceDebug) ? true : false; 9733672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 9833672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 106964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit: 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 10860c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */ 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 114d726991ba52466cde88e37aba4de2395b62477faBill Buzbee int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) { 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock); 118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 120d726991ba52466cde88e37aba4de2395b62477faBill Buzbee dvmChangeStatus(NULL, oldStatus); 121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 12360c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 12460c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 12560c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 12660c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 12760c24f436d603c564d5351a6f81821f12635733cBen Cheng 12860c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 12960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE, 13060c24f436d603c564d5351a6f81821f12635733cBen Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 13160c24f436d603c564d5351a6f81821f12635733cBen Cheng MAP_PRIVATE | MAP_ANON, -1, 0); 13260c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 13360c24f436d603c564d5351a6f81821f12635733cBen Cheng LOGE("Failed to create the code cache: %s\n", strerror(errno)); 13460c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 13560c24f436d603c564d5351a6f81821f12635733cBen Cheng } 13660c24f436d603c564d5351a6f81821f12635733cBen Cheng 1376999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng // STOPSHIP - for debugging only 1386999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("Code cache starts at %p", gDvmJit.codeCache); 1397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 14060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 14160c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 14260c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 14360c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 14460c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 14560c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 14660c24f436d603c564d5351a6f81821f12635733cBen Cheng 14760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 14860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 14960c24f436d603c564d5351a6f81821f12635733cBen Cheng 15060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 15160c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 15360c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 15460c24f436d603c564d5351a6f81821f12635733cBen Cheng} 15560c24f436d603c564d5351a6f81821f12635733cBen Cheng 1567a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 1577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 1587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng void *fp = thread->curFrame; 1597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 1607a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 1617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 1647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 1657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 1667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 1677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 1697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 1707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 1717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (dvmIsBreakFrame(fp)) { 1747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: break frame (%p)", 1757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 1767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 1787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: %s.%s%s (%p)", 1797a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 1807a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 1817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 1827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 1837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 1847a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 1857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 1887a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 1947a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 19760c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 19860c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 19960c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 2026999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng int byteUsed = gDvmJit.codeCacheByteUsed; 20360c24f436d603c564d5351a6f81821f12635733cBen Cheng 2047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* If any thread is found stuck in the JIT state, don't reset the cache */ 20560c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 2076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Crawl the stack to wipe out the returnAddr field so that 2086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) the soon-to-be-deleted code in the JIT cache won't be used 2096999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) or the thread stuck in the JIT land will soon return 2106999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * to the interpreter land 2116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng crawlDalvikStack(thread, false); 2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 21760c24f436d603c564d5351a6f81821f12635733cBen Cheng 2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 2196999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset delayed (%d bytes %d/%d)", 2206999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset, 2216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng ++gDvmJit.numCodeCacheResetDelayed); 2226999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng return; 2237a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2256999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Lock the mutex to clean up the work queue */ 2266999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 2276999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 2286999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Drain the work queue to free the work orders */ 2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 23460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 23560c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 23660c24f436d603c564d5351a6f81821f12635733cBen Cheng 23760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 23860c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 23960c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 24060c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 2417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng memset((char *) gDvmJit.codeCache + gDvmJit.templateSize, 2427a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 0, 2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 24460c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 24560c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 24660c24f436d603c564d5351a6f81821f12635733cBen Cheng 24760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 24860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 24960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 25060c24f436d603c564d5351a6f81821f12635733cBen Cheng 25160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 25260c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 25360c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 25460c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 25560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 25660c24f436d603c564d5351a6f81821f12635733cBen Cheng 2576999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Reset the IC patch work queue */ 2586999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerICPatchLock); 2596999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.compilerICPatchIndex = 0; 2606999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 2616999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 26260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 26360c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 26460c24f436d603c564d5351a6f81821f12635733cBen Cheng 2656999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 2667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2676999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)", 2686999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng (dvmGetRelativeTimeUsec() - startTime) / 1000, 2696999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng byteUsed, ++gDvmJit.numCodeCacheReset, 2706999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.numCodeCacheResetDelayed); 2716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng} 2726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 2736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/* 2746999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently 2756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do: 2766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it 2776999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * from scratch. 2786999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders. 2796999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2806999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void) 2816999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{ 2826999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.codeCacheFull) { 2836999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng resetCodeCache(); 2846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } 2856999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmCompilerPatchInlineCache(); 28660c24f436d603c564d5351a6f81821f12635733cBen Cheng} 28760c24f436d603c564d5351a6f81821f12635733cBen Cheng 288964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeebool compilerThreadStartup(void) 289964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{ 290964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee JitEntry *pJitTable = NULL; 291964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned char *pJitProfTable = NULL; 292964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned int i; 293964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 294964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerArchInit()) 295964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 296964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 297964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 298964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Setup the code cache if we have not inherited a valid code cache 299964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * from the zygote. 300964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 301964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCache == NULL) { 302964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerSetupCodeCache()) 303964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 304964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 305964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 306964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Allocate the initial arena block */ 307964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmCompilerHeapInit() == false) { 308964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 309964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 310964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 311964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 312964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 313964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Track method-level compilation statistics */ 314964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 315964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 316964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 317964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 318964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Set up the JitTable */ 319964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 320964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Power of 2? */ 321964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(gDvmJit.jitTableSize && 322964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1))); 323964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 324964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmInitMutex(&gDvmJit.tableLock); 325964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.tableLock); 326964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable = (JitEntry*) 327964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee calloc(gDvmJit.jitTableSize, sizeof(*pJitTable)); 328964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitTable) { 329964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit table allocation failed\n"); 330964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * NOTE: the profile table must only be allocated once, globally. 335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Profiling is turned on and off by nulling out gDvm.pJitProfTable 336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and then restoring its original value. However, this action 337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is not syncronized for speed so threads may continue to hold 338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and update the profile table after profiling has been turned 339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * off by null'ng the global pointer. Be aware. 340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE); 342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitProfTable) { 343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit prof table allocation failed\n"); 344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 347964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE); 348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee for (i=0; i < gDvmJit.jitTableSize; i++) { 349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable[i].u.info.chain = gDvmJit.jitTableSize; 350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Is chain field wide enough for termination pattern? */ 352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize); 353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pJitEntryTable = pJitTable; 355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1; 356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableEntriesUsed = 0; 357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.compilerHighWater = 358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pProfTable = pJitProfTable; 36006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTableCopy = pJitProfTable; 361964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 362964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 363964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Signal running threads to refresh their cached pJitTable pointers */ 364964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); 365964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmResumeAllThreads(SUSPEND_FOR_REFRESH); 366964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return true; 367964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 368964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail: 369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; 370964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 371964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee} 372964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 373ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 37594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee int ret; 37694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee struct timespec ts; 37794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 3785ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 3795ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 380b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 381b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * Wait a little before recieving translation requests on the assumption 382964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * that process start-up code isn't worth compiling. 383b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 38494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 38594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 38694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* 38794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * TUNING: once framework is calling VMRuntime.startJitCompilation, 38894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * experiment with the delay time (and perhaps have target-dependent 38994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * values? 39094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee */ 39194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmAbsoluteTime(1000, 0, &ts); 39294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC) 39394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee ret = pthread_cond_timedwait_monotonic(&gDvmJit.compilerQueueActivity, 39494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee &gDvmJit.compilerLock, &ts); 39594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#else 39694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee ret = pthread_cond_timedwait(&gDvmJit.compilerQueueActivity, 39794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee &gDvmJit.compilerLock, &ts); 39894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#endif 39994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee assert(ret == 0 || ret == ETIMEDOUT); 40094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 40194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee if (gDvmJit.haltCompilerThread) { 40294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 40394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee return NULL; 40494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee } 40594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 40694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 40794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 408964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStartup(); 409b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 410ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 411ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 412ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 413ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 414ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 415ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 416ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 417ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 418ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 419ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 420ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 421ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 422ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 423ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 424ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 425ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 426ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 427ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 429964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Check whether there is a suspend request on me. This 430964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is necessary to allow a clean shutdown. 431964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 432ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmCheckSuspendPending(NULL); 4332717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 4342717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 4352717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 4366999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng bool resizeFail = 4376999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 4386999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 4396999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * If the jit table is full, consider it's time to reset 4406999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * the code cache too. 4416999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 4426999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull |= resizeFail; 4432717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 444ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 445ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 4466999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } else if (!gDvmJit.codeCacheFull) { 447d726991ba52466cde88e37aba4de2395b62477faBill Buzbee /* If compilation failed, use interpret-template */ 448d726991ba52466cde88e37aba4de2395b62477faBill Buzbee if (!dvmCompilerDoWork(&work)) { 449d726991ba52466cde88e37aba4de2395b62477faBill Buzbee work.result.codeAddress = gDvmJit.interpretTemplate; 450ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 45160c24f436d603c564d5351a6f81821f12635733cBen Cheng if (!work.result.discardResult) { 45260c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 45360c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 45460c24f436d603c564d5351a6f81821f12635733cBen Cheng } 455ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 456ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 457ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 458ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 459ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 460ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 461ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 462ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 463ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 4645ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 4655ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 4665ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 4675ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 4685ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 4695ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 4705ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 47143eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden if (gDvm.verboseShutdown) 47243eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden LOGD("Compiler thread shutting down\n"); 473ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 474ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 475ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 476ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 477ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 47894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 47994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmInitMutex(&gDvmJit.compilerLock); 4806999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmInitMutex(&gDvmJit.compilerICPatchLock); 48194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 48294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 48394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 48494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 48594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* Reset the work queue */ 48694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 48794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerQueueLength = 0; 48894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 48994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 490ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 49194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * Defer rest of initialization until we're sure JIT'ng makes sense. Launch 492964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * the compiler thread, which will do the real initialization if and 493964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * when it is signalled to do so. 494ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 495964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 496964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStart, NULL); 497ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 498ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 499ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 500ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 501ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 502ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 503ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 504ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 505ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 506ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 507ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 508ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 509ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 510ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 511ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 512ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 51343eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden else if (gDvm.verboseShutdown) 514ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 515ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 516ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 51706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 51806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 51906bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh() 52006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{ 52106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActive; 52206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActivate; 52306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 52406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmLockMutex(&gDvmJit.tableLock); 52506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActive = gDvmJit.pProfTable != NULL; 52606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0)); 52706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 52806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee if (jitActivate && !jitActive) { 52906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = gDvmJit.pProfTableCopy; 53006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 53106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } else if (!jitActivate && jitActive) { 53206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = NULL; 53306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 53406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmJitUnchainAll(); 53506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } 53606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee} 537