Calling EnsureInitialized can block due to locking on the class
object, that an application can also do.
Just rely that the compilation request is for a reason.
The compiler aleady knows how to compile methods of classes that
are not initialized.
bug:
62243120
Test: test.py --jit
(cherry picked from commit
23ddfe86788fe1c95b8be6c76f3a127f8f51dd9f)
Change-Id: I21157fd9ab5589f0ec8e18ac321b2ac7177ad9b2
bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method, bool osr) {
DCHECK(!method->IsProxyMethod());
+ DCHECK(method->GetDeclaringClass()->IsResolved());
+
TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit));
- StackHandleScope<2> hs(self);
self->AssertNoPendingException();
Runtime* runtime = Runtime::Current();
- // Ensure the class is initialized.
- Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
- if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
- VLOG(jit) << "JIT failed to initialize " << method->PrettyMethod();
- return false;
- }
-
// Do the compilation.
bool success = false;
{
--- /dev/null
+JNI_OnLoad called
--- /dev/null
+Regression test for the JIT compiler, which used to wait
+on a class object, meaning applocation code could just block
+all JIT compilations.
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ System.loadLibrary(args[0]);
+ if (!hasJit()) {
+ return;
+ }
+ Foo.hotMethod();
+ }
+
+ public native static boolean isJitCompiled(Class<?> cls, String methodName);
+ private native static boolean hasJit();
+}
+
+class Foo {
+ static void hotMethod() {
+ for (int i = 0; i < array.length; ++i) {
+ array[i] = array;
+ }
+ }
+
+ static {
+ array = new Object[10000];
+ while (!Main.isJitCompiled(Foo.class, "hotMethod")) {
+ Foo.hotMethod();
+ Thread.yield();
+ }
+ }
+
+ static Object[] array;
+}
CHECK(chars.c_str() != nullptr);
ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
chars.c_str(), kRuntimePointerSize);
- const void* code = method->GetOatMethodQuickCode(kRuntimePointerSize);
- jit::Jit* jit = Runtime::Current()->GetJit();
- if (jit != nullptr && jit->GetCodeCache()->ContainsPc(code)) {
- return true;
+ return method->GetOatMethodQuickCode(kRuntimePointerSize) != nullptr;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_Main_isJitCompiled(JNIEnv* env,
+ jclass,
+ jclass cls,
+ jstring method_name) {
+ jit::Jit* jit = GetJitIfEnabled();
+ if (jit == nullptr) {
+ return false;
}
- return code != nullptr;
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ ScopedUtfChars chars(env, method_name);
+ CHECK(chars.c_str() != nullptr);
+ ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
+ chars.c_str(), kRuntimePointerSize);
+ return jit->GetCodeCache()->ContainsPc(method->GetEntryPointFromQuickCompiledCode());
}
extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env,