Compiler.cpp revision b88ec3cbb419b5eac23508dc6b73de2620d7521a
1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Copyright (C) 2009 The Android Open Source Project
3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License");
5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * you may not use this file except in compliance with the License.
6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * You may obtain a copy of the License at
7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *      http://www.apache.org/licenses/LICENSE-2.0
9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Unless required by applicable law or agreed to in writing, software
11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS,
12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See the License for the specific language governing permissions and
14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * limitations under the License.
15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
17ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <sys/mman.h>
18ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include <errno.h>
197c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng#include <cutils/ashmem.h>
20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
21ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "Dalvik.h"
22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "interp/Jit.h"
23ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "CompilerInternals.h"
24ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
25ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void)
26ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return gDvmJit.compilerQueueLength;
28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void)
31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind
33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           != kWorkOrderInvalid);
34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    CompilerWorkOrder work =
35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex];
36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind =
37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        kWorkOrderInvalid;
38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) {
39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkDequeueIndex = 0;
40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength--;
42f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee    if (gDvmJit.compilerQueueLength == 0) {
43b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro        dvmSignalCond(&gDvmJit.compilerQueueEmpty);
44f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee    }
45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Remember the high water mark of the queue length */
47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued)
48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength;
49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return work;
51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
53964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/*
54964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful.
55964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * This routine will not block, but simply return if it couldn't
56964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * aquire the lock or if the queue is full.
571357e94efecd485bda933270a9181035f6a39e09Ben Cheng *
581357e94efecd485bda933270a9181035f6a39e09Ben Cheng * NOTE: Make sure that the caller frees the info pointer if the return value
591357e94efecd485bda933270a9181035f6a39e09Ben Cheng * is false.
60964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */
61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
62ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int cc;
64ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
65ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int numWork;
6660c24f436d603c564d5351a6f81821f12635733cBen Cheng    bool result = true;
67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
68964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmTryLockMutex(&gDvmJit.compilerLock)) {
693e5cd17e4a0306dc976e1dc37b39d19dee4451a7Ben Cheng        return false;  // Couldn't acquire the lock
70964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /*
736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng     * Return if queue or code cache is full.
747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     */
756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE ||
766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        gDvmJit.codeCacheFull == true) {
7760c24f436d603c564d5351a6f81821f12635733cBen Cheng        result = false;
78964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto unlockAndExit;
79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (numWork = gDvmJit.compilerQueueLength,
82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           i = gDvmJit.compilerWorkDequeueIndex;
83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork > 0;
84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork--) {
85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Already enqueued */
86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (gDvmJit.compilerWorkQueue[i++].pc == pc)
87964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto unlockAndExit;
88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Wrap around */
89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (i == COMPILER_WORK_QUEUE_SIZE)
90ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            i = 0;
91ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
92ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
93ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    CompilerWorkOrder *newOrder =
94ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng        &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex];
95ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->pc = pc;
96ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->kind = kind;
97ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->info = info;
98ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.codeAddress = NULL;
99ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.discardResult =
1001f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee        (kind == kWorkOrderTraceDebug) ? true : false;
10133672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng    newOrder->result.requestingThread = dvmThreadSelf();
10233672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng
103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkEnqueueIndex++;
104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkEnqueueIndex = 0;
106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength++;
107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(cc == 0);
109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
110964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit:
111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
11260c24f436d603c564d5351a6f81821f12635733cBen Cheng    return result;
113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
11511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng/* Block until the queue length is 0, or there is a pending suspend request */
116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void)
117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
11811d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    Thread *self = dvmThreadSelf();
11911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
12111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
12211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng           self->suspendCount == 0) {
123812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        /*
124812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * Use timed wait here - more than one mutator threads may be blocked
125812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * but the compiler thread will only signal once when the queue is
126812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * emptied. Furthermore, the compiler thread may have been shutdown
127812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * so the blocked thread may never get the wakeup signal.
128812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         */
129812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock,                             1000, 0);
130ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
131ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
132ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
133ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
13460c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void)
13560c24f436d603c564d5351a6f81821f12635733cBen Cheng{
13660c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dvmCompilerTemplateStart(void);
13760c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dmvCompilerTemplateEnd(void);
1387c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    int fd;
13960c24f436d603c564d5351a6f81821f12635733cBen Cheng
14060c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Allocate the code cache */
1417c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize);
1427c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    if (fd < 0) {
1437c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        LOGE("Could not create %u-byte ashmem region for the JIT code cache",
1447c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng             gDvmJit.codeCacheSize);
1457c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        return false;
1467c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    }
1477c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize,
1487c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             PROT_READ | PROT_WRITE | PROT_EXEC,
1497c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             MAP_PRIVATE , fd, 0);
1507c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    close(fd);
15160c24f436d603c564d5351a6f81821f12635733cBen Cheng    if (gDvmJit.codeCache == MAP_FAILED) {
1527c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        LOGE("Failed to mmap the JIT code cache: %s\n", strerror(errno));
15360c24f436d603c564d5351a6f81821f12635733cBen Cheng        return false;
15460c24f436d603c564d5351a6f81821f12635733cBen Cheng    }
15560c24f436d603c564d5351a6f81821f12635733cBen Cheng
156b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    gDvmJit.pageSizeMask = getpagesize() - 1;
157b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
1587c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */
1597c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    // LOGD("Code cache starts at %p", gDvmJit.codeCache);
1607a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
16160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Copy the template code into the beginning of the code cache */
16260c24f436d603c564d5351a6f81821f12635733cBen Cheng    int templateSize = (intptr_t) dmvCompilerTemplateEnd -
16360c24f436d603c564d5351a6f81821f12635733cBen Cheng                       (intptr_t) dvmCompilerTemplateStart;
16460c24f436d603c564d5351a6f81821f12635733cBen Cheng    memcpy((void *) gDvmJit.codeCache,
16560c24f436d603c564d5351a6f81821f12635733cBen Cheng           (void *) dvmCompilerTemplateStart,
16660c24f436d603c564d5351a6f81821f12635733cBen Cheng           templateSize);
16760c24f436d603c564d5351a6f81821f12635733cBen Cheng
16872621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    /*
16972621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * Work around a CPU bug by keeping the 32-bit ARM handler code in its own
17072621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * page.
17172621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     */
17272621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) {
17372621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng        templateSize = (templateSize + 4095) & ~4095;
17472621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    }
17572621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng
17660c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.templateSize = templateSize;
17760c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = templateSize;
17860c24f436d603c564d5351a6f81821f12635733cBen Cheng
17960c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Only flush the part in the code cache that is being used now */
18060c24f436d603c564d5351a6f81821f12635733cBen Cheng    cacheflush((intptr_t) gDvmJit.codeCache,
18160c24f436d603c564d5351a6f81821f12635733cBen Cheng               (intptr_t) gDvmJit.codeCache + templateSize, 0);
182b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
183b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize,
184b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng             PROTECT_CODE_CACHE_ATTRS);
185b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
18660c24f436d603c564d5351a6f81821f12635733cBen Cheng    return true;
18760c24f436d603c564d5351a6f81821f12635733cBen Cheng}
18860c24f436d603c564d5351a6f81821f12635733cBen Cheng
1897a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print)
1907a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{
1917a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    void *fp = thread->curFrame;
1927a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    StackSaveArea* saveArea = NULL;
1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int stackLevel = 0;
1947a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
1957a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (print) {
1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid,
1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             dvmGetThreadStatusStr(thread->status),
1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache,
1997a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache ? "jit" : "interp");
2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Crawl the Dalvik stack frames to clear the returnAddr field */
2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (fp != NULL) {
2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea = SAVEAREA_FROM_FP(fp);
2047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (print) {
2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            if (dvmIsBreakFrame(fp)) {
2077a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: break frame (%p)",
2087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel, saveArea->returnAddr);
2097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            else {
2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: %s.%s%s (%p)",
2127a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel,
2137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->clazz->descriptor,
2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->name,
2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     dvmIsNativeMethod(saveArea->method) ?
2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                         " (native)" : "",
2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->returnAddr);
2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        stackLevel++;
2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea->returnAddr = NULL;
2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        assert(fp != saveArea->prevFrame);
2237a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        fp = saveArea->prevFrame;
2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Make sure the stack is fully unwound to the bottom */
2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    assert(saveArea == NULL ||
2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           (u1 *) (saveArea+1) == thread->interpStackStart);
2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng}
2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
23060c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void)
23160c24f436d603c564d5351a6f81821f12635733cBen Cheng{
23260c24f436d603c564d5351a6f81821f12635733cBen Cheng    Thread* thread;
2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    u8 startTime = dvmGetRelativeTimeUsec();
2347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int inJit = 0;
2356999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    int byteUsed = gDvmJit.codeCacheByteUsed;
23660c24f436d603c564d5351a6f81821f12635733cBen Cheng
2377a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* If any thread is found stuck in the JIT state, don't reset the cache */
23860c24f436d603c564d5351a6f81821f12635733cBen Cheng    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2396999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        /*
2406999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * Crawl the stack to wipe out the returnAddr field so that
2416999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 1) the soon-to-be-deleted code in the JIT cache won't be used
2426999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 2) or the thread stuck in the JIT land will soon return
2436999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         *    to the interpreter land
2446999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         */
2456999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        crawlDalvikStack(thread, false);
2467a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (thread->inJitCodeCache) {
2477a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            inJit++;
2487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
25060c24f436d603c564d5351a6f81821f12635733cBen Cheng
2517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (inJit) {
2526999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        LOGD("JIT code cache reset delayed (%d bytes %d/%d)",
2536999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset,
2546999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             ++gDvmJit.numCodeCacheResetDelayed);
2556999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        return;
2567a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2586999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Lock the mutex to clean up the work queue */
2596999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
2606999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
2616999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Drain the work queue to free the work orders */
2627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (workQueueLength()) {
2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        CompilerWorkOrder work = workDequeue();
2647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        free(work.info);
2657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
26760c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the JitEntry table contents to the initial unpopulated state */
26860c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmJitResetTable();
26960c24f436d603c564d5351a6f81821f12635733cBen Cheng
270b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
27160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /*
27260c24f436d603c564d5351a6f81821f12635733cBen Cheng     * Wipe out the code cache content to force immediate crashes if
27360c24f436d603c564d5351a6f81821f12635733cBen Cheng     * stale JIT'ed code is invoked.
27460c24f436d603c564d5351a6f81821f12635733cBen Cheng     */
2757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    memset((char *) gDvmJit.codeCache + gDvmJit.templateSize,
2767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           0,
2777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           gDvmJit.codeCacheByteUsed - gDvmJit.templateSize);
27860c24f436d603c564d5351a6f81821f12635733cBen Cheng    cacheflush((intptr_t) gDvmJit.codeCache,
27960c24f436d603c564d5351a6f81821f12635733cBen Cheng               (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0);
28060c24f436d603c564d5351a6f81821f12635733cBen Cheng
281b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
282b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
28360c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the current mark of used bytes to the end of template code */
28460c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
28560c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.numCompilations = 0;
28660c24f436d603c564d5351a6f81821f12635733cBen Cheng
28760c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the work queue */
28860c24f436d603c564d5351a6f81821f12635733cBen Cheng    memset(gDvmJit.compilerWorkQueue, 0,
28960c24f436d603c564d5351a6f81821f12635733cBen Cheng           sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
29060c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
29160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerQueueLength = 0;
29260c24f436d603c564d5351a6f81821f12635733cBen Cheng
2936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Reset the IC patch work queue */
2946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerICPatchLock);
2956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    gDvmJit.compilerICPatchIndex = 0;
2966999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
2976999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
29860c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* All clear now */
29960c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheFull = false;
30060c24f436d603c564d5351a6f81821f12635733cBen Cheng
3016999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
3027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
3036999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    LOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)",
3046999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         (dvmGetRelativeTimeUsec() - startTime) / 1000,
3056999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         byteUsed, ++gDvmJit.numCodeCacheReset,
3066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         gDvmJit.numCodeCacheResetDelayed);
3076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng}
3086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
3096999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/*
3106999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently
3116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do:
3126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it
3136999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng *    from scratch.
3146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders.
3156999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */
3166999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void)
3176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{
3186999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    if (gDvmJit.codeCacheFull) {
3196999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        resetCodeCache();
3206999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    }
3216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmCompilerPatchInlineCache();
32260c24f436d603c564d5351a6f81821f12635733cBen Cheng}
32360c24f436d603c564d5351a6f81821f12635733cBen Cheng
324964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeebool compilerThreadStartup(void)
325964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{
326964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    JitEntry *pJitTable = NULL;
327964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned char *pJitProfTable = NULL;
328964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned int i;
329964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
330964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!dvmCompilerArchInit())
331964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
332964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
333964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
334964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Setup the code cache if we have not inherited a valid code cache
335964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * from the zygote.
336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (gDvmJit.codeCache == NULL) {
338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        if (!dvmCompilerSetupCodeCache())
339964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto fail;
340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Allocate the initial arena block */
343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmCompilerHeapInit() == false) {
344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
347964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
3491357e94efecd485bda933270a9181035f6a39e09Ben Cheng#if defined(WITH_JIT_TUNING)
350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Track method-level compilation statistics */
351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
352452efba773098c070c6bd623124e1fed21342ba4Ben Cheng    gDvm.verboseShutdown = true;
3531357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif
354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Set up the JitTable */
358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Power of 2? */
360964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(gDvmJit.jitTableSize &&
361964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee           !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
362964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
363964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmInitMutex(&gDvmJit.tableLock);
364964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
365964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitTable = (JitEntry*)
366964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
367964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitTable) {
368964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit table allocation failed\n");
369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
370964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
371964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
372964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
373964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * NOTE: the profile table must only be allocated once, globally.
374964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Profiling is turned on and off by nulling out gDvm.pJitProfTable
375964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and then restoring its original value.  However, this action
376964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * is not syncronized for speed so threads may continue to hold
377964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and update the profile table after profiling has been turned
378964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * off by null'ng the global pointer.  Be aware.
379964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
380964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
381964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitProfTable) {
382964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit prof table allocation failed\n");
383964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
384964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
385964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
386964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE);
387964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    for (i=0; i < gDvmJit.jitTableSize; i++) {
388964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee       pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
389964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
390964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Is chain field wide enough for termination pattern? */
391964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
392964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
393964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.pJitEntryTable = pJitTable;
394964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableEntriesUsed = 0;
396964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.compilerHighWater =
397964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
398a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
399a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * If the VM is launched with wait-on-the-debugger, we will need to hide
400a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * the profile table here
401a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
402a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable;
40306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    gDvmJit.pProfTableCopy = pJitProfTable;
404964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
405964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
406964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Signal running threads to refresh their cached pJitTable pointers */
407964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmSuspendAllThreads(SUSPEND_FOR_REFRESH);
408964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmResumeAllThreads(SUSPEND_FOR_REFRESH);
409dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
410dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /* Enable signature breakpoints by customizing the following code */
411dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#if defined(SIGNATURE_BREAKPOINT)
412dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
413dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Suppose one sees the following native crash in the bugreport:
414dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): Build fingerprint: 'unknown'
415dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): pid: 2468, tid: 2507  >>> com.google.android.gallery3d
416dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): signal 11 (SIGSEGV), fault addr 00001400
417dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r0 44ea7190  r1 44e4f7b8  r2 44ebc710  r3 00000000
418dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r4 00000a00  r5 41862dec  r6 4710dc10  r7 00000280
419dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r8 ad010f40  r9 46a37a12  10 001116b0  fp 42a78208
420dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  ip 00000090  sp 4710dbc8  lr ad060e67  pc 46b90682
421dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * cpsr 00000030
422dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #00  pc 46b90682 /dev/ashmem/dalvik-jit-code-cache
423dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #01  pc 00060e62  /system/lib/libdvm.so
424dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
425dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): code around pc:
426dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68
427dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e
428dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028
429dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b
430dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70
431dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
432dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Clearly it is a JIT bug. To find out which translation contains the
433dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offending code, the content of the memory dump around the faulting PC
434dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time
435dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * when a similar compilation is being created, the JIT compiler replay the
436dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * trace in the verbose mode and one can investigate the instruction
437dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * sequence in details.
438dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
439dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The length of the signature may need additional experiments to determine.
440dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The rule of thumb is don't include PC-relative instructions in the
441dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * signature since it may be affected by the alignment of the compiled code.
442dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * However, a signature that's too short might increase the chance of false
443dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * positive matches. Using gdbjithelper to disassembly the memory content
444dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * first might be a good companion approach.
445dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
446dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * For example, if the next 4 words starting from 46b90680 is pasted into
447dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * the data structure:
448dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
449dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
450dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpointSize = 4;
451dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint =
452dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng        malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize);
453dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[0] = 0x512000bc;
454dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[1] = 0x37016eaf;
455dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[2] = 0x6ea866af;
456dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[3] = 0x6f696028;
457dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
458dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
459dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The following log will be printed when a match is found in subsequent
460dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * testings:
461dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
462dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words)
463dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): --------
464dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems,
465dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offset 0x1f7
466dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26
467dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42
468dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0)
469dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1)
470dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0)
471dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0)
472dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0)
473dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10)
474dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624
475dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8
476dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * blocks
477dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
478dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
479dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x20 (0020): ldr     r0, [r5, #52]
480dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x22 (0022): ldr     r2, [pc, #96]
481dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x24 (0024): cmp     r0, #0
482dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x26 (0026): beq     0x00000034
483dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x28 (0028): ldr     r1, [r1, #0]
484dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2a (002a): ldr     r0, [r0, #0]
485dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2c (002c): blx     r2
486dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2e (002e): cmp     r0, #0
487dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x30 (0030): beq     0x00000050
488dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x32 (0032): ldr     r0, [r5, #52]
489dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x34 (0034): lsls    r4, r7, #2
490dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x36 (0036): str     r0, [r4, r4]
491dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0)
492dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0195:
493dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26,
494dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * v26, (#1)
495dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x38 (0038): ldr     r7, [r5, #104]
496dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3a (003a): adds    r7, r7, #1
497dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3c (003c): str     r7, [r5, #104]
498dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0)
499dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0165:
500dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26,
501dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * (#0)
502dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3e (003e): ldr     r0, [r5, #104]
503dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x40 (0040): str     r0, [r5, #0]
504dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
505dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The "str r0, [r4, r4]" is indeed the culprit of the native crash.
506dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
507dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#endif
508dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
509964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return true;
510964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
511964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail:
512964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return false;
513964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
514964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee}
515964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
516ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg)
517ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
5185ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_VMWAIT);
5195ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
520b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee    /*
521eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * If we're not running stand-alone, wait a little before
522eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * recieving translation requests on the assumption that process start
523eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * up code isn't worth compiling.  We'll resume when the framework
524eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * signals us that the first screen draw has happened, or the timer
525eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * below expires (to catch daemons).
526f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     *
527f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * There is a theoretical race between the callback to
528f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * VMRuntime.startJitCompiation and when the compiler thread reaches this
529f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * point. In case the callback happens earlier, in order not to permanently
530f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * hold the system_server (which is not using the timed wait) in
531f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * interpreter-only mode we bypass the delay here.
532b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee     */
533f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng    if (gDvmJit.runningInAndroidFramework &&
534f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        !gDvmJit.alreadyEnabledViaFramework) {
535f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        /*
536f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the current VM instance is the system server (detected by having
537f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * 0 in gDvm.systemServerPid), we will use the indefinite wait on the
538f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * conditional variable to determine whether to start the JIT or not.
539f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the system server detects that the whole system is booted in
540f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * safe mode, the conditional variable will never be signaled and the
541f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * system server will remain in the interpreter-only mode. All
542f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * subsequent apps will be started with the --enable-safemode flag
543f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * explicitly appended.
544f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         */
545f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        if (gDvm.systemServerPid == 0) {
546f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
547f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
548f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                              &gDvmJit.compilerLock);
549f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
550f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            LOGD("JIT started for system_server");
551f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        } else {
552f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
553f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            /*
554f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * TUNING: experiment with the delay & perhaps make it
555f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * target-specific
556f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             */
557f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
558f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                                 &gDvmJit.compilerLock, 3000, 0);
559f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
560f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        }
561eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        if (gDvmJit.haltCompilerThread) {
562eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee             return NULL;
563eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        }
56494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    }
56594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
566964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    compilerThreadStartup();
567b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee
568ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
569ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
570ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Since the compiler thread will not touch any objects on the heap once
571ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * being created, we just fake its state as VMWAIT so that it can be a
572ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * bit late when there is suspend request pending.
573ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
574ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (!gDvmJit.haltCompilerThread) {
575ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (workQueueLength() == 0) {
576ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            int cc;
577ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
578ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(cc == 0);
579ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
580ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                              &gDvmJit.compilerLock);
581ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            continue;
582ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
583ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            do {
584ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                CompilerWorkOrder work = workDequeue();
585ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmUnlockMutex(&gDvmJit.compilerLock);
586978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
58786717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng                u8 startTime = dvmGetRelativeTimeUsec();
58886717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
589964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                /*
590964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * Check whether there is a suspend request on me.  This
591964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * is necessary to allow a clean shutdown.
59211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 *
59311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * However, in the blocking stress testing mode, let the
59411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * compiler thread continue doing compilations to unblock
59511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * other requesting threads. This may occasionally cause
59611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * shutdown from proceeding cleanly in the standalone invocation
59711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * of the vm but this should be acceptable.
598964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 */
59911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                if (!gDvmJit.blockingMode)
600ab227f7a9a9d4c7837ee7a5cc9f07b665d516bacAndy McFadden                    dvmCheckSuspendPending(dvmThreadSelf());
6012717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                /* Is JitTable filling up? */
6022717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                if (gDvmJit.jitTableEntriesUsed >
6032717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
6046999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    bool resizeFail =
6056999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                        dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
6066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    /*
6076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * If the jit table is full, consider it's time to reset
6086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * the code cache too.
6096999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     */
6106999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    gDvmJit.codeCacheFull |= resizeFail;
6112717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                }
612ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                if (gDvmJit.haltCompilerThread) {
613ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    LOGD("Compiler shutdown in progress - discarding request");
6146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                } else if (!gDvmJit.codeCacheFull) {
615fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    bool compileOK = false;
616fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    jmp_buf jmpBuf;
617fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    work.bailPtr = &jmpBuf;
618fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    bool aborted = setjmp(jmpBuf);
619fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    if (!aborted) {
620fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                        compileOK = dvmCompilerDoWork(&work);
621ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    }
622fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    if (aborted || !compileOK) {
623fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                        dvmCompilerArenaReset();
624bd0472480c6e876198fe19c4ffa22350c0ce57daBill Buzbee                        work.result.codeAddress = dvmCompilerGetInterpretTemplate();
625fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    } else if (!work.result.discardResult) {
62660c24f436d603c564d5351a6f81821f12635733cBen Cheng                        dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
62760c24f436d603c564d5351a6f81821f12635733cBen Cheng                                          work.result.instructionSet);
62860c24f436d603c564d5351a6f81821f12635733cBen Cheng                    }
629ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                }
630ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                free(work.info);
631978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
63286717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng                gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime;
63386717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
634ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmLockMutex(&gDvmJit.compilerLock);
635ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } while (workQueueLength() != 0);
636ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
637ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
638ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
639ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
640ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng
6415ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    /*
6425ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * As part of detaching the thread we need to call into Java code to update
6435ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * the ThreadGroup, and we should not be in VMWAIT state while executing
6445ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * interpreted code.
6455ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     */
6465ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_RUNNING);
6475ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
64843eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden    if (gDvm.verboseShutdown)
64943eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        LOGD("Compiler thread shutting down\n");
650ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return NULL;
651ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
652ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
653ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void)
654ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
65594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
65694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmInitMutex(&gDvmJit.compilerLock);
6576999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmInitMutex(&gDvmJit.compilerICPatchLock);
658b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    dvmInitMutex(&gDvmJit.codeCacheProtectionLock);
65994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
66094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
66194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);
66294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
66394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    /* Reset the work queue */
66494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
66594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerQueueLength = 0;
66694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
66794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
668ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
66994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * Defer rest of initialization until we're sure JIT'ng makes sense. Launch
670964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * the compiler thread, which will do the real initialization if and
671964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * when it is signalled to do so.
672ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
673964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler",
674964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                                   compilerThreadStart, NULL);
675ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
676ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
677ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void)
678ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
679ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    void *threadReturn;
680ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
6812fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Disable new translation requests */
6822fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTable = NULL;
6832fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTableCopy = NULL;
6842fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee
68588a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng    if (gDvm.verboseShutdown) {
68688a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        dvmCompilerDumpStats();
68788a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        while (gDvmJit.compilerQueueLength)
68888a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng          sleep(5);
68988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng    }
69088a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng
691ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerHandle) {
692ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
693ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.haltCompilerThread = true;
694ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
695ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmLockMutex(&gDvmJit.compilerLock);
696ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        pthread_cond_signal(&gDvmJit.compilerQueueActivity);
697ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmUnlockMutex(&gDvmJit.compilerLock);
698ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
699ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng        if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0)
700ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGW("Compiler thread join failed\n");
70143eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        else if (gDvm.verboseShutdown)
702ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGD("Compiler thread has shut down\n");
703ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
70406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
7052fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Break loops within the translation cache */
7062fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    dvmJitUnchainAll();
70796cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee
7082fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /*
7092fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * NOTE: our current implementatation doesn't allow for the compiler
7102fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * thread to be restarted after it exits here.  We aren't freeing
7112fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * the JitTable or the ProfTable because threads which still may be
7122fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * running or in the process of shutting down may hold references to
7132fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * them.
7142fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     */
71596cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee}
71606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
71706bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh()
71806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{
71906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActive;
72006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActivate;
7213e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    bool needUnchain = false;
72206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
723a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
724a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * The tableLock might not be initialized yet by the compiler thread if
725a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * debugger is attached from the very beginning of the VM launch. If
726a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * pProfTableCopy is NULL, the lock is not initialized yet and we don't
727a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * need to refresh anything either.
728a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
729a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    if (gDvmJit.pProfTableCopy == NULL) {
730a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        return;
731a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    }
732a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng
73306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
73406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActive = gDvmJit.pProfTable != NULL;
735c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden
736c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
73706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActivate = !(gDvm.debuggerActive || (gDvm.activeProfilers > 0));
738c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden#elif defined(WITH_DEBUGGER)
739c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden    jitActivate = !gDvm.debuggerActive;
740c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden#elif defined(WITH_PROFILER)
741c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden    jitActivate = !(gDvm.activeProfilers > 0);
742c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden#else
743c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden    jitActivate = true;
744c95e0fbce4f77b2b08eb48205e405793de0d4248Andy McFadden#endif
74506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
74606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    if (jitActivate && !jitActive) {
74706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = gDvmJit.pProfTableCopy;
74806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    } else if (!jitActivate && jitActive) {
74906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = NULL;
7503e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        needUnchain = true;
75106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    }
7523e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
7533e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    if (needUnchain)
7543e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        dvmJitUnchainAll();
75506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee}
756