Compiler.cpp revision fc519dc8f4444f6d93806ec15ce7445b322070fd
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> 197c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng#include <cutils/ashmem.h> 20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 21ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "Dalvik.h" 22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "interp/Jit.h" 23ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "CompilerInternals.h" 24ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 25ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void) 26ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return gDvmJit.compilerQueueLength; 28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void) 31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind 33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng != kWorkOrderInvalid); 34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = 35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex]; 36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind = 37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng kWorkOrderInvalid; 38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) { 39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkDequeueIndex = 0; 40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength--; 42f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee if (gDvmJit.compilerQueueLength == 0) { 43f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee int cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 44f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee } 45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Remember the high water mark of the queue length */ 47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued) 48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength; 49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return work; 51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 53964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/* 54964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful. 55964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * This routine will not block, but simply return if it couldn't 56964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * aquire the lock or if the queue is full. 571357e94efecd485bda933270a9181035f6a39e09Ben Cheng * 581357e94efecd485bda933270a9181035f6a39e09Ben Cheng * NOTE: Make sure that the caller frees the info pointer if the return value 591357e94efecd485bda933270a9181035f6a39e09Ben Cheng * is false. 60964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 62ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 64ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int i; 65ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int numWork; 6660c24f436d603c564d5351a6f81821f12635733cBen Cheng bool result = true; 67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 68964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmTryLockMutex(&gDvmJit.compilerLock)) { 693e5cd17e4a0306dc976e1dc37b39d19dee4451a7Ben Cheng return false; // Couldn't acquire the lock 70964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Return if queue or code cache is full. 747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE || 766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull == true) { 7760c24f436d603c564d5351a6f81821f12635733cBen Cheng result = false; 78964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkQueue[i++].pc == pc) 87964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto unlockAndExit; 88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 90ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 91ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 92ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 93ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 94ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 95ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 96ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 97ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 98ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 99ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 1001f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee (kind == kWorkOrderTraceDebug) ? true : false; 10133672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 10233672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 110964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit: 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 11260c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */ 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 118d726991ba52466cde88e37aba4de2395b62477faBill Buzbee int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) { 121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock); 122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 124d726991ba52466cde88e37aba4de2395b62477faBill Buzbee dvmChangeStatus(NULL, oldStatus); 125ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 126ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 12760c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 12860c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 12960c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 13060c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 1317c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng int fd; 13260c24f436d603c564d5351a6f81821f12635733cBen Cheng 13360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 1347c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize); 1357c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng if (fd < 0) { 1367c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng LOGE("Could not create %u-byte ashmem region for the JIT code cache", 1377c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCacheSize); 1387c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng return false; 1397c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng } 1407c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize, 1417c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 1427c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng MAP_PRIVATE , fd, 0); 1437c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng close(fd); 14460c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 1457c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng LOGE("Failed to mmap the JIT code cache: %s\n", strerror(errno)); 14660c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 14760c24f436d603c564d5351a6f81821f12635733cBen Cheng } 14860c24f436d603c564d5351a6f81821f12635733cBen Cheng 1497c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */ 1507c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng // LOGD("Code cache starts at %p", gDvmJit.codeCache); 1517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 15360c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 15460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 15560c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 15660c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 15760c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 15860c24f436d603c564d5351a6f81821f12635733cBen Cheng 15960c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 16060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 16160c24f436d603c564d5351a6f81821f12635733cBen Cheng 16260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 16360c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 16460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 16560c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 16660c24f436d603c564d5351a6f81821f12635733cBen Cheng} 16760c24f436d603c564d5351a6f81821f12635733cBen Cheng 1687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 1697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 1707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng void *fp = thread->curFrame; 1717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 1727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 1737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 1767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 1777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 1787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 1797a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1807a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 1817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 1827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 1837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1847a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (dvmIsBreakFrame(fp)) { 1867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: break frame (%p)", 1877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 1887a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: %s.%s%s (%p)", 1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 1947a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1997a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 2077a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 2087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 20960c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 21060c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 21160c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 2127a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 2146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng int byteUsed = gDvmJit.codeCacheByteUsed; 21560c24f436d603c564d5351a6f81821f12635733cBen Cheng 2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* If any thread is found stuck in the JIT state, don't reset the cache */ 21760c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2186999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 2196999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Crawl the stack to wipe out the returnAddr field so that 2206999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) the soon-to-be-deleted code in the JIT cache won't be used 2216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) or the thread stuck in the JIT land will soon return 2226999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * to the interpreter land 2236999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2246999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng crawlDalvikStack(thread, false); 2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 22960c24f436d603c564d5351a6f81821f12635733cBen Cheng 2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 2316999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset delayed (%d bytes %d/%d)", 2326999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset, 2336999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng ++gDvmJit.numCodeCacheResetDelayed); 2346999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng return; 2357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2376999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Lock the mutex to clean up the work queue */ 2386999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 2396999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 2406999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Drain the work queue to free the work orders */ 2417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 2427a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 2447a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2457a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 24660c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 24760c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 24860c24f436d603c564d5351a6f81821f12635733cBen Cheng 24960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 25060c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 25160c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 25260c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 2537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng memset((char *) gDvmJit.codeCache + gDvmJit.templateSize, 2547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 0, 2557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 25660c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 25760c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 25860c24f436d603c564d5351a6f81821f12635733cBen Cheng 25960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 26060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 26160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 26260c24f436d603c564d5351a6f81821f12635733cBen Cheng 26360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 26460c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 26560c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 26660c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 26760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 26860c24f436d603c564d5351a6f81821f12635733cBen Cheng 2696999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Reset the IC patch work queue */ 2706999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerICPatchLock); 2716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.compilerICPatchIndex = 0; 2726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 2736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 27460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 27560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 27660c24f436d603c564d5351a6f81821f12635733cBen Cheng 2776999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 2787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2796999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)", 2806999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng (dvmGetRelativeTimeUsec() - startTime) / 1000, 2816999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng byteUsed, ++gDvmJit.numCodeCacheReset, 2826999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.numCodeCacheResetDelayed); 2836999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng} 2846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 2856999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/* 2866999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently 2876999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do: 2886999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it 2896999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * from scratch. 2906999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders. 2916999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2926999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void) 2936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{ 2946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.codeCacheFull) { 2956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng resetCodeCache(); 2966999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } 2976999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmCompilerPatchInlineCache(); 29860c24f436d603c564d5351a6f81821f12635733cBen Cheng} 29960c24f436d603c564d5351a6f81821f12635733cBen Cheng 300964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeebool compilerThreadStartup(void) 301964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{ 302964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee JitEntry *pJitTable = NULL; 303964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned char *pJitProfTable = NULL; 304964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned int i; 305964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 306964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerArchInit()) 307964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 308964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 309964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 310964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Setup the code cache if we have not inherited a valid code cache 311964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * from the zygote. 312964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 313964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCache == NULL) { 314964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerSetupCodeCache()) 315964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 316964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 317964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 318964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Allocate the initial arena block */ 319964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmCompilerHeapInit() == false) { 320964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 321964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 322964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 323964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 324964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 3251357e94efecd485bda933270a9181035f6a39e09Ben Cheng#if defined(WITH_JIT_TUNING) 326964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Track method-level compilation statistics */ 327964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 3281357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif 329964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 330964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Set up the JitTable */ 333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Power of 2? */ 335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(gDvmJit.jitTableSize && 336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1))); 337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmInitMutex(&gDvmJit.tableLock); 339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.tableLock); 340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable = (JitEntry*) 341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee calloc(gDvmJit.jitTableSize, sizeof(*pJitTable)); 342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitTable) { 343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit table allocation failed\n"); 344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 347964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * NOTE: the profile table must only be allocated once, globally. 349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Profiling is turned on and off by nulling out gDvm.pJitProfTable 350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and then restoring its original value. However, this action 351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is not syncronized for speed so threads may continue to hold 352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and update the profile table after profiling has been turned 353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * off by null'ng the global pointer. Be aware. 354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE); 356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitProfTable) { 357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit prof table allocation failed\n"); 358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 360964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 361964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE); 362964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee for (i=0; i < gDvmJit.jitTableSize; i++) { 363964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable[i].u.info.chain = gDvmJit.jitTableSize; 364964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 365964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Is chain field wide enough for termination pattern? */ 366964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize); 367964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 368964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pJitEntryTable = pJitTable; 369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1; 370964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableEntriesUsed = 0; 371964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.compilerHighWater = 372964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 373964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pProfTable = pJitProfTable; 37406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTableCopy = pJitProfTable; 375964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 376964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 377964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Signal running threads to refresh their cached pJitTable pointers */ 378964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); 379964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmResumeAllThreads(SUSPEND_FOR_REFRESH); 380964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return true; 381964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 382964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail: 383964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; 384964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 385964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee} 386964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 387ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 388ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 38994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee int ret; 39094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee struct timespec ts; 39194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 3925ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 3935ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 394b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 395eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * If we're not running stand-alone, wait a little before 396eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * recieving translation requests on the assumption that process start 397eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * up code isn't worth compiling. We'll resume when the framework 398eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * signals us that the first screen draw has happened, or the timer 399eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * below expires (to catch daemons). 400f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 401f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * There is a theoretical race between the callback to 402f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * VMRuntime.startJitCompiation and when the compiler thread reaches this 403f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * point. In case the callback happens earlier, in order not to permanently 404f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * hold the system_server (which is not using the timed wait) in 405f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * interpreter-only mode we bypass the delay here. 406b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 407f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvmJit.runningInAndroidFramework && 408f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng !gDvmJit.alreadyEnabledViaFramework) { 409f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 410f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the current VM instance is the system server (detected by having 411f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 0 in gDvm.systemServerPid), we will use the indefinite wait on the 412f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * conditional variable to determine whether to start the JIT or not. 413f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the system server detects that the whole system is booted in 414f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * safe mode, the conditional variable will never be signaled and the 415f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * system server will remain in the interpreter-only mode. All 416f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * subsequent apps will be started with the --enable-safemode flag 417f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * explicitly appended. 418f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 419f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvm.systemServerPid == 0) { 420f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 421f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 422f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock); 423f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 424f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng LOGD("JIT started for system_server"); 425f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } else { 426f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 427f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 428f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * TUNING: experiment with the delay & perhaps make it 429f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * target-specific 430f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 431f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmRelativeCondWait(&gDvmJit.compilerQueueActivity, 432f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock, 3000, 0); 433f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 434f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } 435eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee if (gDvmJit.haltCompilerThread) { 436eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee return NULL; 437eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee } 43894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee } 43994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 440964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStartup(); 441b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 442ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 443ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 444ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 445ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 446ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 447ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 448ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 449ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 450ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 451ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 452ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 453ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 454ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 455ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 456ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 457ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 458ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 459ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 46086717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#if defined(JIT_STATS) 46186717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 46286717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 463964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 464964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Check whether there is a suspend request on me. This 465964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is necessary to allow a clean shutdown. 466964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 467ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmCheckSuspendPending(NULL); 4682717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 4692717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 4702717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 4716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng bool resizeFail = 4726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 4736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 4746999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * If the jit table is full, consider it's time to reset 4756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * the code cache too. 4766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 4776999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull |= resizeFail; 4782717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 479ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 480ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 4816999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } else if (!gDvmJit.codeCacheFull) { 482fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee bool compileOK = false; 483fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee jmp_buf jmpBuf; 484fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee work.bailPtr = &jmpBuf; 485fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee bool aborted = setjmp(jmpBuf); 486fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee if (!aborted) { 487fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee compileOK = dvmCompilerDoWork(&work); 488ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 489fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee if (aborted || !compileOK) { 490fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee dvmCompilerArenaReset(); 491fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee work.result.codeAddress = gDvmJit.interpretTemplate; 492fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee } else if (!work.result.discardResult) { 49360c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 49460c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 49560c24f436d603c564d5351a6f81821f12635733cBen Cheng } 496ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 497ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 49886717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#if defined(JIT_STATS) 49986717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime; 50086717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 501ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 502ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 503ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 504ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 505ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 506ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 507ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 5085ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 5095ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 5105ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 5115ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 5125ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 5135ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 5145ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 51543eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden if (gDvm.verboseShutdown) 51643eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden LOGD("Compiler thread shutting down\n"); 517ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 518ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 519ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 520ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 521ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 52294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 52394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmInitMutex(&gDvmJit.compilerLock); 5246999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmInitMutex(&gDvmJit.compilerICPatchLock); 52594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 52694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 52794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 52894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 52994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* Reset the work queue */ 53094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 53194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerQueueLength = 0; 53294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 53394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 534ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 53594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * Defer rest of initialization until we're sure JIT'ng makes sense. Launch 536964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * the compiler thread, which will do the real initialization if and 537964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * when it is signalled to do so. 538ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 539964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 540964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStart, NULL); 541ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 542ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 543ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 544ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 545ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 546ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 54788a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng if (gDvm.verboseShutdown) { 54888a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng dvmCompilerDumpStats(); 54988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng while (gDvmJit.compilerQueueLength) 55088a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng sleep(5); 55188a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng } 55288a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng 553ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 554ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 555ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 556ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 557ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 558ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 559ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 560ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 561ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 562ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 56343eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden else if (gDvm.verboseShutdown) 564ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 565ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 56606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 56796cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee dvmDestroyMutex(&gDvmJit.tableLock); 56896cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee dvmDestroyMutex(&gDvmJit.compilerLock); 56996cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee dvmDestroyMutex(&gDvmJit.compilerICPatchLock); 57096cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee 57196cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee if (gDvmJit.pJitEntryTable) { 57296cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee free(gDvmJit.pJitEntryTable); 57396cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee gDvmJit.pJitEntryTable = NULL; 57496cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee } 57596cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee 57696cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee if (gDvmJit.pProfTable) { 57796cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee free(gDvmJit.pProfTable); 57896cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee gDvmJit.pProfTable = NULL; 57996cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee } 58096cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee 58196cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee} 58206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 58306bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh() 58406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{ 58506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActive; 58606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActivate; 5873e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee bool needUnchain = false; 58806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 58906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmLockMutex(&gDvmJit.tableLock); 59006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActive = gDvmJit.pProfTable != NULL; 59106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0)); 59206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 59306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee if (jitActivate && !jitActive) { 59406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = gDvmJit.pProfTableCopy; 59506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } else if (!jitActivate && jitActive) { 59606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = NULL; 5973e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee needUnchain = true; 59806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } 5993e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 6003e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee if (needUnchain) 6013e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmJitUnchainAll(); 60206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee} 603