Compiler.cpp revision 43eb5015ca8bc0c859100b659d9c12934011a42e
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
52964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/*
53964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful.
54964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * This routine will not block, but simply return if it couldn't
55964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * aquire the lock or if the queue is full.
56964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */
57ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
58ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int cc;
60ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int numWork;
6260c24f436d603c564d5351a6f81821f12635733cBen Cheng    bool result = true;
63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
64964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmTryLockMutex(&gDvmJit.compilerLock)) {
65964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        return false;  // Couldn't aquire the lock
66964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /*
697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     * Return if queue is full.
707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     * If the code cache is full, we will allow the work order to be added and
717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     * we use that to trigger code cache reset.
727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     */
737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE) {
7460c24f436d603c564d5351a6f81821f12635733cBen Cheng        result = false;
75964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto unlockAndExit;
76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (numWork = gDvmJit.compilerQueueLength,
79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           i = gDvmJit.compilerWorkDequeueIndex;
80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork > 0;
81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork--) {
82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Already enqueued */
83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (gDvmJit.compilerWorkQueue[i++].pc == pc)
84964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto unlockAndExit;
85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Wrap around */
86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (i == COMPILER_WORK_QUEUE_SIZE)
87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            i = 0;
88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
90ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    CompilerWorkOrder *newOrder =
91ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng        &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex];
92ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->pc = pc;
93ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->kind = kind;
94ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->info = info;
95ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.codeAddress = NULL;
96ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.discardResult =
9760c24f436d603c564d5351a6f81821f12635733cBen Cheng        (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ?
9860c24f436d603c564d5351a6f81821f12635733cBen Cheng        true : false;
9933672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng    newOrder->result.requestingThread = dvmThreadSelf();
10033672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng
101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkEnqueueIndex++;
102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkEnqueueIndex = 0;
104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength++;
105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(cc == 0);
107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
108964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit:
109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
11060c24f436d603c564d5351a6f81821f12635733cBen Cheng    return result;
111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Block until queue length is 0 */
114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void)
115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
116d726991ba52466cde88e37aba4de2395b62477faBill Buzbee    int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) {
119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock);
120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
122d726991ba52466cde88e37aba4de2395b62477faBill Buzbee    dvmChangeStatus(NULL, oldStatus);
123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
12560c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void)
12660c24f436d603c564d5351a6f81821f12635733cBen Cheng{
12760c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dvmCompilerTemplateStart(void);
12860c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dmvCompilerTemplateEnd(void);
12960c24f436d603c564d5351a6f81821f12635733cBen Cheng
13060c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Allocate the code cache */
13160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
13260c24f436d603c564d5351a6f81821f12635733cBen Cheng                          PROT_READ | PROT_WRITE | PROT_EXEC,
13360c24f436d603c564d5351a6f81821f12635733cBen Cheng                          MAP_PRIVATE | MAP_ANON, -1, 0);
13460c24f436d603c564d5351a6f81821f12635733cBen Cheng    if (gDvmJit.codeCache == MAP_FAILED) {
13560c24f436d603c564d5351a6f81821f12635733cBen Cheng        LOGE("Failed to create the code cache: %s\n", strerror(errno));
13660c24f436d603c564d5351a6f81821f12635733cBen Cheng        return false;
13760c24f436d603c564d5351a6f81821f12635733cBen Cheng    }
13860c24f436d603c564d5351a6f81821f12635733cBen Cheng
1397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    // For debugging only
1407a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    // LOGD("Code cache starts at %p", gDvmJit.codeCache);
1417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
14260c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Copy the template code into the beginning of the code cache */
14360c24f436d603c564d5351a6f81821f12635733cBen Cheng    int templateSize = (intptr_t) dmvCompilerTemplateEnd -
14460c24f436d603c564d5351a6f81821f12635733cBen Cheng                       (intptr_t) dvmCompilerTemplateStart;
14560c24f436d603c564d5351a6f81821f12635733cBen Cheng    memcpy((void *) gDvmJit.codeCache,
14660c24f436d603c564d5351a6f81821f12635733cBen Cheng           (void *) dvmCompilerTemplateStart,
14760c24f436d603c564d5351a6f81821f12635733cBen Cheng           templateSize);
14860c24f436d603c564d5351a6f81821f12635733cBen Cheng
14960c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.templateSize = templateSize;
15060c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = templateSize;
15160c24f436d603c564d5351a6f81821f12635733cBen Cheng
15260c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Only flush the part in the code cache that is being used now */
15360c24f436d603c564d5351a6f81821f12635733cBen Cheng    cacheflush((intptr_t) gDvmJit.codeCache,
15460c24f436d603c564d5351a6f81821f12635733cBen Cheng               (intptr_t) gDvmJit.codeCache + templateSize, 0);
15560c24f436d603c564d5351a6f81821f12635733cBen Cheng    return true;
15660c24f436d603c564d5351a6f81821f12635733cBen Cheng}
15760c24f436d603c564d5351a6f81821f12635733cBen Cheng
1587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print)
1597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{
1607a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    void *fp = thread->curFrame;
1617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    StackSaveArea* saveArea = NULL;
1627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int stackLevel = 0;
1637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
1647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (print) {
1657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid,
1667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             dvmGetThreadStatusStr(thread->status),
1677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache,
1687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache ? "jit" : "interp");
1697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
1707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Crawl the Dalvik stack frames to clear the returnAddr field */
1717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (fp != NULL) {
1727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea = SAVEAREA_FROM_FP(fp);
1737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
1747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (print) {
1757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            if (dvmIsBreakFrame(fp)) {
1767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: break frame (%p)",
1777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel, saveArea->returnAddr);
1787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
1797a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            else {
1807a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: %s.%s%s (%p)",
1817a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel,
1827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->clazz->descriptor,
1837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->name,
1847a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     dvmIsNativeMethod(saveArea->method) ?
1857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                         " (native)" : "",
1867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->returnAddr);
1877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
1887a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        stackLevel++;
1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea->returnAddr = NULL;
1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        assert(fp != saveArea->prevFrame);
1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        fp = saveArea->prevFrame;
1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
1947a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Make sure the stack is fully unwound to the bottom */
1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    assert(saveArea == NULL ||
1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           (u1 *) (saveArea+1) == thread->interpStackStart);
1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng}
1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
19960c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void)
20060c24f436d603c564d5351a6f81821f12635733cBen Cheng{
20160c24f436d603c564d5351a6f81821f12635733cBen Cheng    Thread* thread;
2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    u8 startTime = dvmGetRelativeTimeUsec();
2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int inJit = 0;
20460c24f436d603c564d5351a6f81821f12635733cBen Cheng
2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    LOGD("Reset the JIT code cache (%d bytes used / %d time(s))",
2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng         gDvmJit.codeCacheByteUsed, ++gDvmJit.numCodeCacheReset);
20760c24f436d603c564d5351a6f81821f12635733cBen Cheng
20860c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Stop the world */
20960c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET);
21060c24f436d603c564d5351a6f81821f12635733cBen Cheng
2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* If any thread is found stuck in the JIT state, don't reset the cache */
21260c24f436d603c564d5351a6f81821f12635733cBen Cheng    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (thread->inJitCodeCache) {
2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            inJit++;
2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            /*
2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             * STOPSHIP
2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             * Change the verbose mode to false after the new code receives
2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             * more QA love.
2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             */
2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            crawlDalvikStack(thread, true);
2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
22360c24f436d603c564d5351a6f81821f12635733cBen Cheng
2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (inJit) {
2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        /* Wait a while for the busy threads to rest and try again */
2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        gDvmJit.delayCodeCacheReset = 256;
2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        goto done;
2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Drain the work queue to free the work order */
2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (workQueueLength()) {
2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        CompilerWorkOrder work = workDequeue();
2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        free(work.info);
2347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Wipe out the returnAddr field that soon will point to stale code */
2377a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2387a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        crawlDalvikStack(thread, false);
23960c24f436d603c564d5351a6f81821f12635733cBen Cheng    }
24060c24f436d603c564d5351a6f81821f12635733cBen Cheng
24160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the JitEntry table contents to the initial unpopulated state */
24260c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmJitResetTable();
24360c24f436d603c564d5351a6f81821f12635733cBen Cheng
24460c24f436d603c564d5351a6f81821f12635733cBen Cheng    /*
24560c24f436d603c564d5351a6f81821f12635733cBen Cheng     * Wipe out the code cache content to force immediate crashes if
24660c24f436d603c564d5351a6f81821f12635733cBen Cheng     * stale JIT'ed code is invoked.
24760c24f436d603c564d5351a6f81821f12635733cBen Cheng     */
2487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    memset((char *) gDvmJit.codeCache + gDvmJit.templateSize,
2497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           0,
2507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           gDvmJit.codeCacheByteUsed - gDvmJit.templateSize);
25160c24f436d603c564d5351a6f81821f12635733cBen Cheng    cacheflush((intptr_t) gDvmJit.codeCache,
25260c24f436d603c564d5351a6f81821f12635733cBen Cheng               (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0);
25360c24f436d603c564d5351a6f81821f12635733cBen Cheng
25460c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the current mark of used bytes to the end of template code */
25560c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
25660c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.numCompilations = 0;
25760c24f436d603c564d5351a6f81821f12635733cBen Cheng
25860c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the work queue */
25960c24f436d603c564d5351a6f81821f12635733cBen Cheng    memset(gDvmJit.compilerWorkQueue, 0,
26060c24f436d603c564d5351a6f81821f12635733cBen Cheng           sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
26160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
26260c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerQueueLength = 0;
26360c24f436d603c564d5351a6f81821f12635733cBen Cheng
26460c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* All clear now */
26560c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheFull = false;
26660c24f436d603c564d5351a6f81821f12635733cBen Cheng
2677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    LOGD("Code cache reset takes %lld usec",
2687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng         dvmGetRelativeTimeUsec() - startTime);
2697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengdone:
27160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Resume all threads */
27260c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmResumeAllThreads(SUSPEND_FOR_CC_RESET);
27360c24f436d603c564d5351a6f81821f12635733cBen Cheng}
27460c24f436d603c564d5351a6f81821f12635733cBen Cheng
275964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeebool compilerThreadStartup(void)
276964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{
277964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    JitEntry *pJitTable = NULL;
278964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned char *pJitProfTable = NULL;
279964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned int i;
280964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
281964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!dvmCompilerArchInit())
282964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
283964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
284964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
285964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Setup the code cache if we have not inherited a valid code cache
286964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * from the zygote.
287964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
288964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (gDvmJit.codeCache == NULL) {
289964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        if (!dvmCompilerSetupCodeCache())
290964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto fail;
291964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
292964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
293964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Allocate the initial arena block */
294964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmCompilerHeapInit() == false) {
295964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
296964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
297964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
298964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
299964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
300964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Track method-level compilation statistics */
301964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
302964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
303964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
304964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
305964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Set up the JitTable */
306964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
307964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Power of 2? */
308964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(gDvmJit.jitTableSize &&
309964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee           !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
310964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
311964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmInitMutex(&gDvmJit.tableLock);
312964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
313964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitTable = (JitEntry*)
314964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
315964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitTable) {
316964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit table allocation failed\n");
317964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
318964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
319964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
320964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
321964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * NOTE: the profile table must only be allocated once, globally.
322964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Profiling is turned on and off by nulling out gDvm.pJitProfTable
323964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and then restoring its original value.  However, this action
324964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * is not syncronized for speed so threads may continue to hold
325964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and update the profile table after profiling has been turned
326964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * off by null'ng the global pointer.  Be aware.
327964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
328964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
329964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitProfTable) {
330964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit prof table allocation failed\n");
331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE);
335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    for (i=0; i < gDvmJit.jitTableSize; i++) {
336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee       pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Is chain field wide enough for termination pattern? */
339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.pJitEntryTable = pJitTable;
342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableEntriesUsed = 0;
344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.compilerHighWater =
345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.pProfTable = pJitProfTable;
34706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    gDvmJit.pProfTableCopy = pJitProfTable;
348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Signal running threads to refresh their cached pJitTable pointers */
351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmSuspendAllThreads(SUSPEND_FOR_REFRESH);
352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmResumeAllThreads(SUSPEND_FOR_REFRESH);
353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return true;
354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail:
356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return false;
357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee}
359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
360ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg)
361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
36294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    int ret;
36394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    struct timespec ts;
36494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
3655ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_VMWAIT);
3665ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
367b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee    /*
368b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee     * Wait a little before recieving translation requests on the assumption
369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * that process start-up code isn't worth compiling.
370b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee     */
37194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
37294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
37394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    /*
37494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * TUNING: once framework is calling VMRuntime.startJitCompilation,
37594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * experiment with the delay time (and perhaps have target-dependent
37694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * values?
37794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     */
37894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmAbsoluteTime(1000, 0, &ts);
37994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#if defined(HAVE_TIMEDWAIT_MONOTONIC)
38094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    ret = pthread_cond_timedwait_monotonic(&gDvmJit.compilerQueueActivity,
38194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee                                           &gDvmJit.compilerLock, &ts);
38294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#else
38394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    ret = pthread_cond_timedwait(&gDvmJit.compilerQueueActivity,
38494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee                                 &gDvmJit.compilerLock, &ts);
38594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee#endif
38694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    assert(ret == 0 || ret == ETIMEDOUT);
38794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
38894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    if (gDvmJit.haltCompilerThread) {
38994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee        dvmUnlockMutex(&gDvmJit.compilerLock);
39094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee        return NULL;
39194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    }
39294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
39394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
39494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    compilerThreadStartup();
396b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee
397ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
398ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
399ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Since the compiler thread will not touch any objects on the heap once
400ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * being created, we just fake its state as VMWAIT so that it can be a
401ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * bit late when there is suspend request pending.
402ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
403ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (!gDvmJit.haltCompilerThread) {
404ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (workQueueLength() == 0) {
405ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            int cc;
406ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
407ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(cc == 0);
408ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
409ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                              &gDvmJit.compilerLock);
410ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            continue;
411ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
412ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            do {
413964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                bool resizeFail = false;
414ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                CompilerWorkOrder work = workDequeue();
415ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmUnlockMutex(&gDvmJit.compilerLock);
416964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                /*
417964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * Check whether there is a suspend request on me.  This
418964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * is necessary to allow a clean shutdown.
419964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 */
420ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmCheckSuspendPending(NULL);
4212717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                /* Is JitTable filling up? */
4222717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                if (gDvmJit.jitTableEntriesUsed >
4232717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
424964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                    resizeFail = dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
4252717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                }
426ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                if (gDvmJit.haltCompilerThread) {
427ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    LOGD("Compiler shutdown in progress - discarding request");
428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                } else if (!resizeFail) {
429d726991ba52466cde88e37aba4de2395b62477faBill Buzbee                    /* If compilation failed, use interpret-template */
430d726991ba52466cde88e37aba4de2395b62477faBill Buzbee                    if (!dvmCompilerDoWork(&work)) {
431d726991ba52466cde88e37aba4de2395b62477faBill Buzbee                        work.result.codeAddress = gDvmJit.interpretTemplate;
432ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    }
43360c24f436d603c564d5351a6f81821f12635733cBen Cheng                    if (!work.result.discardResult) {
43460c24f436d603c564d5351a6f81821f12635733cBen Cheng                        dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
43560c24f436d603c564d5351a6f81821f12635733cBen Cheng                                          work.result.instructionSet);
43660c24f436d603c564d5351a6f81821f12635733cBen Cheng                    }
437ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                }
438ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                free(work.info);
439ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmLockMutex(&gDvmJit.compilerLock);
44060c24f436d603c564d5351a6f81821f12635733cBen Cheng
44149ca78679485ee56d5925da122216821c668043fBen Cheng                /*
44249ca78679485ee56d5925da122216821c668043fBen Cheng                 * FIXME - temporarily disable code cache reset until
44349ca78679485ee56d5925da122216821c668043fBen Cheng                 * stale code stops leaking.
44449ca78679485ee56d5925da122216821c668043fBen Cheng                 */
44549ca78679485ee56d5925da122216821c668043fBen Cheng#if 0
446964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                if (gDvmJit.codeCacheFull == true || resizeFail) {
4477a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                    if (gDvmJit.delayCodeCacheReset == 0) {
4487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                        resetCodeCache();
4497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                        assert(workQueueLength() == 0 ||
4507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                               gDvmJit.delayCodeCacheReset != 0);
4517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                    } else {
4527a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                        LOGD("Delay the next %d tries to reset code cache",
4537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                             gDvmJit.delayCodeCacheReset);
4547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                        gDvmJit.delayCodeCacheReset--;
4557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                    }
45660c24f436d603c564d5351a6f81821f12635733cBen Cheng                }
45749ca78679485ee56d5925da122216821c668043fBen Cheng#endif
458ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } while (workQueueLength() != 0);
459ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
460ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
461ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
462ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
463ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng
4645ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    /*
4655ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * As part of detaching the thread we need to call into Java code to update
4665ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * the ThreadGroup, and we should not be in VMWAIT state while executing
4675ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * interpreted code.
4685ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     */
4695ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_RUNNING);
4705ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
47143eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden    if (gDvm.verboseShutdown)
47243eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        LOGD("Compiler thread shutting down\n");
473ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return NULL;
474ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
475ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
476ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void)
477ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
47894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
47994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmInitMutex(&gDvmJit.compilerLock);
48094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
48194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
48294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);
48394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
48494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    /* Reset the work queue */
48594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
48694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerQueueLength = 0;
48794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
48894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
489ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
49094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * Defer rest of initialization until we're sure JIT'ng makes sense. Launch
491964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * the compiler thread, which will do the real initialization if and
492964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * when it is signalled to do so.
493ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
494964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler",
495964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                                   compilerThreadStart, NULL);
496ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
497ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
498ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void)
499ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
500ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    void *threadReturn;
501ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
502ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerHandle) {
503ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
504ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.haltCompilerThread = true;
505ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
506ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmLockMutex(&gDvmJit.compilerLock);
507ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        pthread_cond_signal(&gDvmJit.compilerQueueActivity);
508ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmUnlockMutex(&gDvmJit.compilerLock);
509ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
510ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng        if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0)
511ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGW("Compiler thread join failed\n");
51243eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        else if (gDvm.verboseShutdown)
513ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGD("Compiler thread has shut down\n");
514ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
515ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
51606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
51706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
51806bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh()
51906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{
52006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActive;
52106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActivate;
52206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
52306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
52406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActive = gDvmJit.pProfTable != NULL;
52506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0));
52606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
52706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    if (jitActivate && !jitActive) {
52806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = gDvmJit.pProfTableCopy;
52906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
53006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    } else if (!jitActivate && jitActive) {
53106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = NULL;
53206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
53306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        dvmJitUnchainAll();
53406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    }
53506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee}
536