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