Compiler.cpp revision 18fba346582c08d81aa96d9508c0e935bad5f36f
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;
987a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newOrder->result.methodCompilationAborted = NULL;
99ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.codeAddress = NULL;
100ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.discardResult =
1011f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee        (kind == kWorkOrderTraceDebug) ? true : false;
10218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    newOrder->result.cacheVersion = gDvmJit.cacheVersion;
10333672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng    newOrder->result.requestingThread = dvmThreadSelf();
10433672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng
105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkEnqueueIndex++;
106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkEnqueueIndex = 0;
108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength++;
109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(cc == 0);
111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
112964a7b06a9134947b5985c7f712d18d57ed665d2Bill BuzbeeunlockAndExit:
113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
11460c24f436d603c564d5351a6f81821f12635733cBen Cheng    return result;
115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
11711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng/* Block until the queue length is 0, or there is a pending suspend request */
118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void)
119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
12011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    Thread *self = dvmThreadSelf();
12111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
12311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
12411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng           self->suspendCount == 0) {
125812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        /*
126812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * Use timed wait here - more than one mutator threads may be blocked
127812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * but the compiler thread will only signal once when the queue is
128812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * emptied. Furthermore, the compiler thread may have been shutdown
129812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * so the blocked thread may never get the wakeup signal.
130812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         */
131812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock,                             1000, 0);
132ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
133ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
134ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
135ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
13660c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void)
13760c24f436d603c564d5351a6f81821f12635733cBen Cheng{
13860c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dvmCompilerTemplateStart(void);
13960c24f436d603c564d5351a6f81821f12635733cBen Cheng    extern void dmvCompilerTemplateEnd(void);
1407c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    int fd;
14160c24f436d603c564d5351a6f81821f12635733cBen Cheng
14260c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Allocate the code cache */
1437c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize);
1447c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    if (fd < 0) {
1457c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        LOGE("Could not create %u-byte ashmem region for the JIT code cache",
1467c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng             gDvmJit.codeCacheSize);
1477c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        return false;
1487c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    }
1497c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize,
1507c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             PROT_READ | PROT_WRITE | PROT_EXEC,
1517c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             MAP_PRIVATE , fd, 0);
1527c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    close(fd);
15360c24f436d603c564d5351a6f81821f12635733cBen Cheng    if (gDvmJit.codeCache == MAP_FAILED) {
1547c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        LOGE("Failed to mmap the JIT code cache: %s\n", strerror(errno));
15560c24f436d603c564d5351a6f81821f12635733cBen Cheng        return false;
15660c24f436d603c564d5351a6f81821f12635733cBen Cheng    }
15760c24f436d603c564d5351a6f81821f12635733cBen Cheng
158b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    gDvmJit.pageSizeMask = getpagesize() - 1;
159b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
1607c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */
1617c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    // LOGD("Code cache starts at %p", gDvmJit.codeCache);
1627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
16360c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Copy the template code into the beginning of the code cache */
16460c24f436d603c564d5351a6f81821f12635733cBen Cheng    int templateSize = (intptr_t) dmvCompilerTemplateEnd -
16560c24f436d603c564d5351a6f81821f12635733cBen Cheng                       (intptr_t) dvmCompilerTemplateStart;
16660c24f436d603c564d5351a6f81821f12635733cBen Cheng    memcpy((void *) gDvmJit.codeCache,
16760c24f436d603c564d5351a6f81821f12635733cBen Cheng           (void *) dvmCompilerTemplateStart,
16860c24f436d603c564d5351a6f81821f12635733cBen Cheng           templateSize);
16960c24f436d603c564d5351a6f81821f12635733cBen Cheng
17072621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    /*
17172621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * Work around a CPU bug by keeping the 32-bit ARM handler code in its own
17272621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * page.
17372621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     */
17472621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) {
17572621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng        templateSize = (templateSize + 4095) & ~4095;
17672621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    }
17772621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng
17860c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.templateSize = templateSize;
17960c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = templateSize;
18060c24f436d603c564d5351a6f81821f12635733cBen Cheng
18160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Only flush the part in the code cache that is being used now */
18213fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache,
18313fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          (intptr_t) gDvmJit.codeCache + templateSize, 0);
184b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
1851f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng    int result = mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize,
1861f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng                          PROTECT_CODE_CACHE_ATTRS);
1871f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng
1881f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng    if (result == -1) {
1891f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng        LOGE("Failed to remove the write permission for the code cache");
1901f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng        dvmAbort();
1911f3da0b96578b9d9e4f9e38577d3365b7a49147bBen Cheng    }
192b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
19360c24f436d603c564d5351a6f81821f12635733cBen Cheng    return true;
19460c24f436d603c564d5351a6f81821f12635733cBen Cheng}
19560c24f436d603c564d5351a6f81821f12635733cBen Cheng
1967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print)
1977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{
1987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    void *fp = thread->curFrame;
1997a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    StackSaveArea* saveArea = NULL;
2007a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int stackLevel = 0;
2017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2027a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (print) {
2037a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        LOGD("Crawling tid %d (%s / %p %s)", thread->systemTid,
2047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             dvmGetThreadStatusStr(thread->status),
2057a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache,
2067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache ? "jit" : "interp");
2077a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2087a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Crawl the Dalvik stack frames to clear the returnAddr field */
2097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (fp != NULL) {
2107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea = SAVEAREA_FROM_FP(fp);
2117a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2127a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (print) {
213fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            if (dvmIsBreakFrame((u4*)fp)) {
2147a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: break frame (%p)",
2157a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel, saveArea->returnAddr);
2167a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2177a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            else {
2187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                LOGD("  #%d: %s.%s%s (%p)",
2197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel,
2207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->clazz->descriptor,
2217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->name,
2227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     dvmIsNativeMethod(saveArea->method) ?
2237a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                         " (native)" : "",
2247a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->returnAddr);
2257a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2267a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2277a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        stackLevel++;
2287a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea->returnAddr = NULL;
2297a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        assert(fp != saveArea->prevFrame);
2307a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        fp = saveArea->prevFrame;
2317a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2327a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Make sure the stack is fully unwound to the bottom */
2337a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    assert(saveArea == NULL ||
2347a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           (u1 *) (saveArea+1) == thread->interpStackStart);
2357a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng}
2367a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
23760c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void)
23860c24f436d603c564d5351a6f81821f12635733cBen Cheng{
23960c24f436d603c564d5351a6f81821f12635733cBen Cheng    Thread* thread;
2407a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    u8 startTime = dvmGetRelativeTimeUsec();
2417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int inJit = 0;
2426999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    int byteUsed = gDvmJit.codeCacheByteUsed;
24360c24f436d603c564d5351a6f81821f12635733cBen Cheng
2447a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* If any thread is found stuck in the JIT state, don't reset the cache */
24560c24f436d603c564d5351a6f81821f12635733cBen Cheng    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2466999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        /*
2476999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * Crawl the stack to wipe out the returnAddr field so that
2486999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 1) the soon-to-be-deleted code in the JIT cache won't be used
2496999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 2) or the thread stuck in the JIT land will soon return
2506999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         *    to the interpreter land
2516999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         */
2526999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        crawlDalvikStack(thread, false);
2537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (thread->inJitCodeCache) {
2547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            inJit++;
2557a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2567a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
25760c24f436d603c564d5351a6f81821f12635733cBen Cheng
2587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (inJit) {
2596999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        LOGD("JIT code cache reset delayed (%d bytes %d/%d)",
2606999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset,
2616999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             ++gDvmJit.numCodeCacheResetDelayed);
2626999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        return;
2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2656999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Lock the mutex to clean up the work queue */
2666999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
2676999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
26818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    /* Update the translation cache version */
26918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    gDvmJit.cacheVersion++;
27018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee
2716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Drain the work queue to free the work orders */
2727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (workQueueLength()) {
2737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        CompilerWorkOrder work = workDequeue();
2747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        free(work.info);
2757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
27760c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the JitEntry table contents to the initial unpopulated state */
27860c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmJitResetTable();
27960c24f436d603c564d5351a6f81821f12635733cBen Cheng
280b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
28160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /*
28260c24f436d603c564d5351a6f81821f12635733cBen Cheng     * Wipe out the code cache content to force immediate crashes if
28360c24f436d603c564d5351a6f81821f12635733cBen Cheng     * stale JIT'ed code is invoked.
28460c24f436d603c564d5351a6f81821f12635733cBen Cheng     */
2857a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    memset((char *) gDvmJit.codeCache + gDvmJit.templateSize,
2867a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           0,
2877a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           gDvmJit.codeCacheByteUsed - gDvmJit.templateSize);
28813fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache,
28913fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          (intptr_t) gDvmJit.codeCache +
29013fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          gDvmJit.codeCacheByteUsed, 0);
29160c24f436d603c564d5351a6f81821f12635733cBen Cheng
292b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
293b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
29460c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the current mark of used bytes to the end of template code */
29560c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
29660c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.numCompilations = 0;
29760c24f436d603c564d5351a6f81821f12635733cBen Cheng
29860c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the work queue */
29960c24f436d603c564d5351a6f81821f12635733cBen Cheng    memset(gDvmJit.compilerWorkQueue, 0,
30060c24f436d603c564d5351a6f81821f12635733cBen Cheng           sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
30160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
30260c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerQueueLength = 0;
30360c24f436d603c564d5351a6f81821f12635733cBen Cheng
3046999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Reset the IC patch work queue */
3056999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerICPatchLock);
3066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    gDvmJit.compilerICPatchIndex = 0;
3076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
3086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
30960c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* All clear now */
31060c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheFull = false;
31160c24f436d603c564d5351a6f81821f12635733cBen Cheng
3126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
3137a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
3146999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    LOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)",
3156999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         (dvmGetRelativeTimeUsec() - startTime) / 1000,
3166999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         byteUsed, ++gDvmJit.numCodeCacheReset,
3176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         gDvmJit.numCodeCacheResetDelayed);
3186999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng}
3196999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
3206999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/*
3216999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently
3226999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do:
3236999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it
3246999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng *    from scratch.
3256999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders.
3266999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */
3276999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void)
3286999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{
3296999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    if (gDvmJit.codeCacheFull) {
3306999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        resetCodeCache();
3316999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    }
3326999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmCompilerPatchInlineCache();
33360c24f436d603c564d5351a6f81821f12635733cBen Cheng}
33460c24f436d603c564d5351a6f81821f12635733cBen Cheng
335953a0ed4e507fd6e756aa3e5c671bee80d7e9b3eAndy McFaddenstatic bool compilerThreadStartup(void)
336964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{
337964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    JitEntry *pJitTable = NULL;
338964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned char *pJitProfTable = NULL;
3392e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    JitTraceProfCounters *pJitTraceProfCounters = NULL;
340964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned int i;
341964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
342964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!dvmCompilerArchInit())
343964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
344964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
345964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
346964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Setup the code cache if we have not inherited a valid code cache
347964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * from the zygote.
348964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
349964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (gDvmJit.codeCache == NULL) {
350964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        if (!dvmCompilerSetupCodeCache())
351964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto fail;
352964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
353964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
354964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Allocate the initial arena block */
355964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmCompilerHeapInit() == false) {
356964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
357964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
358964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
359964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
360964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
361964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Track method-level compilation statistics */
362964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
3637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
365452efba773098c070c6bd623124e1fed21342ba4Ben Cheng    gDvm.verboseShutdown = true;
3661357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif
367964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
368964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
369964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
370964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Set up the JitTable */
371964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
372964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Power of 2? */
373964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(gDvmJit.jitTableSize &&
374964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee           !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
375964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
376964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmInitMutex(&gDvmJit.tableLock);
377964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
378964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitTable = (JitEntry*)
379964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
380964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitTable) {
381964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit table allocation failed\n");
382964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
383964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
384964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
385964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
386964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * NOTE: the profile table must only be allocated once, globally.
387964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Profiling is turned on and off by nulling out gDvm.pJitProfTable
388964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and then restoring its original value.  However, this action
389964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * is not syncronized for speed so threads may continue to hold
390964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and update the profile table after profiling has been turned
391964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * off by null'ng the global pointer.  Be aware.
392964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
393964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
394964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitProfTable) {
395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        LOGE("jit prof table allocation failed\n");
396964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
397964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
398964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
399964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE);
400964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    for (i=0; i < gDvmJit.jitTableSize; i++) {
401964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee       pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
402964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
403964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Is chain field wide enough for termination pattern? */
404964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
405964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
4062e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    /* Allocate the trace profiling structure */
4072e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    pJitTraceProfCounters = (JitTraceProfCounters*)
4082e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                             calloc(1, sizeof(*pJitTraceProfCounters));
4092e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if (!pJitTraceProfCounters) {
4102e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        LOGE("jit trace prof counters allocation failed\n");
4112e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
4122e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        goto fail;
4132e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    }
4142e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
415964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.pJitEntryTable = pJitTable;
416964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
417964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableEntriesUsed = 0;
418964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.compilerHighWater =
419964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
420a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
421a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * If the VM is launched with wait-on-the-debugger, we will need to hide
422a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * the profile table here
423a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
424a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable;
42506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    gDvmJit.pProfTableCopy = pJitProfTable;
4262e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    gDvmJit.pJitTraceProfCounters = pJitTraceProfCounters;
427964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
429964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Signal running threads to refresh their cached pJitTable pointers */
430964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmSuspendAllThreads(SUSPEND_FOR_REFRESH);
431964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmResumeAllThreads(SUSPEND_FOR_REFRESH);
432dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
433dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /* Enable signature breakpoints by customizing the following code */
434dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#if defined(SIGNATURE_BREAKPOINT)
435dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
436dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Suppose one sees the following native crash in the bugreport:
437dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): Build fingerprint: 'unknown'
438dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): pid: 2468, tid: 2507  >>> com.google.android.gallery3d
439dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): signal 11 (SIGSEGV), fault addr 00001400
440dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r0 44ea7190  r1 44e4f7b8  r2 44ebc710  r3 00000000
441dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r4 00000a00  r5 41862dec  r6 4710dc10  r7 00000280
442dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r8 ad010f40  r9 46a37a12  10 001116b0  fp 42a78208
443dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  ip 00000090  sp 4710dbc8  lr ad060e67  pc 46b90682
444dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * cpsr 00000030
445dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #00  pc 46b90682 /dev/ashmem/dalvik-jit-code-cache
446dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #01  pc 00060e62  /system/lib/libdvm.so
447dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
448dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): code around pc:
449dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68
450dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e
451dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028
452dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b
453dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70
454dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
455dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Clearly it is a JIT bug. To find out which translation contains the
456dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offending code, the content of the memory dump around the faulting PC
457dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time
458dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * when a similar compilation is being created, the JIT compiler replay the
459dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * trace in the verbose mode and one can investigate the instruction
460dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * sequence in details.
461dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
462dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The length of the signature may need additional experiments to determine.
463dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The rule of thumb is don't include PC-relative instructions in the
464dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * signature since it may be affected by the alignment of the compiled code.
465dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * However, a signature that's too short might increase the chance of false
466dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * positive matches. Using gdbjithelper to disassembly the memory content
467dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * first might be a good companion approach.
468dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
469dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * For example, if the next 4 words starting from 46b90680 is pasted into
470dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * the data structure:
471dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
472dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
473dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpointSize = 4;
474dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint =
475dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng        malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize);
476dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[0] = 0x512000bc;
477dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[1] = 0x37016eaf;
478dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[2] = 0x6ea866af;
479dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[3] = 0x6f696028;
480dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
481dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
482dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The following log will be printed when a match is found in subsequent
483dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * testings:
484dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
485dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words)
486dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): --------
487dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems,
488dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offset 0x1f7
489dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26
490dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42
491dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0)
492dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1)
493dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0)
494dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0)
495dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0)
496dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10)
497dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624
498dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8
499dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * blocks
500dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
501dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
502dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x20 (0020): ldr     r0, [r5, #52]
503dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x22 (0022): ldr     r2, [pc, #96]
504dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x24 (0024): cmp     r0, #0
505dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x26 (0026): beq     0x00000034
506dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x28 (0028): ldr     r1, [r1, #0]
507dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2a (002a): ldr     r0, [r0, #0]
508dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2c (002c): blx     r2
509dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2e (002e): cmp     r0, #0
510dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x30 (0030): beq     0x00000050
511dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x32 (0032): ldr     r0, [r5, #52]
512dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x34 (0034): lsls    r4, r7, #2
513dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x36 (0036): str     r0, [r4, r4]
514dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0)
515dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0195:
516dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26,
517dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * v26, (#1)
518dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x38 (0038): ldr     r7, [r5, #104]
519dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3a (003a): adds    r7, r7, #1
520dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3c (003c): str     r7, [r5, #104]
521dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0)
522dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0165:
523dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26,
524dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * (#0)
525dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3e (003e): ldr     r0, [r5, #104]
526dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x40 (0040): str     r0, [r5, #0]
527dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
528dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The "str r0, [r4, r4]" is indeed the culprit of the native crash.
529dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
530dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#endif
531dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
532964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return true;
533964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
534964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail:
535964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return false;
536964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
537964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee}
538964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
539ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg)
540ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
5415ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_VMWAIT);
5425ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
543b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee    /*
544eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * If we're not running stand-alone, wait a little before
545eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * recieving translation requests on the assumption that process start
546eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * up code isn't worth compiling.  We'll resume when the framework
547eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * signals us that the first screen draw has happened, or the timer
548eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * below expires (to catch daemons).
549f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     *
550f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * There is a theoretical race between the callback to
551f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * VMRuntime.startJitCompiation and when the compiler thread reaches this
552f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * point. In case the callback happens earlier, in order not to permanently
553f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * hold the system_server (which is not using the timed wait) in
554f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * interpreter-only mode we bypass the delay here.
555b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee     */
556f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng    if (gDvmJit.runningInAndroidFramework &&
557f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        !gDvmJit.alreadyEnabledViaFramework) {
558f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        /*
559f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the current VM instance is the system server (detected by having
560f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * 0 in gDvm.systemServerPid), we will use the indefinite wait on the
561f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * conditional variable to determine whether to start the JIT or not.
562f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the system server detects that the whole system is booted in
563f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * safe mode, the conditional variable will never be signaled and the
564f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * system server will remain in the interpreter-only mode. All
565f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * subsequent apps will be started with the --enable-safemode flag
566f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * explicitly appended.
567f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         */
568f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        if (gDvm.systemServerPid == 0) {
569f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
570f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
571f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                              &gDvmJit.compilerLock);
572f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
573f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            LOGD("JIT started for system_server");
574f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        } else {
575f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
576f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            /*
577f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * TUNING: experiment with the delay & perhaps make it
578f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * target-specific
579f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             */
580f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
581f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                                 &gDvmJit.compilerLock, 3000, 0);
582f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
583f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        }
584eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        if (gDvmJit.haltCompilerThread) {
585eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee             return NULL;
586eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        }
58794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    }
58894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
589964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    compilerThreadStartup();
590b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee
591ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
592ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
593ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Since the compiler thread will not touch any objects on the heap once
594ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * being created, we just fake its state as VMWAIT so that it can be a
595ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * bit late when there is suspend request pending.
596ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
597ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (!gDvmJit.haltCompilerThread) {
598ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (workQueueLength() == 0) {
599ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            int cc;
600ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
601ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(cc == 0);
602ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
603ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                              &gDvmJit.compilerLock);
604ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            continue;
605ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
606ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            do {
607ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                CompilerWorkOrder work = workDequeue();
608ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmUnlockMutex(&gDvmJit.compilerLock);
609978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
61086717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng                u8 startTime = dvmGetRelativeTimeUsec();
61186717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
612964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                /*
613964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * Check whether there is a suspend request on me.  This
614964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * is necessary to allow a clean shutdown.
61511d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 *
61611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * However, in the blocking stress testing mode, let the
61711d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * compiler thread continue doing compilations to unblock
61811d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * other requesting threads. This may occasionally cause
61911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * shutdown from proceeding cleanly in the standalone invocation
62011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * of the vm but this should be acceptable.
621964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 */
62211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                if (!gDvmJit.blockingMode)
623ab227f7a9a9d4c7837ee7a5cc9f07b665d516bacAndy McFadden                    dvmCheckSuspendPending(dvmThreadSelf());
6242717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                /* Is JitTable filling up? */
6252717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                if (gDvmJit.jitTableEntriesUsed >
6262717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
6276999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    bool resizeFail =
6286999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                        dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
6296999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    /*
6306999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * If the jit table is full, consider it's time to reset
6316999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * the code cache too.
6326999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     */
6336999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    gDvmJit.codeCacheFull |= resizeFail;
6342717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                }
635ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                if (gDvmJit.haltCompilerThread) {
636ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    LOGD("Compiler shutdown in progress - discarding request");
6376999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                } else if (!gDvmJit.codeCacheFull) {
638fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    jmp_buf jmpBuf;
639fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    work.bailPtr = &jmpBuf;
640fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    bool aborted = setjmp(jmpBuf);
641fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    if (!aborted) {
6422e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                        bool codeCompiled = dvmCompilerDoWork(&work);
6432e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                        if (codeCompiled && !work.result.discardResult &&
6442e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                                work.result.codeAddress) {
6452e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                            dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
6462e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                                              work.result.instructionSet,
6472e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                                              work.result.profileCodeSize);
6482e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                        }
64960c24f436d603c564d5351a6f81821f12635733cBen Cheng                    }
6502e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                    dvmCompilerArenaReset();
651ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                }
652ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                free(work.info);
653978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
65486717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng                gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime;
65586717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
656ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmLockMutex(&gDvmJit.compilerLock);
657ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } while (workQueueLength() != 0);
658ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
659ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
660ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
661ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
662ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng
6635ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    /*
6645ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * As part of detaching the thread we need to call into Java code to update
6655ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * the ThreadGroup, and we should not be in VMWAIT state while executing
6665ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * interpreted code.
6675ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     */
6685ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_RUNNING);
6695ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
67043eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden    if (gDvm.verboseShutdown)
67143eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        LOGD("Compiler thread shutting down\n");
672ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return NULL;
673ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
674ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
675ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void)
676ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
67794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
67894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmInitMutex(&gDvmJit.compilerLock);
6796999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmInitMutex(&gDvmJit.compilerICPatchLock);
680b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    dvmInitMutex(&gDvmJit.codeCacheProtectionLock);
68194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
68294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
68394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);
68494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
68594d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    /* Reset the work queue */
68694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
68794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerQueueLength = 0;
68894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
68994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
690ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
69194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * Defer rest of initialization until we're sure JIT'ng makes sense. Launch
692964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * the compiler thread, which will do the real initialization if and
693964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * when it is signalled to do so.
694ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
695964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler",
696964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                                   compilerThreadStart, NULL);
697ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
698ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
699ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void)
700ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
701ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    void *threadReturn;
702ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
7032fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Disable new translation requests */
7042fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTable = NULL;
7052fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTableCopy = NULL;
7062fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee
7072e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if (gDvm.verboseShutdown ||
7082e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            gDvmJit.profileMode == kTraceProfilingContinuous) {
70988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        dvmCompilerDumpStats();
71088a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        while (gDvmJit.compilerQueueLength)
71188a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng          sleep(5);
71288a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng    }
71388a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng
714ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerHandle) {
715ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
716ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.haltCompilerThread = true;
717ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
718ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmLockMutex(&gDvmJit.compilerLock);
719ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        pthread_cond_signal(&gDvmJit.compilerQueueActivity);
720ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmUnlockMutex(&gDvmJit.compilerLock);
721ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
722ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng        if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0)
723ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGW("Compiler thread join failed\n");
72443eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        else if (gDvm.verboseShutdown)
725ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng            LOGD("Compiler thread has shut down\n");
726ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
72706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
7282fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Break loops within the translation cache */
7292fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    dvmJitUnchainAll();
73096cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee
7312fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /*
7322fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * NOTE: our current implementatation doesn't allow for the compiler
7332fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * thread to be restarted after it exits here.  We aren't freeing
7342fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * the JitTable or the ProfTable because threads which still may be
7352fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * running or in the process of shutting down may hold references to
7362fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * them.
7372fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     */
73896cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee}
73906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
74006bb83906737fec543c86ab36f450cc62066b58aBill Buzbeevoid dvmCompilerStateRefresh()
74106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{
74206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActive;
74306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActivate;
7443e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    bool needUnchain = false;
74506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
746a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
747a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * The tableLock might not be initialized yet by the compiler thread if
748a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * debugger is attached from the very beginning of the VM launch. If
749a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * pProfTableCopy is NULL, the lock is not initialized yet and we don't
750a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * need to refresh anything either.
751a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
752a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    if (gDvmJit.pProfTableCopy == NULL) {
753a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        return;
754a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    }
755a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng
75618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    /*
75718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * On the first enabling of method tracing, switch the compiler
75818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * into a mode that includes trace support for invokes and returns.
75918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * If there are any existing translations, flush them.  NOTE:  we
76018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * can't blindly flush the translation cache because this code
76118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * may be executed before the compiler thread has finished
76218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * initialization.
76318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     */
76418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    if ((gDvm.interpBreak & kSubModeMethodTrace) &&
76518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        !gDvmJit.methodTraceSupport) {
76618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        bool resetRequired;
76718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        /*
76818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         * compilerLock will prevent new compilations from being
76918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         * installed while we are working.
77018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         */
77118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        dvmLockMutex(&gDvmJit.compilerLock);
77218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        gDvmJit.cacheVersion++; // invalidate compilations in flight
77318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        gDvmJit.methodTraceSupport = true;
77418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        resetRequired = (gDvmJit.numCompilations != 0);
77518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        dvmUnlockMutex(&gDvmJit.compilerLock);
77618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        if (resetRequired) {
77718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET);
77818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            resetCodeCache();
77918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            dvmResumeAllThreads(SUSPEND_FOR_CC_RESET);
78018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        }
78118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    }
78218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee
78306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
78406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActive = gDvmJit.pProfTable != NULL;
785cb3081f675109049e63380170b60871e8275f9a8buzbee    jitActivate = !dvmDebuggerOrProfilerActive();
78606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
78706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    if (jitActivate && !jitActive) {
78806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = gDvmJit.pProfTableCopy;
78906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    } else if (!jitActivate && jitActive) {
79006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = NULL;
7913e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        needUnchain = true;
79206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    }
7933e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
7943e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    if (needUnchain)
7953e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        dvmJitUnchainAll();
79606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee}
797