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"
240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef ARCH_IA32
250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "codegen/x86/Translator.h"
260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "codegen/x86/Lower.h"
270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif
28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
295d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiroextern "C" void dvmCompilerTemplateStart(void);
30d585beda3690b8b5b978e3c59af224336614ba72Yanchuan Nianextern "C" void dvmCompilerTemplateEnd(void);
315d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro
32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic inline bool workQueueLength(void)
33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return gDvmJit.compilerQueueLength;
35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic CompilerWorkOrder workDequeue(void)
38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind
40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           != kWorkOrderInvalid);
41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    CompilerWorkOrder work =
42ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex];
43ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind =
44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        kWorkOrderInvalid;
45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) {
46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkDequeueIndex = 0;
47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength--;
49f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee    if (gDvmJit.compilerQueueLength == 0) {
50b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro        dvmSignalCond(&gDvmJit.compilerQueueEmpty);
51f9f33287693f9f9aa44318036b8aab627bd21a32Bill Buzbee    }
52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
53ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Remember the high water mark of the queue length */
54ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued)
55ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength;
56ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
57ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return work;
58ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
601b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee/*
611b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * Enqueue a work order - retrying until successful.  If attempt to enqueue
621b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * is repeatedly unsuccessful, assume the JIT is in a bad state and force a
631b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee * code cache reset.
641b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee */
651b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee#define ENQUEUE_MAX_RETRIES 20
661b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbeevoid dvmCompilerForceWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
671b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee{
681b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee    bool success;
691b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee    int retries = 0;
701b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee    do {
711b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee        success = dvmCompilerWorkEnqueue(pc, kind, info);
721b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee        if (!success) {
731b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee            retries++;
741b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee            if (retries > ENQUEUE_MAX_RETRIES) {
75c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("JIT: compiler queue wedged - forcing reset");
761b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                gDvmJit.codeCacheFull = true;  // Force reset
771b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                success = true;  // Because we'll drop the order now anyway
781b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee            } else {
791b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                dvmLockMutex(&gDvmJit.compilerLock);
801b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                pthread_cond_wait(&gDvmJit.compilerQueueActivity,
811b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                                  &gDvmJit.compilerLock);
821b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee                dvmUnlockMutex(&gDvmJit.compilerLock);
831b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee
841b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee            }
851b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee        }
861b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee    } while (!success);
871b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee}
881b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee
89964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee/*
90964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee * Attempt to enqueue a work order, returning true if successful.
911357e94efecd485bda933270a9181035f6a39e09Ben Cheng *
921357e94efecd485bda933270a9181035f6a39e09Ben Cheng * NOTE: Make sure that the caller frees the info pointer if the return value
931357e94efecd485bda933270a9181035f6a39e09Ben Cheng * is false.
94964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee */
95ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int cc;
98ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int numWork;
10060c24f436d603c564d5351a6f81821f12635733cBen Cheng    bool result = true;
101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1021b3da59fff0c63770e10684e243a36f3d0218637Bill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
1047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /*
1056999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng     * Return if queue or code cache is full.
1067a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng     */
1076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE ||
1086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        gDvmJit.codeCacheFull == true) {
1095d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro        dvmUnlockMutex(&gDvmJit.compilerLock);
1105d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro        return false;
111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (numWork = gDvmJit.compilerQueueLength,
114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           i = gDvmJit.compilerWorkDequeueIndex;
115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork > 0;
116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng         numWork--) {
117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Already enqueued */
1185d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro        if (gDvmJit.compilerWorkQueue[i++].pc == pc) {
1195d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro            dvmUnlockMutex(&gDvmJit.compilerLock);
1205d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro            return true;
1215d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro        }
122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        /* Wrap around */
123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (i == COMPILER_WORK_QUEUE_SIZE)
124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            i = 0;
125ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
126ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
127ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    CompilerWorkOrder *newOrder =
128ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng        &gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex];
129ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->pc = pc;
130ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->kind = kind;
131ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->info = info;
1327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newOrder->result.methodCompilationAborted = NULL;
133ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.codeAddress = NULL;
134ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng    newOrder->result.discardResult =
1351f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee        (kind == kWorkOrderTraceDebug) ? true : false;
13618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    newOrder->result.cacheVersion = gDvmJit.cacheVersion;
13733672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng    newOrder->result.requestingThread = dvmThreadSelf();
13833672456e19bff9913b4a3459e6b8472f4c26c84Ben Cheng
139ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerWorkEnqueueIndex++;
140ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
141ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.compilerWorkEnqueueIndex = 0;
142ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    gDvmJit.compilerQueueLength++;
143ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
144ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    assert(cc == 0);
145ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
146ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
14760c24f436d603c564d5351a6f81821f12635733cBen Cheng    return result;
148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
149ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
15011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng/* Block until the queue length is 0, or there is a pending suspend request */
151ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerDrainQueue(void)
152ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
15311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    Thread *self = dvmThreadSelf();
15411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng
155ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
15611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
157389e258a5b9b2afb7bfaee3344c615d3310fae4ebuzbee           self->suspendCount == 0) {
158812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        /*
159812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * Use timed wait here - more than one mutator threads may be blocked
160812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * but the compiler thread will only signal once when the queue is
161812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * emptied. Furthermore, the compiler thread may have been shutdown
162812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         * so the blocked thread may never get the wakeup signal.
163812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng         */
164812e6b1a6485e4468bc88fd69e9304817b8192ddBen Cheng        dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock,                             1000, 0);
165ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
166ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
167ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
168ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
16960c24f436d603c564d5351a6f81821f12635733cBen Chengbool dvmCompilerSetupCodeCache(void)
17060c24f436d603c564d5351a6f81821f12635733cBen Cheng{
1717c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    int fd;
17260c24f436d603c564d5351a6f81821f12635733cBen Cheng
17360c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Allocate the code cache */
1747c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    fd = ashmem_create_region("dalvik-jit-code-cache", gDvmJit.codeCacheSize);
1757c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    if (fd < 0) {
176c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Could not create %u-byte ashmem region for the JIT code cache",
1777c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng             gDvmJit.codeCacheSize);
1787c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng        return false;
1797c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    }
1807c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    gDvmJit.codeCache = mmap(NULL, gDvmJit.codeCacheSize,
1817c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             PROT_READ | PROT_WRITE | PROT_EXEC,
1827c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng                             MAP_PRIVATE , fd, 0);
1837c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    close(fd);
18460c24f436d603c564d5351a6f81821f12635733cBen Cheng    if (gDvmJit.codeCache == MAP_FAILED) {
185bbbe552a31f7229708bfc748480ce538218ae076buzbee        ALOGE("Failed to mmap the JIT code cache of size %d: %s", gDvmJit.codeCacheSize, strerror(errno));
18660c24f436d603c564d5351a6f81821f12635733cBen Cheng        return false;
18760c24f436d603c564d5351a6f81821f12635733cBen Cheng    }
18860c24f436d603c564d5351a6f81821f12635733cBen Cheng
189b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    gDvmJit.pageSizeMask = getpagesize() - 1;
190b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
1917c4afdb7e96bb74909f111f08741aed261d191f8Ben Cheng    /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */
192062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    // ALOGD("Code cache starts at %p", gDvmJit.codeCache);
1937a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
1940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifndef ARCH_IA32
19560c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Copy the template code into the beginning of the code cache */
196d585beda3690b8b5b978e3c59af224336614ba72Yanchuan Nian    int templateSize = (intptr_t) dvmCompilerTemplateEnd -
19760c24f436d603c564d5351a6f81821f12635733cBen Cheng                       (intptr_t) dvmCompilerTemplateStart;
19860c24f436d603c564d5351a6f81821f12635733cBen Cheng    memcpy((void *) gDvmJit.codeCache,
19960c24f436d603c564d5351a6f81821f12635733cBen Cheng           (void *) dvmCompilerTemplateStart,
20060c24f436d603c564d5351a6f81821f12635733cBen Cheng           templateSize);
20160c24f436d603c564d5351a6f81821f12635733cBen Cheng
20272621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    /*
20372621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * Work around a CPU bug by keeping the 32-bit ARM handler code in its own
20472621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     * page.
20572621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng     */
20672621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    if (dvmCompilerInstructionSet() == DALVIK_JIT_THUMB2) {
20772621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng        templateSize = (templateSize + 4095) & ~4095;
20872621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng    }
20972621c9d3c175b0f9b239de5b0bcd83c7e5984e8Ben Cheng
21060c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.templateSize = templateSize;
21160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = templateSize;
21260c24f436d603c564d5351a6f81821f12635733cBen Cheng
21360c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Only flush the part in the code cache that is being used now */
21413fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache,
21513fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          (intptr_t) gDvmJit.codeCache + templateSize, 0);
2160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else
2170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    gDvmJit.codeCacheByteUsed = 0;
2180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    stream = (char*)gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
2190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    ALOGV("codeCache = %p stream = %p before initJIT", gDvmJit.codeCache, stream);
2200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    streamStart = stream;
2210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    initJIT(NULL, NULL);
2220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    gDvmJit.templateSize = (stream - streamStart);
2230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    gDvmJit.codeCacheByteUsed = (stream - streamStart);
2240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen    ALOGV("stream = %p after initJIT", stream);
2250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif
226b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
2279cf04e3569d48dae36e0492226250da04699f8d4Jun Tian    int result = mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize,
2289cf04e3569d48dae36e0492226250da04699f8d4Jun Tian                          PROTECT_CODE_CACHE_ATTRS);
2299cf04e3569d48dae36e0492226250da04699f8d4Jun Tian
2309cf04e3569d48dae36e0492226250da04699f8d4Jun Tian    if (result == -1) {
2319cf04e3569d48dae36e0492226250da04699f8d4Jun Tian        ALOGE("Failed to remove the write permission for the code cache");
2329cf04e3569d48dae36e0492226250da04699f8d4Jun Tian        dvmAbort();
2339cf04e3569d48dae36e0492226250da04699f8d4Jun Tian    }
2349cf04e3569d48dae36e0492226250da04699f8d4Jun Tian
23560c24f436d603c564d5351a6f81821f12635733cBen Cheng    return true;
23660c24f436d603c564d5351a6f81821f12635733cBen Cheng}
23760c24f436d603c564d5351a6f81821f12635733cBen Cheng
2387a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Chengstatic void crawlDalvikStack(Thread *thread, bool print)
2397a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng{
24030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    void *fp = thread->interpSave.curFrame;
2417a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    StackSaveArea* saveArea = NULL;
2427a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int stackLevel = 0;
2437a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2447a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (print) {
245062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Crawling tid %d (%s / %p %s)", thread->systemTid,
2467a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             dvmGetThreadStatusStr(thread->status),
2477a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache,
2487a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng             thread->inJitCodeCache ? "jit" : "interp");
2497a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2507a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Crawl the Dalvik stack frames to clear the returnAddr field */
2517a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (fp != NULL) {
2527a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea = SAVEAREA_FROM_FP(fp);
2537a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
2547a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (print) {
255fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro            if (dvmIsBreakFrame((u4*)fp)) {
256062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                ALOGD("  #%d: break frame (%p)",
2577a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel, saveArea->returnAddr);
2587a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2597a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            else {
260062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                ALOGD("  #%d: %s.%s%s (%p)",
2617a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     stackLevel,
2627a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->clazz->descriptor,
2637a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->method->name,
2647a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     dvmIsNativeMethod(saveArea->method) ?
2657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                         " (native)" : "",
2667a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng                     saveArea->returnAddr);
2677a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            }
2687a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2697a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        stackLevel++;
2707a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        saveArea->returnAddr = NULL;
2717a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        assert(fp != saveArea->prevFrame);
2727a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        fp = saveArea->prevFrame;
2737a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
2747a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    /* Make sure the stack is fully unwound to the bottom */
2757a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    assert(saveArea == NULL ||
2767a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng           (u1 *) (saveArea+1) == thread->interpStackStart);
2777a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng}
2787a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
27960c24f436d603c564d5351a6f81821f12635733cBen Chengstatic void resetCodeCache(void)
28060c24f436d603c564d5351a6f81821f12635733cBen Cheng{
28160c24f436d603c564d5351a6f81821f12635733cBen Cheng    Thread* thread;
2827a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    u8 startTime = dvmGetRelativeTimeUsec();
2837a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    int inJit = 0;
2846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    int byteUsed = gDvmJit.codeCacheByteUsed;
28560c24f436d603c564d5351a6f81821f12635733cBen Cheng
2865867bea193779ff3009738513bae9bc84f4a34aabuzbee    /* If any thread is found stuck in the JIT state, don't reset the cache  */
2875867bea193779ff3009738513bae9bc84f4a34aabuzbee    dvmLockThreadList(NULL);
28860c24f436d603c564d5351a6f81821f12635733cBen Cheng    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2896999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        /*
2906999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * Crawl the stack to wipe out the returnAddr field so that
2916999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 1) the soon-to-be-deleted code in the JIT cache won't be used
2926999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         * 2) or the thread stuck in the JIT land will soon return
2936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         *    to the interpreter land
2946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         */
2956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        crawlDalvikStack(thread, false);
2967a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        if (thread->inJitCodeCache) {
2977a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng            inJit++;
2987a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        }
2995867bea193779ff3009738513bae9bc84f4a34aabuzbee        /* Cancel any ongoing trace selection */
300cf2aac7e6a29e7e1e5f622fd6123e0d1a9a75bdabuzbee        dvmDisableSubMode(thread, kSubModeJitTraceBuild);
3017a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
3025867bea193779ff3009738513bae9bc84f4a34aabuzbee    dvmUnlockThreadList();
30360c24f436d603c564d5351a6f81821f12635733cBen Cheng
3047a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    if (inJit) {
305062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("JIT code cache reset delayed (%d bytes %d/%d)",
3066999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             gDvmJit.codeCacheByteUsed, gDvmJit.numCodeCacheReset,
3076999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng             ++gDvmJit.numCodeCacheResetDelayed);
3086999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        return;
3097a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
3107a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
3116999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Lock the mutex to clean up the work queue */
3126999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
3136999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
31418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    /* Update the translation cache version */
31518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    gDvmJit.cacheVersion++;
31618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee
3176999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Drain the work queue to free the work orders */
3187a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    while (workQueueLength()) {
3197a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        CompilerWorkOrder work = workDequeue();
3207a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng        free(work.info);
3217a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng    }
3227a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
32360c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the JitEntry table contents to the initial unpopulated state */
32460c24f436d603c564d5351a6f81821f12635733cBen Cheng    dvmJitResetTable();
32560c24f436d603c564d5351a6f81821f12635733cBen Cheng
326b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
32760c24f436d603c564d5351a6f81821f12635733cBen Cheng    /*
32860c24f436d603c564d5351a6f81821f12635733cBen Cheng     * Wipe out the code cache content to force immediate crashes if
32960c24f436d603c564d5351a6f81821f12635733cBen Cheng     * stale JIT'ed code is invoked.
33060c24f436d603c564d5351a6f81821f12635733cBen Cheng     */
331a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham    dvmCompilerCacheClear((char *) gDvmJit.codeCache + gDvmJit.templateSize,
332a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham                          gDvmJit.codeCacheByteUsed - gDvmJit.templateSize);
333a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham
33413fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    dvmCompilerCacheFlush((intptr_t) gDvmJit.codeCache,
33513fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          (intptr_t) gDvmJit.codeCache +
33613fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee                          gDvmJit.codeCacheByteUsed, 0);
33760c24f436d603c564d5351a6f81821f12635733cBen Cheng
338b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
339b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng
34060c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the current mark of used bytes to the end of template code */
34160c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
34260c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.numCompilations = 0;
34360c24f436d603c564d5351a6f81821f12635733cBen Cheng
34460c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* Reset the work queue */
34560c24f436d603c564d5351a6f81821f12635733cBen Cheng    memset(gDvmJit.compilerWorkQueue, 0,
34660c24f436d603c564d5351a6f81821f12635733cBen Cheng           sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
34760c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
34860c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.compilerQueueLength = 0;
34960c24f436d603c564d5351a6f81821f12635733cBen Cheng
3506999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    /* Reset the IC patch work queue */
3516999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmLockMutex(&gDvmJit.compilerICPatchLock);
3526999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    gDvmJit.compilerICPatchIndex = 0;
3536999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerICPatchLock);
3546999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
355385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    /*
356385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng     * Reset the inflight compilation address (can only be done in safe points
357385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng     * or by the compiler thread when its thread state is RUNNING).
358385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng     */
359385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    gDvmJit.inflightBaseAddr = NULL;
360385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng
36160c24f436d603c564d5351a6f81821f12635733cBen Cheng    /* All clear now */
36260c24f436d603c564d5351a6f81821f12635733cBen Cheng    gDvmJit.codeCacheFull = false;
36360c24f436d603c564d5351a6f81821f12635733cBen Cheng
3646999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
3657a0bcd0de6c4da6499a088a18d1750e51204c2a6Ben Cheng
366062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    ALOGD("JIT code cache reset in %lld ms (%d bytes %d/%d)",
3676999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         (dvmGetRelativeTimeUsec() - startTime) / 1000,
3686999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         byteUsed, ++gDvmJit.numCodeCacheReset,
3696999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng         gDvmJit.numCodeCacheResetDelayed);
3706999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng}
3716999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng
3726999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng/*
3736999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * Perform actions that are only safe when all threads are suspended. Currently
3746999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * we do:
3756999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 1) Check if the code cache is full. If so reset it and restart populating it
3766999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng *    from scratch.
3776999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng * 2) Patch predicted chaining cells by consuming recorded work orders.
3786999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng */
3796999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Chengvoid dvmCompilerPerformSafePointChecks(void)
3806999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng{
3816999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    if (gDvmJit.codeCacheFull) {
3826999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng        resetCodeCache();
3836999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    }
3846999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmCompilerPatchInlineCache();
38560c24f436d603c564d5351a6f81821f12635733cBen Cheng}
38660c24f436d603c564d5351a6f81821f12635733cBen Cheng
387953a0ed4e507fd6e756aa3e5c671bee80d7e9b3eAndy McFaddenstatic bool compilerThreadStartup(void)
388964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee{
389964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    JitEntry *pJitTable = NULL;
390964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned char *pJitProfTable = NULL;
3912e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    JitTraceProfCounters *pJitTraceProfCounters = NULL;
392964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    unsigned int i;
393964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
394964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!dvmCompilerArchInit())
395964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
396964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
397964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
398964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Setup the code cache if we have not inherited a valid code cache
399964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * from the zygote.
400964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
401964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (gDvmJit.codeCache == NULL) {
402964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        if (!dvmCompilerSetupCodeCache())
403964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee            goto fail;
404964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
405964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
406964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Allocate the initial arena block */
407964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (dvmCompilerHeapInit() == false) {
408964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
409964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
410964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
411385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    /* Cache the thread pointer */
412385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng    gDvmJit.compilerThread = dvmThreadSelf();
413385828e36ea70effe9aa18a954d008b1f7dc1d63Ben Cheng
414964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
415964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
416964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Track method-level compilation statistics */
417964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
4187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
4197a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
420452efba773098c070c6bd623124e1fed21342ba4Ben Cheng    gDvm.verboseShutdown = true;
4211357e94efecd485bda933270a9181035f6a39e09Ben Cheng#endif
422964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
423964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
424964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
425964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Set up the JitTable */
426964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
427964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Power of 2? */
428964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(gDvmJit.jitTableSize &&
429964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee           !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
430964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
431964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmInitMutex(&gDvmJit.tableLock);
432964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
433964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitTable = (JitEntry*)
434964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
435964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitTable) {
436c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("jit table allocation failed");
437964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
438964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
439964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
440964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /*
441964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * NOTE: the profile table must only be allocated once, globally.
442964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * Profiling is turned on and off by nulling out gDvm.pJitProfTable
443964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and then restoring its original value.  However, this action
4449a3147c7412f4794434b4c2604aa2ba784867774buzbee     * is not synchronized for speed so threads may continue to hold
445964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * and update the profile table after profiling has been turned
446964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * off by null'ng the global pointer.  Be aware.
447964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     */
448964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
449964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    if (!pJitProfTable) {
450c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("jit prof table allocation failed");
451e3b363d470aa94e2a8c9df214c658980a6e83122You Kim        free(pJitTable);
452964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
453964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        goto fail;
454964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
455964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    memset(pJitProfTable, gDvmJit.threshold, JIT_PROF_SIZE);
456964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    for (i=0; i < gDvmJit.jitTableSize; i++) {
457964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee       pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
458964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    }
459964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Is chain field wide enough for termination pattern? */
460964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
461964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
4622e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    /* Allocate the trace profiling structure */
4632e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    pJitTraceProfCounters = (JitTraceProfCounters*)
4642e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                             calloc(1, sizeof(*pJitTraceProfCounters));
4652e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if (!pJitTraceProfCounters) {
466c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("jit trace prof counters allocation failed");
467e3b363d470aa94e2a8c9df214c658980a6e83122You Kim        free(pJitTable);
468e3b363d470aa94e2a8c9df214c658980a6e83122You Kim        free(pJitProfTable);
4692e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        dvmUnlockMutex(&gDvmJit.tableLock);
4702e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        goto fail;
4712e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    }
4722e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
473964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.pJitEntryTable = pJitTable;
474964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
475964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.jitTableEntriesUsed = 0;
476964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    gDvmJit.compilerHighWater =
477964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee        COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
478a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
479a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * If the VM is launched with wait-on-the-debugger, we will need to hide
480a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * the profile table here
481a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
482a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable;
48306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    gDvmJit.pProfTableCopy = pJitProfTable;
4842e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    gDvmJit.pJitTraceProfCounters = pJitTraceProfCounters;
48599e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmJitUpdateThreadStateAll();
486964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
487964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
488964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    /* Signal running threads to refresh their cached pJitTable pointers */
489964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmSuspendAllThreads(SUSPEND_FOR_REFRESH);
490964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    dvmResumeAllThreads(SUSPEND_FOR_REFRESH);
491dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
492dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /* Enable signature breakpoints by customizing the following code */
493dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#if defined(SIGNATURE_BREAKPOINT)
494dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
495dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Suppose one sees the following native crash in the bugreport:
496dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): Build fingerprint: 'unknown'
497dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): pid: 2468, tid: 2507  >>> com.google.android.gallery3d
498dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): signal 11 (SIGSEGV), fault addr 00001400
499dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r0 44ea7190  r1 44e4f7b8  r2 44ebc710  r3 00000000
500dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r4 00000a00  r5 41862dec  r6 4710dc10  r7 00000280
501dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  r8 ad010f40  r9 46a37a12  10 001116b0  fp 42a78208
502dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  ip 00000090  sp 4710dbc8  lr ad060e67  pc 46b90682
503dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * cpsr 00000030
504dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #00  pc 46b90682 /dev/ashmem/dalvik-jit-code-cache
505dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638):  #01  pc 00060e62  /system/lib/libdvm.so
506dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
507dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): code around pc:
508dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90660 6888d01c 34091dcc d2174287 4a186b68
509dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90670 d0052800 68006809 28004790 6b68d00e
510dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90680 512000bc 37016eaf 6ea866af 6f696028
511dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b90690 682a6069 429a686b e003da08 6df1480b
512dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * I/DEBUG   ( 1638): 46b906a0 1c2d4788 47806d70 46a378fa 47806d70
513dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
514dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Clearly it is a JIT bug. To find out which translation contains the
515dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offending code, the content of the memory dump around the faulting PC
516dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * can be pasted into the gDvmJit.signatureBreakpoint[] array and next time
517dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * when a similar compilation is being created, the JIT compiler replay the
518dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * trace in the verbose mode and one can investigate the instruction
519dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * sequence in details.
520dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
521dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The length of the signature may need additional experiments to determine.
522dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The rule of thumb is don't include PC-relative instructions in the
523dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * signature since it may be affected by the alignment of the compiled code.
524dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * However, a signature that's too short might increase the chance of false
525dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * positive matches. Using gdbjithelper to disassembly the memory content
526dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * first might be a good companion approach.
527dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
528dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * For example, if the next 4 words starting from 46b90680 is pasted into
529dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * the data structure:
530dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
531dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
532dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpointSize = 4;
533dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint =
534dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng        malloc(sizeof(u4) * gDvmJit.signatureBreakpointSize);
535dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[0] = 0x512000bc;
536dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[1] = 0x37016eaf;
537dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[2] = 0x6ea866af;
538dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    gDvmJit.signatureBreakpoint[3] = 0x6f696028;
539dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
540dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng    /*
541dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The following log will be printed when a match is found in subsequent
542dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * testings:
543dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
544dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Signature match starting from offset 0x34 (4 words)
545dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): --------
546dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): Compiler: Building trace for computeVisibleItems,
547dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * offset 0x1f7
548dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a12: 0x0090 add-int v42, v5, v26
549dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a16: 0x004d aput-object v13, v14, v42
550dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37a1a: 0x0028 goto, (#0), (#0)
551dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a3794e: 0x00d8 add-int/lit8 v26, v26, (#1)
552dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a37952: 0x0028 goto, (#0), (#0)
553dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378ee: 0x0002 move/from16 v0, v26, (#0)
554dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f2: 0x0002 move/from16 v1, v29, (#0)
555dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x46a378f6: 0x0035 if-ge v0, v1, (#10)
556dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): TRACEINFO (554): 0x46a37624
557dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * Lcom/cooliris/media/GridLayer;computeVisibleItems 0x1f7 14 of 934, 8
558dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * blocks
559dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
560dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *     :
561dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x20 (0020): ldr     r0, [r5, #52]
562dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x22 (0022): ldr     r2, [pc, #96]
563dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x24 (0024): cmp     r0, #0
564dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x26 (0026): beq     0x00000034
565dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x28 (0028): ldr     r1, [r1, #0]
566dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2a (002a): ldr     r0, [r0, #0]
567dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2c (002c): blx     r2
568dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x2e (002e): cmp     r0, #0
569dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x30 (0030): beq     0x00000050
570dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x32 (0032): ldr     r0, [r5, #52]
571dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x34 (0034): lsls    r4, r7, #2
572dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x36 (0036): str     r0, [r4, r4]
573dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x01fb @ goto, (#0), (#0)
574dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0195:
575dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0195 @ add-int/lit8 v26,
576dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * v26, (#1)
577dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x38 (0038): ldr     r7, [r5, #104]
578dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3a (003a): adds    r7, r7, #1
579dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3c (003c): str     r7, [r5, #104]
580dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0197 @ goto, (#0), (#0)
581dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): L0x0165:
582dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): -------- dalvik offset: 0x0165 @ move/from16 v0, v26,
583dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * (#0)
584dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x3e (003e): ldr     r0, [r5, #104]
585dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * D/dalvikvm( 2468): 0x40 (0040): str     r0, [r5, #0]
586dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     *
587dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     * The "str r0, [r4, r4]" is indeed the culprit of the native crash.
588dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng     */
589dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng#endif
590dca714364abf3111fc18c1ac49c2760392fb7c9bBen Cheng
591964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return true;
592964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
593964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbeefail:
594964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return false;
595964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
596964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee}
597964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee
598ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic void *compilerThreadStart(void *arg)
599ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
6005ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_VMWAIT);
6015ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
602b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee    /*
603eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * If we're not running stand-alone, wait a little before
604eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * recieving translation requests on the assumption that process start
605eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * up code isn't worth compiling.  We'll resume when the framework
606eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * signals us that the first screen draw has happened, or the timer
607eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee     * below expires (to catch daemons).
608f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     *
609f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * There is a theoretical race between the callback to
610f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * VMRuntime.startJitCompiation and when the compiler thread reaches this
611f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * point. In case the callback happens earlier, in order not to permanently
612f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * hold the system_server (which is not using the timed wait) in
613f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng     * interpreter-only mode we bypass the delay here.
614b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee     */
615f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng    if (gDvmJit.runningInAndroidFramework &&
616f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        !gDvmJit.alreadyEnabledViaFramework) {
617f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        /*
618f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the current VM instance is the system server (detected by having
619f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * 0 in gDvm.systemServerPid), we will use the indefinite wait on the
620f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * conditional variable to determine whether to start the JIT or not.
621f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * If the system server detects that the whole system is booted in
622f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * safe mode, the conditional variable will never be signaled and the
623f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * system server will remain in the interpreter-only mode. All
624f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * subsequent apps will be started with the --enable-safemode flag
625f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         * explicitly appended.
626f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng         */
627f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        if (gDvm.systemServerPid == 0) {
628f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
629f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
630f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                              &gDvmJit.compilerLock);
631f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
632062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("JIT started for system_server");
633f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        } else {
634f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmLockMutex(&gDvmJit.compilerLock);
635f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            /*
636f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * TUNING: experiment with the delay & perhaps make it
637f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             * target-specific
638f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng             */
639f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
640f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng                                 &gDvmJit.compilerLock, 3000, 0);
641f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng            dvmUnlockMutex(&gDvmJit.compilerLock);
642f30acbb249b137b049500f136d2bb273c0b6221aBen Cheng        }
643eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        if (gDvmJit.haltCompilerThread) {
644eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee             return NULL;
645eb695c6f814f6b0bdbba0e837555d3fe5ad23104Bill Buzbee        }
64694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    }
64794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
648964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    compilerThreadStartup();
649b1d8044ee3a7503b94eb54459f3077d7200cd675Bill Buzbee
650ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmLockMutex(&gDvmJit.compilerLock);
651ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
652ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * Since the compiler thread will not touch any objects on the heap once
653ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * being created, we just fake its state as VMWAIT so that it can be a
654ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     * bit late when there is suspend request pending.
655ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
656ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (!gDvmJit.haltCompilerThread) {
657ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (workQueueLength() == 0) {
658ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            int cc;
659ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
660ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(cc == 0);
661ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
662ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                              &gDvmJit.compilerLock);
663ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            continue;
664ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
665ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            do {
666ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                CompilerWorkOrder work = workDequeue();
667ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmUnlockMutex(&gDvmJit.compilerLock);
668978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
669db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                /*
670db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                 * This is live across setjmp().  Mark it volatile to suppress
671db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                 * a gcc warning.  We should not need this since it is assigned
672db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                 * only once but gcc is not smart enough.
673db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                 */
674db7d27bf88146ed20d2c8f3c424c998dae3b9971Doug Kwan                volatile u8 startTime = dvmGetRelativeTimeUsec();
67586717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
676964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                /*
677964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * Check whether there is a suspend request on me.  This
678964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 * is necessary to allow a clean shutdown.
67911d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 *
68011d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * However, in the blocking stress testing mode, let the
68111d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * compiler thread continue doing compilations to unblock
68211d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * other requesting threads. This may occasionally cause
68311d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * shutdown from proceeding cleanly in the standalone invocation
68411d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                 * of the vm but this should be acceptable.
685964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                 */
68611d8f14eef83d1b7bfa8f116de56a92d5ba9e71eBen Cheng                if (!gDvmJit.blockingMode)
687ab227f7a9a9d4c7837ee7a5cc9f07b665d516bacAndy McFadden                    dvmCheckSuspendPending(dvmThreadSelf());
6882717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                /* Is JitTable filling up? */
6892717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                if (gDvmJit.jitTableEntriesUsed >
6902717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
6916999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    bool resizeFail =
6926999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                        dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
6936999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    /*
6946999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * If the jit table is full, consider it's time to reset
6956999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     * the code cache too.
6966999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                     */
6976999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                    gDvmJit.codeCacheFull |= resizeFail;
6982717622484eb0f7ad537275f7260b2f93324eda2Bill Buzbee                }
699ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                if (gDvmJit.haltCompilerThread) {
700062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block                    ALOGD("Compiler shutdown in progress - discarding request");
7016999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng                } else if (!gDvmJit.codeCacheFull) {
702fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    jmp_buf jmpBuf;
703fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    work.bailPtr = &jmpBuf;
704fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    bool aborted = setjmp(jmpBuf);
705fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee                    if (!aborted) {
7062e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                        bool codeCompiled = dvmCompilerDoWork(&work);
7075867bea193779ff3009738513bae9bc84f4a34aabuzbee                        /*
7085867bea193779ff3009738513bae9bc84f4a34aabuzbee                         * Make sure we are still operating with the
7095867bea193779ff3009738513bae9bc84f4a34aabuzbee                         * same translation cache version.  See
7105867bea193779ff3009738513bae9bc84f4a34aabuzbee                         * Issue 4271784 for details.
7115867bea193779ff3009738513bae9bc84f4a34aabuzbee                         */
7125867bea193779ff3009738513bae9bc84f4a34aabuzbee                        dvmLockMutex(&gDvmJit.compilerLock);
7135867bea193779ff3009738513bae9bc84f4a34aabuzbee                        if ((work.result.cacheVersion ==
7145867bea193779ff3009738513bae9bc84f4a34aabuzbee                             gDvmJit.cacheVersion) &&
7155867bea193779ff3009738513bae9bc84f4a34aabuzbee                             codeCompiled &&
7165867bea193779ff3009738513bae9bc84f4a34aabuzbee                             !work.result.discardResult &&
7175867bea193779ff3009738513bae9bc84f4a34aabuzbee                             work.result.codeAddress) {
7182e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                            dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
7192e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                                              work.result.instructionSet,
720cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng                                              false, /* not method entry */
7212e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                                              work.result.profileCodeSize);
7222e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                        }
7235867bea193779ff3009738513bae9bc84f4a34aabuzbee                        dvmUnlockMutex(&gDvmJit.compilerLock);
72460c24f436d603c564d5351a6f81821f12635733cBen Cheng                    }
7252e152baec01433de9c63633ebc6f4adf1cea3a87buzbee                    dvmCompilerArenaReset();
726ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                }
727ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                free(work.info);
728978738d2cbf9d08fa78c65762eaac3351ab76b9aBen Cheng#if defined(WITH_JIT_TUNING)
72986717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng                gDvmJit.jitTime += dvmGetRelativeTimeUsec() - startTime;
73086717f79d9b018f4d69cc991075fa36611f234e5Ben Cheng#endif
731ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                dvmLockMutex(&gDvmJit.compilerLock);
732ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } while (workQueueLength() != 0);
733ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
734ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
735ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
736ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    dvmUnlockMutex(&gDvmJit.compilerLock);
737ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng
7385ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    /*
7395ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * As part of detaching the thread we need to call into Java code to update
7405ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * the ThreadGroup, and we should not be in VMWAIT state while executing
7415ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     * interpreted code.
7425ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng     */
7435ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng    dvmChangeStatus(NULL, THREAD_RUNNING);
7445ccdf0be4b448c98b595444a77dbaa21471ad1b1Ben Cheng
74543eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden    if (gDvm.verboseShutdown)
746062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block        ALOGD("Compiler thread shutting down");
747ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return NULL;
748ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
749ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
750ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengbool dvmCompilerStartup(void)
751ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
75294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
75394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmInitMutex(&gDvmJit.compilerLock);
7546999d84e2c55dc4a46a6c311b55bd5811336d9c4Ben Cheng    dvmInitMutex(&gDvmJit.compilerICPatchLock);
755b88ec3cbb419b5eac23508dc6b73de2620d7521aBen Cheng    dvmInitMutex(&gDvmJit.codeCacheProtectionLock);
75694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmLockMutex(&gDvmJit.compilerLock);
75794d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
75894d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);
75994d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
76094d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    /* Reset the work queue */
76194d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
76294d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    gDvmJit.compilerQueueLength = 0;
76394d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee    dvmUnlockMutex(&gDvmJit.compilerLock);
76494d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee
765ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /*
76694d89f8016b6c305ab0df491874dcedb252ecfccBill Buzbee     * Defer rest of initialization until we're sure JIT'ng makes sense. Launch
767964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * the compiler thread, which will do the real initialization if and
768964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee     * when it is signalled to do so.
769ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng     */
770964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee    return dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler",
771964a7b06a9134947b5985c7f712d18d57ed665d2Bill Buzbee                                   compilerThreadStart, NULL);
772ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
773ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
774ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerShutdown(void)
775ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
776ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    void *threadReturn;
777ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
7782fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Disable new translation requests */
7792fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTable = NULL;
7802fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    gDvmJit.pProfTableCopy = NULL;
78199e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmJitUpdateThreadStateAll();
7822fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee
7832e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if (gDvm.verboseShutdown ||
7842e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            gDvmJit.profileMode == kTraceProfilingContinuous) {
78588a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        dvmCompilerDumpStats();
78688a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng        while (gDvmJit.compilerQueueLength)
78788a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng          sleep(5);
78888a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng    }
78988a0f970e47dc0091d2c9965aa9bd06667e5f4b7Ben Cheng
790ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    if (gDvmJit.compilerHandle) {
791ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
792ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        gDvmJit.haltCompilerThread = true;
793ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
794ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmLockMutex(&gDvmJit.compilerLock);
795ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        pthread_cond_signal(&gDvmJit.compilerQueueActivity);
796ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        dvmUnlockMutex(&gDvmJit.compilerLock);
797ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
798ef00a85e7f148f044b14942aa09204e2d0d72738Ben Cheng        if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0)
799e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            ALOGW("Compiler thread join failed");
80043eb5015ca8bc0c859100b659d9c12934011a42eAndy McFadden        else if (gDvm.verboseShutdown)
801062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Compiler thread has shut down");
802ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
80306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
8042fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /* Break loops within the translation cache */
8052fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    dvmJitUnchainAll();
80696cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee
8072fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee    /*
8082fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * NOTE: our current implementatation doesn't allow for the compiler
8092fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * thread to be restarted after it exits here.  We aren't freeing
8102fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * the JitTable or the ProfTable because threads which still may be
8112fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * running or in the process of shutting down may hold references to
8122fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     * them.
8132fc03c3399cc33dc1c7d669e8970a87144ec7b97Bill Buzbee     */
81496cfe6c39b91dabc78182e2f7676b27b4012886aBill Buzbee}
81506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
81699e3e6e72e3471eb85fc2e405866392b01c080febuzbeevoid dvmCompilerUpdateGlobalState()
81706bb83906737fec543c86ab36f450cc62066b58aBill Buzbee{
81806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActive;
81906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    bool jitActivate;
8203e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    bool needUnchain = false;
82106bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
822a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    /*
823a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * The tableLock might not be initialized yet by the compiler thread if
824a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * debugger is attached from the very beginning of the VM launch. If
825a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * pProfTableCopy is NULL, the lock is not initialized yet and we don't
826a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     * need to refresh anything either.
827a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng     */
828a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    if (gDvmJit.pProfTableCopy == NULL) {
829a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        return;
830a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng    }
831a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng
83218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    /*
83318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * On the first enabling of method tracing, switch the compiler
83418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * into a mode that includes trace support for invokes and returns.
83518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * If there are any existing translations, flush them.  NOTE:  we
83618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * can't blindly flush the translation cache because this code
83718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * may be executed before the compiler thread has finished
83818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     * initialization.
83918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee     */
8409a3147c7412f4794434b4c2604aa2ba784867774buzbee    if ((gDvm.activeProfilers != 0) &&
84118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        !gDvmJit.methodTraceSupport) {
84218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        bool resetRequired;
84318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        /*
84418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         * compilerLock will prevent new compilations from being
84518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         * installed while we are working.
84618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee         */
84718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        dvmLockMutex(&gDvmJit.compilerLock);
84818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        gDvmJit.cacheVersion++; // invalidate compilations in flight
84918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        gDvmJit.methodTraceSupport = true;
85018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        resetRequired = (gDvmJit.numCompilations != 0);
85118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        dvmUnlockMutex(&gDvmJit.compilerLock);
85218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        if (resetRequired) {
85318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            dvmSuspendAllThreads(SUSPEND_FOR_CC_RESET);
85418fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            resetCodeCache();
85518fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            dvmResumeAllThreads(SUSPEND_FOR_CC_RESET);
85618fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        }
85718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee    }
85818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee
85906bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    dvmLockMutex(&gDvmJit.tableLock);
86006bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    jitActive = gDvmJit.pProfTable != NULL;
861cb3081f675109049e63380170b60871e8275f9a8buzbee    jitActivate = !dvmDebuggerOrProfilerActive();
86206bb83906737fec543c86ab36f450cc62066b58aBill Buzbee
86306bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    if (jitActivate && !jitActive) {
86406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = gDvmJit.pProfTableCopy;
86506bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    } else if (!jitActivate && jitActive) {
86606bb83906737fec543c86ab36f450cc62066b58aBill Buzbee        gDvmJit.pProfTable = NULL;
8673e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        needUnchain = true;
86806bb83906737fec543c86ab36f450cc62066b58aBill Buzbee    }
8693e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    dvmUnlockMutex(&gDvmJit.tableLock);
8703e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee    if (needUnchain)
8713e392681fd57eaa64d4a65bd99d3576b8366569dBill Buzbee        dvmJitUnchainAll();
8729a3147c7412f4794434b4c2604aa2ba784867774buzbee    // Make sure all threads have current values
87399e3e6e72e3471eb85fc2e405866392b01c080febuzbee    dvmJitUpdateThreadStateAll();
87406bb83906737fec543c86ab36f450cc62066b58aBill Buzbee}
875