Compiler.cpp revision 7a0bcd0de6c4da6499a088a18d1750e51204c2a6
1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* 2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Copyright (C) 2009 The Android Open Source Project 3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License"); 5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * you may not use this file except in compliance with the License. 6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * You may obtain a copy of the License at 7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * http://www.apache.org/licenses/LICENSE-2.0 9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Unless required by applicable law or agreed to in writing, software 11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS, 12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See the License for the specific language governing permissions and 14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * limitations under the License. 15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 17ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <sys/mman.h> 18ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <errno.h> 19ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "Dalvik.h" 21ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "interp/Jit.h" 22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "CompilerInternals.h" 23ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 24ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void) 25ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 26ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return gDvmJit.compilerQueueLength; 27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void) 30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind 32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng != kWorkOrderInvalid); 33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = 34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex]; 35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind = 36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng kWorkOrderInvalid; 37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) { 38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkDequeueIndex = 0; 39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength--; 41f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee if (gDvmJit.compilerQueueLength == 0) { 42f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee int cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 43f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee } 44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Remember the high water mark of the queue length */ 46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued) 47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength; 48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return work; 50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info) 53ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 54ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 55ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int i; 56ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int numWork; 5760c24f436d603c564d5351a6f81821f12635733cBen Cheng int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 5860c24f436d603c564d5351a6f81821f12635733cBen Cheng bool result = true; 59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 60ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * Return if queue is full. 647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * If the code cache is full, we will allow the work order to be added and 657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * we use that to trigger code cache reset. 667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE) { 6860c24f436d603c564d5351a6f81821f12635733cBen Cheng result = false; 6960c24f436d603c564d5351a6f81821f12635733cBen Cheng goto done; 70ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 72ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for (numWork = gDvmJit.compilerQueueLength, 73ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = gDvmJit.compilerWorkDequeueIndex; 74ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork > 0; 75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng numWork--) { 76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Already enqueued */ 77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkQueue[i++].pc == pc) 78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto done; 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Wrap around */ 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (i == COMPILER_WORK_QUEUE_SIZE) 81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng i = 0; 82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 84ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng CompilerWorkOrder *newOrder = 85ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex]; 86ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->pc = pc; 87ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->kind = kind; 88ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->info = info; 89ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.codeAddress = NULL; 90ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng newOrder->result.discardResult = 9160c24f436d603c564d5351a6f81821f12635733cBen Cheng (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ? 9260c24f436d603c564d5351a6f81821f12635733cBen Cheng true : false; 9333672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng newOrder->result.requestingThread = dvmThreadSelf(); 9433672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng 95ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex++; 96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE) 97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = 0; 98ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength++; 99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity); 100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdone: 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 10460c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmChangeStatus(NULL, oldStatus); 10560c24f436d603c564d5351a6f81821f12635733cBen Cheng return result; 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */ 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void) 110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 111d726991ba52466cde88e37aba4de2395b62477faBill Buzbee int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) { 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock); 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 117d726991ba52466cde88e37aba4de2395b62477faBill Buzbee dvmChangeStatus(NULL, oldStatus); 118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 12060c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void) 12160c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 12260c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dvmCompilerTemplateStart(void); 12360c24f436d603c564d5351a6f81821f12635733cBen Cheng extern void dmvCompilerTemplateEnd(void); 12460c24f436d603c564d5351a6f81821f12635733cBen Cheng 12560c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Allocate the code cache */ 12660c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE, 12760c24f436d603c564d5351a6f81821f12635733cBen Cheng PROT_READ | PROT_WRITE | PROT_EXEC, 12860c24f436d603c564d5351a6f81821f12635733cBen Cheng MAP_PRIVATE | MAP_ANON, -1, 0); 12960c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCache == MAP_FAILED) { 13060c24f436d603c564d5351a6f81821f12635733cBen Cheng LOGE("Failed to create the code cache: %s\n", strerror(errno)); 13160c24f436d603c564d5351a6f81821f12635733cBen Cheng return false; 13260c24f436d603c564d5351a6f81821f12635733cBen Cheng } 13360c24f436d603c564d5351a6f81821f12635733cBen Cheng 1347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng // For debugging only 1357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng // LOGD("Code cache starts at %p", gDvmJit.codeCache); 1367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 13760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Copy the template code into the beginning of the code cache */ 13860c24f436d603c564d5351a6f81821f12635733cBen Cheng int templateSize = (intptr_t) dmvCompilerTemplateEnd - 13960c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) dvmCompilerTemplateStart; 14060c24f436d603c564d5351a6f81821f12635733cBen Cheng memcpy((void *) gDvmJit.codeCache, 14160c24f436d603c564d5351a6f81821f12635733cBen Cheng (void *) dvmCompilerTemplateStart, 14260c24f436d603c564d5351a6f81821f12635733cBen Cheng templateSize); 14360c24f436d603c564d5351a6f81821f12635733cBen Cheng 14460c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.templateSize = templateSize; 14560c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = templateSize; 14660c24f436d603c564d5351a6f81821f12635733cBen Cheng 14760c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Only flush the part in the code cache that is being used now */ 14860c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 14960c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + templateSize, 0); 15060c24f436d603c564d5351a6f81821f12635733cBen Cheng return true; 15160c24f436d603c564d5351a6f81821f12635733cBen Cheng} 15260c24f436d603c564d5351a6f81821f12635733cBen Cheng 1537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print) 1547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{ 1557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng void *fp = thread->curFrame; 1567a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng StackSaveArea* saveArea = NULL; 1577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int stackLevel = 0; 1587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1607a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid, 1617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetThreadStatusStr(thread->status), 1627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache, 1637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng thread->inJitCodeCache ? "jit" : "interp"); 1647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Crawl the Dalvik stack frames to clear the returnAddr field */ 1667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (fp != NULL) { 1677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea = SAVEAREA_FROM_FP(fp); 1687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 1697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (print) { 1707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (dvmIsBreakFrame(fp)) { 1717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: break frame (%p)", 1727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, saveArea->returnAddr); 1737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng else { 1757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD(" #%d: %s.%s%s (%p)", 1767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel, 1777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->clazz->descriptor, 1787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->method->name, 1797a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmIsNativeMethod(saveArea->method) ? 1807a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng " (native)" : "", 1817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr); 1827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1847a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng stackLevel++; 1857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng saveArea->returnAddr = NULL; 1867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(fp != saveArea->prevFrame); 1877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng fp = saveArea->prevFrame; 1887a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Make sure the stack is fully unwound to the bottom */ 1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(saveArea == NULL || 1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng (u1 *) (saveArea+1) == thread->interpStackStart); 1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng} 1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 19460c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void) 19560c24f436d603c564d5351a6f81821f12635733cBen Cheng{ 19660c24f436d603c564d5351a6f81821f12635733cBen Cheng Thread* thread; 1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng u8 startTime = dvmGetRelativeTimeUsec(); 1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng int inJit = 0; 19960c24f436d603c564d5351a6f81821f12635733cBen Cheng 2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Reset the JIT code cache (%d bytes used / %d time(s))", 2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed, ++gDvmJit.numCodeCacheReset); 20260c24f436d603c564d5351a6f81821f12635733cBen Cheng 20360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Stop the world */ 20460c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET); 20560c24f436d603c564d5351a6f81821f12635733cBen Cheng 2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* If any thread is found stuck in the JIT state, don't reset the cache */ 20760c24f436d603c564d5351a6f81821f12635733cBen Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (thread->inJitCodeCache) { 2097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng inJit++; 2107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* 2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * STOPSHIP 2127a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * Change the verbose mode to false after the new code receives 2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng * more QA love. 2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng */ 2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng crawlDalvikStack(thread, true); 2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 21860c24f436d603c564d5351a6f81821f12635733cBen Cheng 2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (inJit) { 2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Wait a while for the busy threads to rest and try again */ 2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset = 256; 2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng goto done; 2237a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Drain the work queue to free the work order */ 2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng while (workQueueLength()) { 2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng CompilerWorkOrder work = workDequeue(); 2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng free(work.info); 2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng /* Wipe out the returnAddr field that soon will point to stale code */ 2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng for (thread = gDvm.threadList; thread != NULL; thread = thread->next) { 2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng crawlDalvikStack(thread, false); 23460c24f436d603c564d5351a6f81821f12635733cBen Cheng } 23560c24f436d603c564d5351a6f81821f12635733cBen Cheng 23660c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the JitEntry table contents to the initial unpopulated state */ 23760c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitResetTable(); 23860c24f436d603c564d5351a6f81821f12635733cBen Cheng 23960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* 24060c24f436d603c564d5351a6f81821f12635733cBen Cheng * Wipe out the code cache content to force immediate crashes if 24160c24f436d603c564d5351a6f81821f12635733cBen Cheng * stale JIT'ed code is invoked. 24260c24f436d603c564d5351a6f81821f12635733cBen Cheng */ 2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng memset((char *) gDvmJit.codeCache + gDvmJit.templateSize, 2447a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 0, 2457a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.codeCacheByteUsed - gDvmJit.templateSize); 24660c24f436d603c564d5351a6f81821f12635733cBen Cheng cacheflush((intptr_t) gDvmJit.codeCache, 24760c24f436d603c564d5351a6f81821f12635733cBen Cheng (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0); 24860c24f436d603c564d5351a6f81821f12635733cBen Cheng 24960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the current mark of used bytes to the end of template code */ 25060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheByteUsed = gDvmJit.templateSize; 25160c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.numCompilations = 0; 25260c24f436d603c564d5351a6f81821f12635733cBen Cheng 25360c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Reset the work queue */ 25460c24f436d603c564d5351a6f81821f12635733cBen Cheng memset(gDvmJit.compilerWorkQueue, 0, 25560c24f436d603c564d5351a6f81821f12635733cBen Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 25660c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 25760c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.compilerQueueLength = 0; 25860c24f436d603c564d5351a6f81821f12635733cBen Cheng 25960c24f436d603c564d5351a6f81821f12635733cBen Cheng /* All clear now */ 26060c24f436d603c564d5351a6f81821f12635733cBen Cheng gDvmJit.codeCacheFull = false; 26160c24f436d603c564d5351a6f81821f12635733cBen Cheng 2627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Code cache reset takes %lld usec", 2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng dvmGetRelativeTimeUsec() - startTime); 2647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng 2657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengdone: 26660c24f436d603c564d5351a6f81821f12635733cBen Cheng /* Resume all threads */ 26760c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmResumeAllThreads(SUSPEND_FOR_CC_RESET); 26860c24f436d603c564d5351a6f81821f12635733cBen Cheng} 26960c24f436d603c564d5351a6f81821f12635733cBen Cheng 270ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg) 271ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 2725ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_VMWAIT); 2735ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 274b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* 275b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * Wait a little before recieving translation requests on the assumption 276b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * that process start-up code isn't worth compiling. The trace 277b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * selector won't attempt to request a translation if the queue is 278b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * filled, so we'll prevent by keeping the high water mark at zero 279b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee * for a shore time. 280b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee */ 281b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee assert(gDvmJit.compilerHighWater == 0); 282b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee usleep(1000); 283b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee gDvmJit.compilerHighWater = 284b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4); 285b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee 286ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 287ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 288ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Since the compiler thread will not touch any objects on the heap once 289ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * being created, we just fake its state as VMWAIT so that it can be a 290ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * bit late when there is suspend request pending. 291ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 292ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while (!gDvmJit.haltCompilerThread) { 293ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (workQueueLength() == 0) { 294ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng int cc; 295ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 296ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(cc == 0); 297ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_wait(&gDvmJit.compilerQueueActivity, 298ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng &gDvmJit.compilerLock); 299ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue; 300ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 301ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng do { 302ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng CompilerWorkOrder work = workDequeue(); 303ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 304ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Check whether there is a suspend request on me */ 305ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmCheckSuspendPending(NULL); 3062717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee /* Is JitTable filling up? */ 3072717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee if (gDvmJit.jitTableEntriesUsed > 3082717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) { 3092717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee dvmJitResizeJitTable(gDvmJit.jitTableSize * 2); 3102717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee } 311ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.haltCompilerThread) { 312ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng LOGD("Compiler shutdown in progress - discarding request"); 313ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } else { 314d726991ba52466cde88e37aba4de2395b62477faBill Buzbee /* If compilation failed, use interpret-template */ 315d726991ba52466cde88e37aba4de2395b62477faBill Buzbee if (!dvmCompilerDoWork(&work)) { 316d726991ba52466cde88e37aba4de2395b62477faBill Buzbee work.result.codeAddress = gDvmJit.interpretTemplate; 317ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 31860c24f436d603c564d5351a6f81821f12635733cBen Cheng if (!work.result.discardResult) { 31960c24f436d603c564d5351a6f81821f12635733cBen Cheng dvmJitSetCodeAddr(work.pc, work.result.codeAddress, 32060c24f436d603c564d5351a6f81821f12635733cBen Cheng work.result.instructionSet); 32160c24f436d603c564d5351a6f81821f12635733cBen Cheng } 322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 323ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng free(work.info); 324ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 32560c24f436d603c564d5351a6f81821f12635733cBen Cheng 32649ca78679485ee56d5925da122216821c668043fBen Cheng /* 32749ca78679485ee56d5925da122216821c668043fBen Cheng * FIXME - temporarily disable code cache reset until 32849ca78679485ee56d5925da122216821c668043fBen Cheng * stale code stops leaking. 32949ca78679485ee56d5925da122216821c668043fBen Cheng */ 33049ca78679485ee56d5925da122216821c668043fBen Cheng#if 0 33160c24f436d603c564d5351a6f81821f12635733cBen Cheng if (gDvmJit.codeCacheFull == true) { 3327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng if (gDvmJit.delayCodeCacheReset == 0) { 3337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng resetCodeCache(); 3347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng assert(workQueueLength() == 0 || 3357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset != 0); 3367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } else { 3377a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng LOGD("Delay the next %d tries to reset code cache", 3387a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset); 3397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng gDvmJit.delayCodeCacheReset--; 3407a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng } 34160c24f436d603c564d5351a6f81821f12635733cBen Cheng } 34249ca78679485ee56d5925da122216821c668043fBen Cheng#endif 343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } while (workQueueLength() != 0); 344ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 345ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueEmpty); 347ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 348ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng 3495ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng /* 3505ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * As part of detaching the thread we need to call into Java code to update 3515ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * the ThreadGroup, and we should not be in VMWAIT state while executing 3525ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng * interpreted code. 3535ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng */ 3545ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng dvmChangeStatus(NULL, THREAD_RUNNING); 3555ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng 356ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread shutting down\n"); 357ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return NULL; 358ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 359ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 360ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void) 361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 362ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Make sure the BBType enum is in sane state */ 3631465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee assert(kChainingCellNormal == 0); 364ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 365ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Architecture-specific chores to initialize */ 366ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCompilerArchInit()) 367ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 368ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 369ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* 370ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Setup the code cache if it is not done so already. For apps it should be 371ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * done by the Zygote already, but for command-line dalvikvm invocation we 372ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * need to do it here. 373ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.codeCache == NULL) { 375ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCompilerSetupCodeCache()) 376ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 377ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 378ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 379ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Allocate the initial arena block */ 380ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (dvmCompilerHeapInit() == false) { 381ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 382ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 383ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 384ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmInitMutex(&gDvmJit.compilerLock); 385ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL); 386ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL); 387ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 388ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 389ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 390ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = false; 391ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 392ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng /* Reset the work queue */ 393ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng memset(gDvmJit.compilerWorkQueue, 0, 394ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE); 395ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0; 396ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.compilerQueueLength = 0; 397b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee /* Block new entries via HighWater until compiler thread is ready */ 398b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee gDvmJit.compilerHighWater = 0; 399ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 400ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng assert(gDvmJit.compilerHighWater < COMPILER_WORK_QUEUE_SIZE); 401ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (!dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler", 402ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng compilerThreadStart, NULL)) { 403ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 404ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng goto fail; 405ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 406ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 4078b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng /* Track method-level compilation statistics */ 4088b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng gDvmJit.methodStatsTable = dvmHashTableCreate(32, NULL); 4098b258bfd8562edf1306ea6a5642595186f1f3f36Ben Cheng 410ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 411ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 412ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return true; 413ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 414ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengfail: 415ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return false; 416ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 417ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 418ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void) 419ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{ 420ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng void *threadReturn; 421ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 422ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if (gDvmJit.compilerHandle) { 423ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 424ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng gDvmJit.haltCompilerThread = true; 425ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 426ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmLockMutex(&gDvmJit.compilerLock); 427ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pthread_cond_signal(&gDvmJit.compilerQueueActivity); 428ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dvmUnlockMutex(&gDvmJit.compilerLock); 429ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 430ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0) 431ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGW("Compiler thread join failed\n"); 432ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng else 433ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng LOGD("Compiler thread has shut down\n"); 434ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng } 435ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng} 436