/* Framework or stand-alone? */
bool runningInAndroidFramework;
+ /* Framework callback happened? */
+ bool alreadyEnabledViaFramework;
+
+ /* Framework requests to disable the JIT for good */
+ bool disableJit;
+
/* Place arrays at the end to ease the display in gdb sessions */
/* Work order queue for compilations */
* up code isn't worth compiling. We'll resume when the framework
* signals us that the first screen draw has happened, or the timer
* below expires (to catch daemons).
+ *
+ * There is a theoretical race between the callback to
+ * VMRuntime.startJitCompiation and when the compiler thread reaches this
+ * point. In case the callback happens earlier, in order not to permanently
+ * hold the system_server (which is not using the timed wait) in
+ * interpreter-only mode we bypass the delay here.
*/
- if (gDvmJit.runningInAndroidFramework) {
- dvmLockMutex(&gDvmJit.compilerLock);
- // TUNING: experiment with the delay & perhaps make it target-specific
- dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
- &gDvmJit.compilerLock, 3000, 0);
- dvmUnlockMutex(&gDvmJit.compilerLock);
+ if (gDvmJit.runningInAndroidFramework &&
+ !gDvmJit.alreadyEnabledViaFramework) {
+ /*
+ * If the current VM instance is the system server (detected by having
+ * 0 in gDvm.systemServerPid), we will use the indefinite wait on the
+ * conditional variable to determine whether to start the JIT or not.
+ * If the system server detects that the whole system is booted in
+ * safe mode, the conditional variable will never be signaled and the
+ * system server will remain in the interpreter-only mode. All
+ * subsequent apps will be started with the --enable-safemode flag
+ * explicitly appended.
+ */
+ if (gDvm.systemServerPid == 0) {
+ dvmLockMutex(&gDvmJit.compilerLock);
+ pthread_cond_wait(&gDvmJit.compilerQueueActivity,
+ &gDvmJit.compilerLock);
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ LOGD("JIT started for system_server");
+ } else {
+ dvmLockMutex(&gDvmJit.compilerLock);
+ /*
+ * TUNING: experiment with the delay & perhaps make it
+ * target-specific
+ */
+ dvmRelativeCondWait(&gDvmJit.compilerQueueActivity,
+ &gDvmJit.compilerLock, 3000, 0);
+ dvmUnlockMutex(&gDvmJit.compilerLock);
+ }
if (gDvmJit.haltCompilerThread) {
return NULL;
}
JValue* pResult)
{
#if defined(WITH_JIT)
- if (gDvm.executionMode == kExecutionModeJit) {
+ if (gDvm.executionMode == kExecutionModeJit &&
+ gDvmJit.disableJit == false) {
dvmLockMutex(&gDvmJit.compilerLock);
+ gDvmJit.alreadyEnabledViaFramework = true;
pthread_cond_signal(&gDvmJit.compilerQueueActivity);
dvmUnlockMutex(&gDvmJit.compilerLock);
}
RETURN_VOID();
}
+/*
+ * public native void disableJitCompilation()
+ *
+ * Callback function from the framework to indicate that a VM instance wants to
+ * permanently disable the JIT compiler. Currently only the system server uses
+ * this interface when it detects system-wide safe mode is enabled.
+ */
+static void Dalvik_dalvik_system_VMRuntime_disableJitCompilation(const u4* args,
+ JValue* pResult)
+{
+#if defined(WITH_JIT)
+ if (gDvm.executionMode == kExecutionModeJit) {
+ gDvmJit.disableJit = true;
+ }
+#endif
+ RETURN_VOID();
+}
+
const DalvikNativeMethod dvm_dalvik_system_VMRuntime[] = {
{ "getTargetHeapUtilization", "()F",
Dalvik_dalvik_system_VMRuntime_getTargetHeapUtilization },
Dalvik_dalvik_system_VMRuntime_getExternalBytesAllocated },
{ "startJitCompilation", "()V",
Dalvik_dalvik_system_VMRuntime_startJitCompilation },
+ { "disableJitCompilation", "()V",
+ Dalvik_dalvik_system_VMRuntime_disableJitCompilation },
{ NULL, NULL, NULL },
};