Compiler.cpp revision 43eb5015ca8bc0c859100b659d9c12934011a42e
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 /* 697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * Return if queue is full. 707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * If the code cache is full, we will allow the work order to be added and 717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * we use that to trigger code cache reset. 727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE) { 7460c24f436d603c564d5351a6f81821f12635733cBen Cheng result = false; 75964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkQueue[i++].pc == pc) 84964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 90ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 91ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 92ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 93ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 94ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 95ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 96ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 9760c24f436d603c564d5351a6f81821f12635733cBen Cheng (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ? 9860c24f436d603c564d5351a6f81821f12635733cBen Cheng true : false; 9933672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 10033672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 108964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit: 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 11060c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */ 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 116d726991ba52466cde88e37aba4de2395b62477faBill Buzbee int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) { 119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock); 120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 122d726991ba52466cde88e37aba4de2395b62477faBill Buzbee dvmChangeStatus(NULL, oldStatus); 123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 12560c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 12660c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 12760c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 12860c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 12960c24f436d603c564d5351a6f81821f12635733cBen Cheng 13060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 13160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE, 13260c24f436d603c564d5351a6f81821f12635733cBen Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 13360c24f436d603c564d5351a6f81821f12635733cBen Cheng MAP_PRIVATE | MAP_ANON, -1, 0); 13460c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 13560c24f436d603c564d5351a6f81821f12635733cBen Cheng LOGE("Failed to create the code cache: %s\n", strerror(errno)); 13660c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 13760c24f436d603c564d5351a6f81821f12635733cBen Cheng } 13860c24f436d603c564d5351a6f81821f12635733cBen Cheng 1397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng // For debugging only 1407a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng // LOGD("Code cache starts at %p", gDvmJit.codeCache); 1417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 14260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 14360c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 14460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 14560c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 14660c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 14760c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 14860c24f436d603c564d5351a6f81821f12635733cBen Cheng 14960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 15060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 15160c24f436d603c564d5351a6f81821f12635733cBen Cheng 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 15360c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 15460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 15560c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 15660c24f436d603c564d5351a6f81821f12635733cBen Cheng} 15760c24f436d603c564d5351a6f81821f12635733cBen Cheng 1587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 1597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 1607a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng void *fp = thread->curFrame; 1617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 1627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 1637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 1667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 1677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 1687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 1697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 1717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 1727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 1737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (dvmIsBreakFrame(fp)) { 1767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: break frame (%p)", 1777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 1787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1797a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 1807a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: %s.%s%s (%p)", 1817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 1827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 1837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 1847a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 1857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 1867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 1877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1887a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1947a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 19960c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 20060c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 20160c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 20460c24f436d603c564d5351a6f81821f12635733cBen Cheng 2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Reset the JIT code cache (%d bytes used / %d time(s))", 2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed, ++gDvmJit.numCodeCacheReset); 20760c24f436d603c564d5351a6f81821f12635733cBen Cheng 20860c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Stop the world */ 20960c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET); 21060c24f436d603c564d5351a6f81821f12635733cBen Cheng 2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* If any thread is found stuck in the JIT state, don't reset the cache */ 21260c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * STOPSHIP 2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * Change the verbose mode to false after the new code receives 2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * more QA love. 2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng crawlDalvikStack(thread, true); 2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 22360c24f436d603c564d5351a6f81821f12635733cBen Cheng 2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Wait a while for the busy threads to rest and try again */ 2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset = 256; 2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng goto done; 2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Drain the work queue to free the work order */ 2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 2347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Wipe out the returnAddr field that soon will point to stale code */ 2377a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2387a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng crawlDalvikStack(thread, false); 23960c24f436d603c564d5351a6f81821f12635733cBen Cheng } 24060c24f436d603c564d5351a6f81821f12635733cBen Cheng 24160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 24260c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 24360c24f436d603c564d5351a6f81821f12635733cBen Cheng 24460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 24560c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 24660c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 24760c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 2487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng memset((char *) gDvmJit.codeCache + gDvmJit.templateSize, 2497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 0, 2507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 25160c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 25260c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 25360c24f436d603c564d5351a6f81821f12635733cBen Cheng 25460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 25560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 25660c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 25760c24f436d603c564d5351a6f81821f12635733cBen Cheng 25860c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 25960c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 26060c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 26160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 26260c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 26360c24f436d603c564d5351a6f81821f12635733cBen Cheng 26460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 26560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 26660c24f436d603c564d5351a6f81821f12635733cBen Cheng 2677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Code cache reset takes %lld usec", 2687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetRelativeTimeUsec() - startTime); 2697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengdone: 27160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Resume all threads */ 27260c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmResumeAllThreads(SUSPEND_FOR_CC_RESET); 27360c24f436d603c564d5351a6f81821f12635733cBen Cheng} 27460c24f436d603c564d5351a6f81821f12635733cBen Cheng 275964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeebool compilerThreadStartup(void) 276964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{ 277964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee JitEntry *pJitTable = NULL; 278964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned char *pJitProfTable = NULL; 279964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned int i; 280964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 281964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerArchInit()) 282964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 283964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 284964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 285964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Setup the code cache if we have not inherited a valid code cache 286964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * from the zygote. 287964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 288964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCache == NULL) { 289964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerSetupCodeCache()) 290964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 291964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 292964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 293964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Allocate the initial arena block */ 294964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmCompilerHeapInit() == false) { 295964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 296964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 297964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 298964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 299964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 300964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Track method-level compilation statistics */ 301964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 302964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 303964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 304964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 305964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Set up the JitTable */ 306964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 307964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Power of 2? */ 308964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(gDvmJit.jitTableSize && 309964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1))); 310964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 311964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmInitMutex(&gDvmJit.tableLock); 312964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.tableLock); 313964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable = (JitEntry*) 314964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee calloc(gDvmJit.jitTableSize, sizeof(*pJitTable)); 315964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitTable) { 316964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit table allocation failed\n"); 317964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 318964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 319964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 320964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 321964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * NOTE: the profile table must only be allocated once, globally. 322964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Profiling is turned on and off by nulling out gDvm.pJitProfTable 323964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and then restoring its original value. However, this action 324964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is not syncronized for speed so threads may continue to hold 325964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and update the profile table after profiling has been turned 326964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * off by null'ng the global pointer. Be aware. 327964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 328964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE); 329964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitProfTable) { 330964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit prof table allocation failed\n"); 331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE); 335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee for (i=0; i < gDvmJit.jitTableSize; i++) { 336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable[i].u.info.chain = gDvmJit.jitTableSize; 337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Is chain field wide enough for termination pattern? */ 339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize); 340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pJitEntryTable = pJitTable; 342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1; 343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableEntriesUsed = 0; 344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.compilerHighWater = 345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pProfTable = pJitProfTable; 34706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTableCopy = pJitProfTable; 348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Signal running threads to refresh their cached pJitTable pointers */ 351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); 352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmResumeAllThreads(SUSPEND_FOR_REFRESH); 353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return true; 354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail: 356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; 357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee} 359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 360ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 36294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee int ret; 36394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee struct timespec ts; 36494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 3655ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 3665ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 367b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 368b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * Wait a little before recieving translation requests on the assumption 369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * that process start-up code isn't worth compiling. 370b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 37194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 37294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 37394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* 37494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * TUNING: once framework is calling VMRuntime.startJitCompilation, 37594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * experiment with the delay time (and perhaps have target-dependent 37694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * values? 37794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee */ 37894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmAbsoluteTime(1000, 0, &ts); 37994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC) 38094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee ret = pthread_cond_timedwait_monotonic(&gDvmJit.compilerQueueActivity, 38194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee &gDvmJit.compilerLock, &ts); 38294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#else 38394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee ret = pthread_cond_timedwait(&gDvmJit.compilerQueueActivity, 38494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee &gDvmJit.compilerLock, &ts); 38594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#endif 38694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee assert(ret == 0 || ret == ETIMEDOUT); 38794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 38894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee if (gDvmJit.haltCompilerThread) { 38994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 39094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee return NULL; 39194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee } 39294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 39394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 39494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStartup(); 396b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 397ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 398ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 399ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 400ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 401ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 402ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 403ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 404ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 405ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 406ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 407ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 408ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 409ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 410ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 411ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 412ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 413964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee bool resizeFail = false; 414ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 415ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 416964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 417964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Check whether there is a suspend request on me. This 418964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is necessary to allow a clean shutdown. 419964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 420ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmCheckSuspendPending(NULL); 4212717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 4222717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 4232717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 424964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee resizeFail = dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 4252717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 426ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 427ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } else if (!resizeFail) { 429d726991ba52466cde88e37aba4de2395b62477faBill Buzbee /* If compilation failed, use interpret-template */ 430d726991ba52466cde88e37aba4de2395b62477faBill Buzbee if (!dvmCompilerDoWork(&work)) { 431d726991ba52466cde88e37aba4de2395b62477faBill Buzbee work.result.codeAddress = gDvmJit.interpretTemplate; 432ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 43360c24f436d603c564d5351a6f81821f12635733cBen Cheng if (!work.result.discardResult) { 43460c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 43560c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 43660c24f436d603c564d5351a6f81821f12635733cBen Cheng } 437ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 438ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 439ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 44060c24f436d603c564d5351a6f81821f12635733cBen Cheng 44149ca78679485ee56d5925da122216821c668043fBen Cheng /* 44249ca78679485ee56d5925da122216821c668043fBen Cheng * FIXME - temporarily disable code cache reset until 44349ca78679485ee56d5925da122216821c668043fBen Cheng * stale code stops leaking. 44449ca78679485ee56d5925da122216821c668043fBen Cheng */ 44549ca78679485ee56d5925da122216821c668043fBen Cheng#if 0 446964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCacheFull == true || resizeFail) { 4477a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (gDvmJit.delayCodeCacheReset == 0) { 4487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng resetCodeCache(); 4497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(workQueueLength() == 0 || 4507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset != 0); 4517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } else { 4527a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Delay the next %d tries to reset code cache", 4537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset); 4547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset--; 4557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 45660c24f436d603c564d5351a6f81821f12635733cBen Cheng } 45749ca78679485ee56d5925da122216821c668043fBen Cheng#endif 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); 48094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 48194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 48294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 48394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 48494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* Reset the work queue */ 48594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 48694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerQueueLength = 0; 48794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 48894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 489ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 49094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * Defer rest of initialization until we're sure JIT'ng makes sense. Launch 491964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * the compiler thread, which will do the real initialization if and 492964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * when it is signalled to do so. 493ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 494964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 495964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStart, NULL); 496ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 497ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 498ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 499ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 500ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 501ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 502ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 503ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 504ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 505ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 506ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 507ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 508ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 509ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 510ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 511ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 51243eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden else if (gDvm.verboseShutdown) 513ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 514ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 515ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 51606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 51706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 51806bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh() 51906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{ 52006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActive; 52106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActivate; 52206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 52306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmLockMutex(&gDvmJit.tableLock); 52406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActive = gDvmJit.pProfTable != NULL; 52506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0)); 52606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 52706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee if (jitActivate && !jitActive) { 52806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = gDvmJit.pProfTableCopy; 52906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 53006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } else if (!jitActivate && jitActive) { 53106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = NULL; 53206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 53306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmJitUnchainAll(); 53406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } 53506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee} 536