Compiler.cpp revision fc75f3ed87b55d625b6054e18645da5cbdba31c6
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) { 43b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro dvmSignalCond(&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; 987a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng newOrder->result.methodCompilationAborted = NULL; 99ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 100ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 1011f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee (kind == kWorkOrderTraceDebug) ? true : false; 10233672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 10333672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 111964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit: 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 11360c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 11611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng/* Block until the queue length is 0, or there is a pending suspend request */ 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 11911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng Thread *self = dvmThreadSelf(); 12011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng 121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 12211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread && 12311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng self->suspendCount == 0) { 124812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng /* 125812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * Use timed wait here - more than one mutator threads may be blocked 126812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * but the compiler thread will only signal once when the queue is 127812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * emptied. Furthermore, the compiler thread may have been shutdown 128812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * so the blocked thread may never get the wakeup signal. 129812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng */ 130812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock, 1000, 0); 131ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 132ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 133ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 134ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 13560c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 13660c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 13760c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 13860c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 1397c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng int fd; 14060c24f436d603c564d5351a6f81821f12635733cBen Cheng 14160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 1427c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize); 1437c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng if (fd < 0) { 1447c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng LOGE("Could not create %u-byte ashmem region for the JIT code cache", 1457c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCacheSize); 1467c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng return false; 1477c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng } 1487c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize, 1497c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 1507c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng MAP_PRIVATE , fd, 0); 1517c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng close(fd); 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 1537c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng LOGE("Failed to mmap the JIT code cache: %s\n", strerror(errno)); 15460c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 15560c24f436d603c564d5351a6f81821f12635733cBen Cheng } 15660c24f436d603c564d5351a6f81821f12635733cBen Cheng 157b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng gDvmJit.pageSizeMask = getpagesize() - 1; 158b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 1597c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */ 1607c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng // LOGD("Code cache starts at %p", gDvmJit.codeCache); 1617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 16260c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 16360c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 16460c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 16560c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 16660c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 16760c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 16860c24f436d603c564d5351a6f81821f12635733cBen Cheng 16972621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng /* 17072621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng * Work around a CPU bug by keeping the 32-bit ARM handler code in its own 17172621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng * page. 17272621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng */ 17372621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) { 17472621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng templateSize = (templateSize + 4095) & ~4095; 17572621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng } 17672621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng 17760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 17860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 17960c24f436d603c564d5351a6f81821f12635733cBen Cheng 18060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 18160c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 18260c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 183b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 1841f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng int result = mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize, 1851f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng PROTECT_CODE_CACHE_ATTRS); 1861f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng 1871f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng if (result == -1) { 1881f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng LOGE("Failed to remove the write permission for the code cache"); 1891f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng dvmAbort(); 1901f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng } 191b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 19260c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 19360c24f436d603c564d5351a6f81821f12635733cBen Cheng} 19460c24f436d603c564d5351a6f81821f12635733cBen Cheng 1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng void *fp = thread->curFrame; 1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 1997a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 2047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2077a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 2087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 2097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 2107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 212fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)fp)) { 2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: break frame (%p)", 2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: %s.%s%s (%p)", 2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 2237a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 2347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 2357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 23660c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 23760c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 23860c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 2397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 2407a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 2416999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng int byteUsed = gDvmJit.codeCacheByteUsed; 24260c24f436d603c564d5351a6f81821f12635733cBen Cheng 2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* If any thread is found stuck in the JIT state, don't reset the cache */ 24460c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2456999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 2466999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Crawl the stack to wipe out the returnAddr field so that 2476999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) the soon-to-be-deleted code in the JIT cache won't be used 2486999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) or the thread stuck in the JIT land will soon return 2496999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * to the interpreter land 2506999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2516999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng crawlDalvikStack(thread, false); 2527a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 25660c24f436d603c564d5351a6f81821f12635733cBen Cheng 2577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 2586999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset delayed (%d bytes %d/%d)", 2596999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset, 2606999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng ++gDvmJit.numCodeCacheResetDelayed); 2616999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng return; 2627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2646999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Lock the mutex to clean up the work queue */ 2656999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 2666999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 2676999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Drain the work queue to free the work orders */ 2687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 2697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 2707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 2717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 27360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 27460c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 27560c24f436d603c564d5351a6f81821f12635733cBen Cheng 276b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 27760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 27860c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 27960c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 28060c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 2817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng memset((char *) gDvmJit.codeCache + gDvmJit.templateSize, 2827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 0, 2837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 28460c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 28560c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 28660c24f436d603c564d5351a6f81821f12635733cBen Cheng 287b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 288b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 28960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 29060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 29160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 29260c24f436d603c564d5351a6f81821f12635733cBen Cheng 29360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 29460c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 29560c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 29660c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 29760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 29860c24f436d603c564d5351a6f81821f12635733cBen Cheng 2996999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Reset the IC patch work queue */ 3006999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerICPatchLock); 3016999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.compilerICPatchIndex = 0; 3026999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 3036999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 30460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 30560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 30660c24f436d603c564d5351a6f81821f12635733cBen Cheng 3076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 3087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 3096999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng LOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)", 3106999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng (dvmGetRelativeTimeUsec() - startTime) / 1000, 3116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng byteUsed, ++gDvmJit.numCodeCacheReset, 3126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.numCodeCacheResetDelayed); 3136999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng} 3146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 3156999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/* 3166999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently 3176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do: 3186999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it 3196999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * from scratch. 3206999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders. 3216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 3226999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void) 3236999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{ 3246999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.codeCacheFull) { 3256999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng resetCodeCache(); 3266999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } 3276999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmCompilerPatchInlineCache(); 32860c24f436d603c564d5351a6f81821f12635733cBen Cheng} 32960c24f436d603c564d5351a6f81821f12635733cBen Cheng 330953a0ed4e507fd6e756aa3e5c671bee80d7e9b3eAndy McFaddenstatic bool compilerThreadStartup(void) 331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{ 332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee JitEntry *pJitTable = NULL; 333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned char *pJitProfTable = NULL; 334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned int i; 335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerArchInit()) 337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Setup the code cache if we have not inherited a valid code cache 341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * from the zygote. 342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCache == NULL) { 344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerSetupCodeCache()) 345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 347964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Allocate the initial arena block */ 349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmCompilerHeapInit() == false) { 350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Track method-level compilation statistics */ 356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 3577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING) 359452efba773098c070c6bd623124e1fed21342ba4Ben Cheng gDvm.verboseShutdown = true; 3601357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif 361964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 362964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 363964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 364964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Set up the JitTable */ 365964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 366964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Power of 2? */ 367964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(gDvmJit.jitTableSize && 368964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1))); 369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 370964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmInitMutex(&gDvmJit.tableLock); 371964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.tableLock); 372964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable = (JitEntry*) 373964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee calloc(gDvmJit.jitTableSize, sizeof(*pJitTable)); 374964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitTable) { 375964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit table allocation failed\n"); 376964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 377964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 378964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 379964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 380964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * NOTE: the profile table must only be allocated once, globally. 381964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Profiling is turned on and off by nulling out gDvm.pJitProfTable 382964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and then restoring its original value. However, this action 383964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is not syncronized for speed so threads may continue to hold 384964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and update the profile table after profiling has been turned 385964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * off by null'ng the global pointer. Be aware. 386964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 387964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE); 388964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitProfTable) { 389964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee LOGE("jit prof table allocation failed\n"); 390964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 391964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 392964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 393964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE); 394964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee for (i=0; i < gDvmJit.jitTableSize; i++) { 395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable[i].u.info.chain = gDvmJit.jitTableSize; 396964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 397964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Is chain field wide enough for termination pattern? */ 398964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize); 399964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 400964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pJitEntryTable = pJitTable; 401964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1; 402964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableEntriesUsed = 0; 403964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.compilerHighWater = 404964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 405a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng /* 406a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * If the VM is launched with wait-on-the-debugger, we will need to hide 407a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * the profile table here 408a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng */ 409a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable; 41006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTableCopy = pJitProfTable; 411964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 412964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 413964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Signal running threads to refresh their cached pJitTable pointers */ 414964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); 415964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmResumeAllThreads(SUSPEND_FOR_REFRESH); 416dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 417dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* Enable signature breakpoints by customizing the following code */ 418dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#if defined(SIGNATURE_BREAKPOINT) 419dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* 420dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Suppose one sees the following native crash in the bugreport: 421dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): Build fingerprint: 'unknown' 422dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): pid: 2468, tid: 2507 >>> com.google.android.gallery3d 423dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): signal 11 (SIGSEGV), fault addr 00001400 424dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r0 44ea7190 r1 44e4f7b8 r2 44ebc710 r3 00000000 425dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r4 00000a00 r5 41862dec r6 4710dc10 r7 00000280 426dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r8 ad010f40 r9 46a37a12 10 001116b0 fp 42a78208 427dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): ip 00000090 sp 4710dbc8 lr ad060e67 pc 46b90682 428dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * cpsr 00000030 429dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): #00 pc 46b90682 /dev/ashmem/dalvik-jit-code-cache 430dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): #01 pc 00060e62 /system/lib/libdvm.so 431dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 432dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): code around pc: 433dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68 434dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e 435dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028 436dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b 437dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70 438dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 439dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Clearly it is a JIT bug. To find out which translation contains the 440dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * offending code, the content of the memory dump around the faulting PC 441dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time 442dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * when a similar compilation is being created, the JIT compiler replay the 443dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * trace in the verbose mode and one can investigate the instruction 444dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * sequence in details. 445dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 446dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The length of the signature may need additional experiments to determine. 447dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The rule of thumb is don't include PC-relative instructions in the 448dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * signature since it may be affected by the alignment of the compiled code. 449dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * However, a signature that's too short might increase the chance of false 450dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * positive matches. Using gdbjithelper to disassembly the memory content 451dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * first might be a good companion approach. 452dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 453dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * For example, if the next 4 words starting from 46b90680 is pasted into 454dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * the data structure: 455dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng */ 456dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 457dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpointSize = 4; 458dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint = 459dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize); 460dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[0] = 0x512000bc; 461dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[1] = 0x37016eaf; 462dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[2] = 0x6ea866af; 463dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[3] = 0x6f696028; 464dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 465dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* 466dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The following log will be printed when a match is found in subsequent 467dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * testings: 468dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 469dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words) 470dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- 471dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems, 472dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * offset 0x1f7 473dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26 474dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42 475dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0) 476dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1) 477dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0) 478dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0) 479dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0) 480dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10) 481dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624 482dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8 483dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * blocks 484dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * : 485dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * : 486dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x20 (0020): ldr r0, [r5, #52] 487dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x22 (0022): ldr r2, [pc, #96] 488dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x24 (0024): cmp r0, #0 489dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x26 (0026): beq 0x00000034 490dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x28 (0028): ldr r1, [r1, #0] 491dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2a (002a): ldr r0, [r0, #0] 492dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2c (002c): blx r2 493dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2e (002e): cmp r0, #0 494dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x30 (0030): beq 0x00000050 495dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x32 (0032): ldr r0, [r5, #52] 496dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x34 (0034): lsls r4, r7, #2 497dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x36 (0036): str r0, [r4, r4] 498dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0) 499dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): L0x0195: 500dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26, 501dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * v26, (#1) 502dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x38 (0038): ldr r7, [r5, #104] 503dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3a (003a): adds r7, r7, #1 504dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3c (003c): str r7, [r5, #104] 505dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0) 506dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): L0x0165: 507dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26, 508dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * (#0) 509dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3e (003e): ldr r0, [r5, #104] 510dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x40 (0040): str r0, [r5, #0] 511dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 512dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The "str r0, [r4, r4]" is indeed the culprit of the native crash. 513dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng */ 514dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#endif 515dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 516964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return true; 517964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 518964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail: 519964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; 520964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 521964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee} 522964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 523ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 524ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 5255ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 5265ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 527b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 528eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * If we're not running stand-alone, wait a little before 529eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * recieving translation requests on the assumption that process start 530eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * up code isn't worth compiling. We'll resume when the framework 531eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * signals us that the first screen draw has happened, or the timer 532eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * below expires (to catch daemons). 533f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 534f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * There is a theoretical race between the callback to 535f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * VMRuntime.startJitCompiation and when the compiler thread reaches this 536f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * point. In case the callback happens earlier, in order not to permanently 537f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * hold the system_server (which is not using the timed wait) in 538f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * interpreter-only mode we bypass the delay here. 539b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 540f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvmJit.runningInAndroidFramework && 541f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng !gDvmJit.alreadyEnabledViaFramework) { 542f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 543f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the current VM instance is the system server (detected by having 544f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 0 in gDvm.systemServerPid), we will use the indefinite wait on the 545f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * conditional variable to determine whether to start the JIT or not. 546f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the system server detects that the whole system is booted in 547f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * safe mode, the conditional variable will never be signaled and the 548f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * system server will remain in the interpreter-only mode. All 549f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * subsequent apps will be started with the --enable-safemode flag 550f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * explicitly appended. 551f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 552f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvm.systemServerPid == 0) { 553f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 554f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 555f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock); 556f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 557f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng LOGD("JIT started for system_server"); 558f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } else { 559f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 560f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 561f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * TUNING: experiment with the delay & perhaps make it 562f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * target-specific 563f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 564f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmRelativeCondWait(&gDvmJit.compilerQueueActivity, 565f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock, 3000, 0); 566f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 567f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } 568eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee if (gDvmJit.haltCompilerThread) { 569eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee return NULL; 570eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee } 57194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee } 57294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 573964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStartup(); 574b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 575ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 576ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 577ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 578ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 579ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 580ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 581ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 582ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 583ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 584ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 585ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 586ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 587ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 588ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 589ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 590ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 591ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 592ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 593978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING) 59486717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 59586717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 596964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 597964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Check whether there is a suspend request on me. This 598964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is necessary to allow a clean shutdown. 59911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * 60011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * However, in the blocking stress testing mode, let the 60111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * compiler thread continue doing compilations to unblock 60211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * other requesting threads. This may occasionally cause 60311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * shutdown from proceeding cleanly in the standalone invocation 60411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * of the vm but this should be acceptable. 605964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 60611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng if (!gDvmJit.blockingMode) 607ab227f7a9a9d4c7837ee7a5cc9f07b665d516bacAndy McFadden dvmCheckSuspendPending(dvmThreadSelf()); 6082717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 6092717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 6102717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 6116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng bool resizeFail = 6126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 6136999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 6146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * If the jit table is full, consider it's time to reset 6156999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * the code cache too. 6166999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 6176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull |= resizeFail; 6182717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 619ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 620ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 6216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } else if (!gDvmJit.codeCacheFull) { 622fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee bool compileOK = false; 623fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee jmp_buf jmpBuf; 624fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee work.bailPtr = &jmpBuf; 625fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee bool aborted = setjmp(jmpBuf); 626fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee if (!aborted) { 627fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee compileOK = dvmCompilerDoWork(&work); 628ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 629fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee if (aborted || !compileOK) { 630fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee dvmCompilerArenaReset(); 6317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } else if (!work.result.discardResult && 6327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng work.result.codeAddress) { 6337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* Make sure that proper code addr is installed */ 6347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng assert(work.result.codeAddress != NULL); 63560c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 63660c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 63760c24f436d603c564d5351a6f81821f12635733cBen Cheng } 638ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 639ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 640978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING) 64186717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime; 64286717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 643ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 644ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 645ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 646ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 647ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 648ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 649ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 6505ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 6515ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 6525ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 6535ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 6545ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 6555ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 6565ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 65743eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden if (gDvm.verboseShutdown) 65843eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden LOGD("Compiler thread shutting down\n"); 659ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 660ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 661ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 662ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 663ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 66494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 66594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmInitMutex(&gDvmJit.compilerLock); 6666999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmInitMutex(&gDvmJit.compilerICPatchLock); 667b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng dvmInitMutex(&gDvmJit.codeCacheProtectionLock); 66894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 66994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 67094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 67194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 67294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* Reset the work queue */ 67394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 67494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerQueueLength = 0; 67594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 67694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 677ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 67894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * Defer rest of initialization until we're sure JIT'ng makes sense. Launch 679964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * the compiler thread, which will do the real initialization if and 680964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * when it is signalled to do so. 681ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 682964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 683964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStart, NULL); 684ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 685ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 686ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 687ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 688ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 689ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 6902fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* Disable new translation requests */ 6912fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee gDvmJit.pProfTable = NULL; 6922fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee gDvmJit.pProfTableCopy = NULL; 6932fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee 69488a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng if (gDvm.verboseShutdown) { 69588a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng dvmCompilerDumpStats(); 69688a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng while (gDvmJit.compilerQueueLength) 69788a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng sleep(5); 69888a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng } 69988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng 700ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 701ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 702ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 703ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 704ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 705ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 706ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 707ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 708ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 709ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 71043eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden else if (gDvm.verboseShutdown) 711ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 712ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 71306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 7142fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* Break loops within the translation cache */ 7152fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee dvmJitUnchainAll(); 71696cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee 7172fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* 7182fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * NOTE: our current implementatation doesn't allow for the compiler 7192fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * thread to be restarted after it exits here. We aren't freeing 7202fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * the JitTable or the ProfTable because threads which still may be 7212fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * running or in the process of shutting down may hold references to 7222fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * them. 7232fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee */ 72496cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee} 72506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 72606bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh() 72706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{ 72806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActive; 72906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActivate; 7303e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee bool needUnchain = false; 73106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 732a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng /* 733a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * The tableLock might not be initialized yet by the compiler thread if 734a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * debugger is attached from the very beginning of the VM launch. If 735a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * pProfTableCopy is NULL, the lock is not initialized yet and we don't 736a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * need to refresh anything either. 737a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng */ 738a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng if (gDvmJit.pProfTableCopy == NULL) { 739a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng return; 740a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng } 741a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng 74206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmLockMutex(&gDvmJit.tableLock); 74306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActive = gDvmJit.pProfTable != NULL; 7445cc61d70ec727aa22f58463bf7940cc717cf3eb1Ben Cheng bool disableJit = gDvm.debuggerActive; 7455cc61d70ec727aa22f58463bf7940cc717cf3eb1Ben Cheng#if !defined(WITH_INLINE_PROFILING) 7465cc61d70ec727aa22f58463bf7940cc717cf3eb1Ben Cheng disableJit = disableJit || (gDvm.activeProfilers > 0); 7475cc61d70ec727aa22f58463bf7940cc717cf3eb1Ben Cheng#endif 7485cc61d70ec727aa22f58463bf7940cc717cf3eb1Ben Cheng jitActivate = !disableJit; 74906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 75006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee if (jitActivate && !jitActive) { 75106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = gDvmJit.pProfTableCopy; 75206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } else if (!jitActivate && jitActive) { 75306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = NULL; 7543e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee needUnchain = true; 75506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } 7563e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 7573e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee if (needUnchain) 7583e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmJitUnchainAll(); 75906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee} 760