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" 240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef ARCH_IA32 250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "codegen/x86/Translator.h" 260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "codegen/x86/Lower.h" 270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 295d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiroextern "C" void dvmCompilerTemplateStart(void); 30d585beda3690b8b5b978e3c59af224336614ba72Yanchuan Nianextern "C" void dvmCompilerTemplateEnd(void); 315d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro 32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void) 33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return gDvmJit.compilerQueueLength; 35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void) 38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind 40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng != kWorkOrderInvalid); 41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = 42ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex]; 43ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind = 44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng kWorkOrderInvalid; 45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) { 46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkDequeueIndex = 0; 47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength--; 49f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee if (gDvmJit.compilerQueueLength == 0) { 50b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro dvmSignalCond(&gDvmJit.compilerQueueEmpty); 51f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee } 52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 53ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Remember the high water mark of the queue length */ 54ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued) 55ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength; 56ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 57ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return work; 58ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 601b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee/* 611b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * Enqueue a work order - retrying until successful. If attempt to enqueue 621b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * is repeatedly unsuccessful, assume the JIT is in a bad state and force a 631b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * code cache reset. 641b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee */ 651b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee#define ENQUEUE_MAX_RETRIES 20 661b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbeevoid dvmCompilerForceWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 671b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee{ 681b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee bool success; 691b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee int retries = 0; 701b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee do { 711b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee success = dvmCompilerWorkEnqueue(pc, kind, info); 721b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee if (!success) { 731b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee retries++; 741b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee if (retries > ENQUEUE_MAX_RETRIES) { 75c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("JIT: compiler queue wedged - forcing reset"); 761b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee gDvmJit.codeCacheFull = true; // Force reset 771b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee success = true; // Because we'll drop the order now anyway 781b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee } else { 791b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 801b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee pthread_cond_wait(&gDvmJit.compilerQueueActivity, 811b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee &gDvmJit.compilerLock); 821b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 831b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee 841b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee } 851b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee } 861b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee } while (!success); 871b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee} 881b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee 89964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/* 90964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful. 911357e94efecd485bda933270a9181035f6a39e09Ben Cheng * 921357e94efecd485bda933270a9181035f6a39e09Ben Cheng * NOTE: Make sure that the caller frees the info pointer if the return value 931357e94efecd485bda933270a9181035f6a39e09Ben Cheng * is false. 94964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 95ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 98ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int i; 99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int numWork; 10060c24f436d603c564d5351a6f81821f12635733cBen Cheng bool result = true; 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 1021b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 1047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 1056999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Return if queue or code cache is full. 1067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 1076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE || 1086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull == true) { 1095d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro dvmUnlockMutex(&gDvmJit.compilerLock); 1105d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro return false; 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 1185d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro if (gDvmJit.compilerWorkQueue[i++].pc == pc) { 1195d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro dvmUnlockMutex(&gDvmJit.compilerLock); 1205d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro return true; 1215d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro } 122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 125ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 126ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 127ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 128ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 129ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 130ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 131ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 1327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng newOrder->result.methodCompilationAborted = NULL; 133ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 134ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 1351f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee (kind == kWorkOrderTraceDebug) ? true : false; 13618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee newOrder->result.cacheVersion = gDvmJit.cacheVersion; 13733672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 13833672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 139ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 140ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 141ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 142ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 143ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 144ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 145ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 146ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 14760c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 149ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 15011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng/* Block until the queue length is 0, or there is a pending suspend request */ 151ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 152ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 15311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng Thread *self = dvmThreadSelf(); 15411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng 155ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 15611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread && 157389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee self->suspendCount == 0) { 158812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng /* 159812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * Use timed wait here - more than one mutator threads may be blocked 160812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * but the compiler thread will only signal once when the queue is 161812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * emptied. Furthermore, the compiler thread may have been shutdown 162812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng * so the blocked thread may never get the wakeup signal. 163812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng */ 164812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock, 1000, 0); 165ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 166ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 167ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 168ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 16960c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 17060c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 1717c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng int fd; 17260c24f436d603c564d5351a6f81821f12635733cBen Cheng 17360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 1747c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize); 1757c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng if (fd < 0) { 176c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Could not create %u-byte ashmem region for the JIT code cache", 1777c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCacheSize); 1787c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng return false; 1797c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng } 1807c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize, 1817c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 1827c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng MAP_PRIVATE , fd, 0); 1837c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng close(fd); 18460c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 185bbbe552a31f7229708bfc748480ce538218ae076buzbee ALOGE("Failed to mmap the JIT code cache of size %d: %s", gDvmJit.codeCacheSize, strerror(errno)); 18660c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 18760c24f436d603c564d5351a6f81821f12635733cBen Cheng } 18860c24f436d603c564d5351a6f81821f12635733cBen Cheng 189b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng gDvmJit.pageSizeMask = getpagesize() - 1; 190b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 1917c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */ 192062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block // ALOGD("Code cache starts at %p", gDvmJit.codeCache); 1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifndef ARCH_IA32 19560c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 196d585beda3690b8b5b978e3c59af224336614ba72Yanchuan Nian int templateSize = (intptr_t) dvmCompilerTemplateEnd - 19760c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 19860c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 19960c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 20060c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 20160c24f436d603c564d5351a6f81821f12635733cBen Cheng 20272621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng /* 20372621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng * Work around a CPU bug by keeping the 32-bit ARM handler code in its own 20472621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng * page. 20572621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng */ 20672621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) { 20772621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng templateSize = (templateSize + 4095) & ~4095; 20872621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng } 20972621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng 21060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 21160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 21260c24f436d603c564d5351a6f81821f12635733cBen Cheng 21360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 21413fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache, 21513fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee (intptr_t) gDvmJit.codeCache + templateSize, 0); 2160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 2170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.codeCacheByteUsed = 0; 2180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream = (char*)gDvmJit.codeCache + gDvmJit.codeCacheByteUsed; 2190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGV("codeCache = %p stream = %p before initJIT", gDvmJit.codeCache, stream); 2200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen streamStart = stream; 2210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen initJIT(NULL, NULL); 2220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.templateSize = (stream - streamStart); 2230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.codeCacheByteUsed = (stream - streamStart); 2240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGV("stream = %p after initJIT", stream); 2250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 226b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 2279cf04e3569d48dae36e0492226250da04699f8d4Jun Tian int result = mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize, 2289cf04e3569d48dae36e0492226250da04699f8d4Jun Tian PROTECT_CODE_CACHE_ATTRS); 2299cf04e3569d48dae36e0492226250da04699f8d4Jun Tian 2309cf04e3569d48dae36e0492226250da04699f8d4Jun Tian if (result == -1) { 2319cf04e3569d48dae36e0492226250da04699f8d4Jun Tian ALOGE("Failed to remove the write permission for the code cache"); 2329cf04e3569d48dae36e0492226250da04699f8d4Jun Tian dvmAbort(); 2339cf04e3569d48dae36e0492226250da04699f8d4Jun Tian } 2349cf04e3569d48dae36e0492226250da04699f8d4Jun Tian 23560c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 23660c24f436d603c564d5351a6f81821f12635733cBen Cheng} 23760c24f436d603c564d5351a6f81821f12635733cBen Cheng 2387a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 2397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 24030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee void *fp = thread->interpSave.curFrame; 2417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 2427a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2447a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 245062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 2467a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 2477a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 2487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 2497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 2517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 2527a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 2537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 255fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro if (dvmIsBreakFrame((u4*)fp)) { 256062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD(" #%d: break frame (%p)", 2577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 2587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 260062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD(" #%d: %s.%s%s (%p)", 2617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 2627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 2647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 2657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 2667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 2677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 2707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 2717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 2727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 2737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 2757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 2767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 2777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 2787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 27960c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 28060c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 28160c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 2827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 2837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 2846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng int byteUsed = gDvmJit.codeCacheByteUsed; 28560c24f436d603c564d5351a6f81821f12635733cBen Cheng 2865867bea193779ff3009738513bae9bc84f4a34aabuzbee /* If any thread is found stuck in the JIT state, don't reset the cache */ 2875867bea193779ff3009738513bae9bc84f4a34aabuzbee dvmLockThreadList(NULL); 28860c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2896999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 2906999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Crawl the stack to wipe out the returnAddr field so that 2916999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) the soon-to-be-deleted code in the JIT cache won't be used 2926999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) or the thread stuck in the JIT land will soon return 2936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * to the interpreter land 2946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 2956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng crawlDalvikStack(thread, false); 2967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2995867bea193779ff3009738513bae9bc84f4a34aabuzbee /* Cancel any ongoing trace selection */ 300cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee dvmDisableSubMode(thread, kSubModeJitTraceBuild); 3017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 3025867bea193779ff3009738513bae9bc84f4a34aabuzbee dvmUnlockThreadList(); 30360c24f436d603c564d5351a6f81821f12635733cBen Cheng 3047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 305062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("JIT code cache reset delayed (%d bytes %d/%d)", 3066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset, 3076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng ++gDvmJit.numCodeCacheResetDelayed); 3086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng return; 3097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 3107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 3116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Lock the mutex to clean up the work queue */ 3126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 3136999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 31418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee /* Update the translation cache version */ 31518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee gDvmJit.cacheVersion++; 31618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee 3176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Drain the work queue to free the work orders */ 3187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 3197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 3207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 3217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 3227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 32360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 32460c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 32560c24f436d603c564d5351a6f81821f12635733cBen Cheng 326b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 32760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 32860c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 32960c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 33060c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 331a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmCompilerCacheClear((char *) gDvmJit.codeCache + gDvmJit.templateSize, 332a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 333a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 33413fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache, 33513fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee (intptr_t) gDvmJit.codeCache + 33613fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee gDvmJit.codeCacheByteUsed, 0); 33760c24f436d603c564d5351a6f81821f12635733cBen Cheng 338b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); 339b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng 34060c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 34160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 34260c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 34360c24f436d603c564d5351a6f81821f12635733cBen Cheng 34460c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 34560c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 34660c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 34760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 34860c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 34960c24f436d603c564d5351a6f81821f12635733cBen Cheng 3506999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* Reset the IC patch work queue */ 3516999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmLockMutex(&gDvmJit.compilerICPatchLock); 3526999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.compilerICPatchIndex = 0; 3536999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerICPatchLock); 3546999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 355385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng /* 356385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng * Reset the inflight compilation address (can only be done in safe points 357385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng * or by the compiler thread when its thread state is RUNNING). 358385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng */ 359385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng gDvmJit.inflightBaseAddr = NULL; 360385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng 36160c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 36260c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 36360c24f436d603c564d5351a6f81821f12635733cBen Cheng 3646999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 3657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 366062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)", 3676999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng (dvmGetRelativeTimeUsec() - startTime) / 1000, 3686999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng byteUsed, ++gDvmJit.numCodeCacheReset, 3696999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.numCodeCacheResetDelayed); 3706999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng} 3716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng 3726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/* 3736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently 3746999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do: 3756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it 3766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * from scratch. 3776999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders. 3786999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 3796999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void) 3806999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{ 3816999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng if (gDvmJit.codeCacheFull) { 3826999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng resetCodeCache(); 3836999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } 3846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmCompilerPatchInlineCache(); 38560c24f436d603c564d5351a6f81821f12635733cBen Cheng} 38660c24f436d603c564d5351a6f81821f12635733cBen Cheng 387953a0ed4e507fd6e756aa3e5c671bee80d7e9b3eAndy McFaddenstatic bool compilerThreadStartup(void) 388964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{ 389964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee JitEntry *pJitTable = NULL; 390964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned char *pJitProfTable = NULL; 3912e152baec01433de9c63633ebc6f4adf1cea3a87buzbee JitTraceProfCounters *pJitTraceProfCounters = NULL; 392964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee unsigned int i; 393964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 394964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerArchInit()) 395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 396964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 397964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 398964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Setup the code cache if we have not inherited a valid code cache 399964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * from the zygote. 400964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 401964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (gDvmJit.codeCache == NULL) { 402964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!dvmCompilerSetupCodeCache()) 403964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 404964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 405964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 406964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Allocate the initial arena block */ 407964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (dvmCompilerHeapInit() == false) { 408964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 409964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 410964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 411385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng /* Cache the thread pointer */ 412385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng gDvmJit.compilerThread = dvmThreadSelf(); 413385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng 414964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 415964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 416964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Track method-level compilation statistics */ 417964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 4187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 4197a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING) 420452efba773098c070c6bd623124e1fed21342ba4Ben Cheng gDvm.verboseShutdown = true; 4211357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif 422964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 423964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 424964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 425964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Set up the JitTable */ 426964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 427964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Power of 2? */ 428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(gDvmJit.jitTableSize && 429964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1))); 430964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 431964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmInitMutex(&gDvmJit.tableLock); 432964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmLockMutex(&gDvmJit.tableLock); 433964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable = (JitEntry*) 434964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee calloc(gDvmJit.jitTableSize, sizeof(*pJitTable)); 435964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitTable) { 436c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("jit table allocation failed"); 437964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 438964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 439964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 440964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 441964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * NOTE: the profile table must only be allocated once, globally. 442964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Profiling is turned on and off by nulling out gDvm.pJitProfTable 443964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and then restoring its original value. However, this action 4449a3147c7412f4794434b4c2604aa2ba784867774buzbee * is not synchronized for speed so threads may continue to hold 445964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * and update the profile table after profiling has been turned 446964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * off by null'ng the global pointer. Be aware. 447964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 448964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE); 449964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee if (!pJitProfTable) { 450c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("jit prof table allocation failed"); 451e3b363d470aa94e2a8c9df214c658980a6e83122You Kim free(pJitTable); 452964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 453964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee goto fail; 454964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 455964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE); 456964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee for (i=0; i < gDvmJit.jitTableSize; i++) { 457964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee pJitTable[i].u.info.chain = gDvmJit.jitTableSize; 458964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee } 459964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Is chain field wide enough for termination pattern? */ 460964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize); 461964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 4622e152baec01433de9c63633ebc6f4adf1cea3a87buzbee /* Allocate the trace profiling structure */ 4632e152baec01433de9c63633ebc6f4adf1cea3a87buzbee pJitTraceProfCounters = (JitTraceProfCounters*) 4642e152baec01433de9c63633ebc6f4adf1cea3a87buzbee calloc(1, sizeof(*pJitTraceProfCounters)); 4652e152baec01433de9c63633ebc6f4adf1cea3a87buzbee if (!pJitTraceProfCounters) { 466c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("jit trace prof counters allocation failed"); 467e3b363d470aa94e2a8c9df214c658980a6e83122You Kim free(pJitTable); 468e3b363d470aa94e2a8c9df214c658980a6e83122You Kim free(pJitProfTable); 4692e152baec01433de9c63633ebc6f4adf1cea3a87buzbee dvmUnlockMutex(&gDvmJit.tableLock); 4702e152baec01433de9c63633ebc6f4adf1cea3a87buzbee goto fail; 4712e152baec01433de9c63633ebc6f4adf1cea3a87buzbee } 4722e152baec01433de9c63633ebc6f4adf1cea3a87buzbee 473964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.pJitEntryTable = pJitTable; 474964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1; 475964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.jitTableEntriesUsed = 0; 476964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee gDvmJit.compilerHighWater = 477964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 478a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng /* 479a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * If the VM is launched with wait-on-the-debugger, we will need to hide 480a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * the profile table here 481a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng */ 482a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable; 48306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTableCopy = pJitProfTable; 4842e152baec01433de9c63633ebc6f4adf1cea3a87buzbee gDvmJit.pJitTraceProfCounters = pJitTraceProfCounters; 48599e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmJitUpdateThreadStateAll(); 486964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 487964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 488964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* Signal running threads to refresh their cached pJitTable pointers */ 489964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmSuspendAllThreads(SUSPEND_FOR_REFRESH); 490964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee dvmResumeAllThreads(SUSPEND_FOR_REFRESH); 491dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 492dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* Enable signature breakpoints by customizing the following code */ 493dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#if defined(SIGNATURE_BREAKPOINT) 494dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* 495dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Suppose one sees the following native crash in the bugreport: 496dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): Build fingerprint: 'unknown' 497dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): pid: 2468, tid: 2507 >>> com.google.android.gallery3d 498dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): signal 11 (SIGSEGV), fault addr 00001400 499dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r0 44ea7190 r1 44e4f7b8 r2 44ebc710 r3 00000000 500dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r4 00000a00 r5 41862dec r6 4710dc10 r7 00000280 501dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): r8 ad010f40 r9 46a37a12 10 001116b0 fp 42a78208 502dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): ip 00000090 sp 4710dbc8 lr ad060e67 pc 46b90682 503dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * cpsr 00000030 504dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): #00 pc 46b90682 /dev/ashmem/dalvik-jit-code-cache 505dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): #01 pc 00060e62 /system/lib/libdvm.so 506dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 507dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): code around pc: 508dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68 509dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e 510dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028 511dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b 512dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * I/DEBUG ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70 513dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 514dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Clearly it is a JIT bug. To find out which translation contains the 515dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * offending code, the content of the memory dump around the faulting PC 516dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time 517dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * when a similar compilation is being created, the JIT compiler replay the 518dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * trace in the verbose mode and one can investigate the instruction 519dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * sequence in details. 520dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 521dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The length of the signature may need additional experiments to determine. 522dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The rule of thumb is don't include PC-relative instructions in the 523dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * signature since it may be affected by the alignment of the compiled code. 524dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * However, a signature that's too short might increase the chance of false 525dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * positive matches. Using gdbjithelper to disassembly the memory content 526dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * first might be a good companion approach. 527dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 528dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * For example, if the next 4 words starting from 46b90680 is pasted into 529dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * the data structure: 530dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng */ 531dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 532dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpointSize = 4; 533dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint = 534dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize); 535dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[0] = 0x512000bc; 536dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[1] = 0x37016eaf; 537dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[2] = 0x6ea866af; 538dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng gDvmJit.signatureBreakpoint[3] = 0x6f696028; 539dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 540dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng /* 541dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The following log will be printed when a match is found in subsequent 542dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * testings: 543dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 544dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words) 545dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- 546dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems, 547dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * offset 0x1f7 548dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26 549dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42 550dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0) 551dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1) 552dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0) 553dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0) 554dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0) 555dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10) 556dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624 557dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8 558dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * blocks 559dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * : 560dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * : 561dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x20 (0020): ldr r0, [r5, #52] 562dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x22 (0022): ldr r2, [pc, #96] 563dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x24 (0024): cmp r0, #0 564dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x26 (0026): beq 0x00000034 565dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x28 (0028): ldr r1, [r1, #0] 566dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2a (002a): ldr r0, [r0, #0] 567dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2c (002c): blx r2 568dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x2e (002e): cmp r0, #0 569dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x30 (0030): beq 0x00000050 570dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x32 (0032): ldr r0, [r5, #52] 571dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x34 (0034): lsls r4, r7, #2 572dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x36 (0036): str r0, [r4, r4] 573dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0) 574dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): L0x0195: 575dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26, 576dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * v26, (#1) 577dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x38 (0038): ldr r7, [r5, #104] 578dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3a (003a): adds r7, r7, #1 579dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3c (003c): str r7, [r5, #104] 580dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0) 581dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): L0x0165: 582dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26, 583dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * (#0) 584dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x3e (003e): ldr r0, [r5, #104] 585dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * D/dalvikvm( 2468): 0x40 (0040): str r0, [r5, #0] 586dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * 587dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng * The "str r0, [r4, r4]" is indeed the culprit of the native crash. 588dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng */ 589dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#endif 590dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng 591964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return true; 592964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 593964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail: 594964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return false; 595964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 596964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee} 597964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee 598ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 599ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 6005ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 6015ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 602b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 603eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * If we're not running stand-alone, wait a little before 604eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * recieving translation requests on the assumption that process start 605eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * up code isn't worth compiling. We'll resume when the framework 606eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * signals us that the first screen draw has happened, or the timer 607eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee * below expires (to catch daemons). 608f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 609f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * There is a theoretical race between the callback to 610f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * VMRuntime.startJitCompiation and when the compiler thread reaches this 611f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * point. In case the callback happens earlier, in order not to permanently 612f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * hold the system_server (which is not using the timed wait) in 613f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * interpreter-only mode we bypass the delay here. 614b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 615f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvmJit.runningInAndroidFramework && 616f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng !gDvmJit.alreadyEnabledViaFramework) { 617f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 618f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the current VM instance is the system server (detected by having 619f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * 0 in gDvm.systemServerPid), we will use the indefinite wait on the 620f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * conditional variable to determine whether to start the JIT or not. 621f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * If the system server detects that the whole system is booted in 622f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * safe mode, the conditional variable will never be signaled and the 623f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * system server will remain in the interpreter-only mode. All 624f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * subsequent apps will be started with the --enable-safemode flag 625f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * explicitly appended. 626f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 627f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng if (gDvm.systemServerPid == 0) { 628f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 629f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 630f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock); 631f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 632062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("JIT started for system_server"); 633f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } else { 634f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmLockMutex(&gDvmJit.compilerLock); 635f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng /* 636f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * TUNING: experiment with the delay & perhaps make it 637f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng * target-specific 638f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng */ 639f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmRelativeCondWait(&gDvmJit.compilerQueueActivity, 640f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng &gDvmJit.compilerLock, 3000, 0); 641f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 642f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng } 643eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee if (gDvmJit.haltCompilerThread) { 644eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee return NULL; 645eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee } 64694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee } 64794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 648964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStartup(); 649b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 650ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 651ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 652ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 653ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 654ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 655ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 656ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 657ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 658ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 659ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 660ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 661ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 662ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 663ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 664ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 665ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 666ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 667ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 668978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING) 669db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan /* 670db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan * This is live across setjmp(). Mark it volatile to suppress 671db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan * a gcc warning. We should not need this since it is assigned 672db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan * only once but gcc is not smart enough. 673db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan */ 674db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan volatile u8 startTime = dvmGetRelativeTimeUsec(); 67586717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 676964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee /* 677964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Check whether there is a suspend request on me. This 678964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * is necessary to allow a clean shutdown. 67911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * 68011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * However, in the blocking stress testing mode, let the 68111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * compiler thread continue doing compilations to unblock 68211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * other requesting threads. This may occasionally cause 68311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * shutdown from proceeding cleanly in the standalone invocation 68411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng * of the vm but this should be acceptable. 685964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */ 68611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng if (!gDvmJit.blockingMode) 687ab227f7a9a9d4c7837ee7a5cc9f07b665d516bacAndy McFadden dvmCheckSuspendPending(dvmThreadSelf()); 6882717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 6892717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 6902717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 6916999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng bool resizeFail = 6926999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 6936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng /* 6946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * If the jit table is full, consider it's time to reset 6956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * the code cache too. 6966999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */ 6976999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng gDvmJit.codeCacheFull |= resizeFail; 6982717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 699ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 700062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Compiler shutdown in progress - discarding request"); 7016999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng } else if (!gDvmJit.codeCacheFull) { 702fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee jmp_buf jmpBuf; 703fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee work.bailPtr = &jmpBuf; 704fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee bool aborted = setjmp(jmpBuf); 705fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee if (!aborted) { 7062e152baec01433de9c63633ebc6f4adf1cea3a87buzbee bool codeCompiled = dvmCompilerDoWork(&work); 7075867bea193779ff3009738513bae9bc84f4a34aabuzbee /* 7085867bea193779ff3009738513bae9bc84f4a34aabuzbee * Make sure we are still operating with the 7095867bea193779ff3009738513bae9bc84f4a34aabuzbee * same translation cache version. See 7105867bea193779ff3009738513bae9bc84f4a34aabuzbee * Issue 4271784 for details. 7115867bea193779ff3009738513bae9bc84f4a34aabuzbee */ 7125867bea193779ff3009738513bae9bc84f4a34aabuzbee dvmLockMutex(&gDvmJit.compilerLock); 7135867bea193779ff3009738513bae9bc84f4a34aabuzbee if ((work.result.cacheVersion == 7145867bea193779ff3009738513bae9bc84f4a34aabuzbee gDvmJit.cacheVersion) && 7155867bea193779ff3009738513bae9bc84f4a34aabuzbee codeCompiled && 7165867bea193779ff3009738513bae9bc84f4a34aabuzbee !work.result.discardResult && 7175867bea193779ff3009738513bae9bc84f4a34aabuzbee work.result.codeAddress) { 7182e152baec01433de9c63633ebc6f4adf1cea3a87buzbee dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 7192e152baec01433de9c63633ebc6f4adf1cea3a87buzbee work.result.instructionSet, 720cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng false, /* not method entry */ 7212e152baec01433de9c63633ebc6f4adf1cea3a87buzbee work.result.profileCodeSize); 7222e152baec01433de9c63633ebc6f4adf1cea3a87buzbee } 7235867bea193779ff3009738513bae9bc84f4a34aabuzbee dvmUnlockMutex(&gDvmJit.compilerLock); 72460c24f436d603c564d5351a6f81821f12635733cBen Cheng } 7252e152baec01433de9c63633ebc6f4adf1cea3a87buzbee dvmCompilerArenaReset(); 726ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 727ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 728978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING) 72986717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime; 73086717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif 731ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 732ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 733ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 734ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 735ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 736ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 737ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 7385ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 7395ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 7405ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 7415ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 7425ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 7435ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 7445ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 74543eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden if (gDvm.verboseShutdown) 746062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Compiler thread shutting down"); 747ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 748ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 749ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 750ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 751ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 75294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 75394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmInitMutex(&gDvmJit.compilerLock); 7546999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng dvmInitMutex(&gDvmJit.compilerICPatchLock); 755b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng dvmInitMutex(&gDvmJit.codeCacheProtectionLock); 75694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmLockMutex(&gDvmJit.compilerLock); 75794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 75894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 75994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 76094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee /* Reset the work queue */ 76194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 76294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee gDvmJit.compilerQueueLength = 0; 76394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee dvmUnlockMutex(&gDvmJit.compilerLock); 76494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee 765ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 76694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee * Defer rest of initialization until we're sure JIT'ng makes sense. Launch 767964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * the compiler thread, which will do the real initialization if and 768964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * when it is signalled to do so. 769ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 770964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 771964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee compilerThreadStart, NULL); 772ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 773ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 774ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 775ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 776ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 777ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 7782fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* Disable new translation requests */ 7792fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee gDvmJit.pProfTable = NULL; 7802fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee gDvmJit.pProfTableCopy = NULL; 78199e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmJitUpdateThreadStateAll(); 7822fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee 7832e152baec01433de9c63633ebc6f4adf1cea3a87buzbee if (gDvm.verboseShutdown || 7842e152baec01433de9c63633ebc6f4adf1cea3a87buzbee gDvmJit.profileMode == kTraceProfilingContinuous) { 78588a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng dvmCompilerDumpStats(); 78688a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng while (gDvmJit.compilerQueueLength) 78788a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng sleep(5); 78888a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng } 78988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng 790ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 791ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 792ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 793ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 794ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 795ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 796ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 797ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 798ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 799e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Compiler thread join failed"); 80043eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden else if (gDvm.verboseShutdown) 801062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("Compiler thread has shut down"); 802ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 80306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 8042fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* Break loops within the translation cache */ 8052fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee dvmJitUnchainAll(); 80696cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee 8072fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee /* 8082fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * NOTE: our current implementatation doesn't allow for the compiler 8092fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * thread to be restarted after it exits here. We aren't freeing 8102fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * the JitTable or the ProfTable because threads which still may be 8112fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * running or in the process of shutting down may hold references to 8122fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee * them. 8132fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee */ 81496cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee} 81506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 81699e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmCompilerUpdateGlobalState() 81706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{ 81806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActive; 81906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee bool jitActivate; 8203e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee bool needUnchain = false; 82106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 822a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng /* 823a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * The tableLock might not be initialized yet by the compiler thread if 824a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * debugger is attached from the very beginning of the VM launch. If 825a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * pProfTableCopy is NULL, the lock is not initialized yet and we don't 826a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng * need to refresh anything either. 827a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng */ 828a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng if (gDvmJit.pProfTableCopy == NULL) { 829a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng return; 830a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng } 831a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng 83218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee /* 83318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * On the first enabling of method tracing, switch the compiler 83418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * into a mode that includes trace support for invokes and returns. 83518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * If there are any existing translations, flush them. NOTE: we 83618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * can't blindly flush the translation cache because this code 83718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * may be executed before the compiler thread has finished 83818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * initialization. 83918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee */ 8409a3147c7412f4794434b4c2604aa2ba784867774buzbee if ((gDvm.activeProfilers != 0) && 84118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee !gDvmJit.methodTraceSupport) { 84218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee bool resetRequired; 84318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee /* 84418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * compilerLock will prevent new compilations from being 84518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee * installed while we are working. 84618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee */ 84718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee dvmLockMutex(&gDvmJit.compilerLock); 84818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee gDvmJit.cacheVersion++; // invalidate compilations in flight 84918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee gDvmJit.methodTraceSupport = true; 85018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee resetRequired = (gDvmJit.numCompilations != 0); 85118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee dvmUnlockMutex(&gDvmJit.compilerLock); 85218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee if (resetRequired) { 85318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET); 85418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee resetCodeCache(); 85518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee dvmResumeAllThreads(SUSPEND_FOR_CC_RESET); 85618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee } 85718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee } 85818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee 85906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee dvmLockMutex(&gDvmJit.tableLock); 86006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee jitActive = gDvmJit.pProfTable != NULL; 861cb3081f675109049e63380170b60871e8275f9a8buzbee jitActivate = !dvmDebuggerOrProfilerActive(); 86206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee 86306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee if (jitActivate && !jitActive) { 86406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = gDvmJit.pProfTableCopy; 86506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } else if (!jitActivate && jitActive) { 86606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee gDvmJit.pProfTable = NULL; 8673e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee needUnchain = true; 86806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee } 8693e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmUnlockMutex(&gDvmJit.tableLock); 8703e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee if (needUnchain) 8713e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee dvmJitUnchainAll(); 8729a3147c7412f4794434b4c2604aa2ba784867774buzbee // Make sure all threads have current values 87399e3e6e72e3471eb85fc2e405866392b01c080febuzbee dvmJitUpdateThreadStateAll(); 87406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee} 875