189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe/* 289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * Copyright (C) 2015 The Android Open Source Project 389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * 489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * you may not use this file except in compliance with the License. 689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * You may obtain a copy of the License at 789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * 889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * 1089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * Unless required by applicable law or agreed to in writing, software 1189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 1289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * See the License for the specific language governing permissions and 1489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe * limitations under the License. 1589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe */ 1689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 1789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "jni.h" 1889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 1989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "base/logging.h" 2089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "dex_file-inl.h" 21ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray#include "jit/jit.h" 22ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray#include "jit/jit_code_cache.h" 2389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "mirror/class-inl.h" 2489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "nth_caller_visitor.h" 25ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray#include "oat_quick_method_header.h" 2689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "runtime.h" 2789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "scoped_thread_state_change.h" 28ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray#include "ScopedUtfChars.h" 2989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "stack.h" 3089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe#include "thread-inl.h" 3189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 3289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampenamespace art { 3389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 3489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe// public static native boolean hasOatFile(); 3589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 3689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_hasOatFile(JNIEnv* env, jclass cls) { 3789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe ScopedObjectAccess soa(env); 3889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 3989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe mirror::Class* klass = soa.Decode<mirror::Class*>(cls); 4089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe const DexFile& dex_file = klass->GetDexFile(); 4189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); 4289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe return (oat_dex_file != nullptr) ? JNI_TRUE : JNI_FALSE; 4389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} 4489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 4589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe// public static native boolean runtimeIsSoftFail(); 4689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 4789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_runtimeIsSoftFail(JNIEnv* env ATTRIBUTE_UNUSED, 4889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe jclass cls ATTRIBUTE_UNUSED) { 4989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe return Runtime::Current()->IsVerificationSoftFail() ? JNI_TRUE : JNI_FALSE; 5089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} 5189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 5289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe// public static native boolean isDex2OatEnabled(); 5389df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 5489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_isDex2OatEnabled(JNIEnv* env ATTRIBUTE_UNUSED, 5589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe jclass cls ATTRIBUTE_UNUSED) { 5689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe return Runtime::Current()->IsDex2OatEnabled(); 5789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} 5889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 5989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe// public static native boolean hasImage(); 6089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 6189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_hasImage(JNIEnv* env ATTRIBUTE_UNUSED, 6289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe jclass cls ATTRIBUTE_UNUSED) { 63dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao return Runtime::Current()->GetHeap()->HasBootImageSpace(); 6489df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} 6589df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 6689df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe// public static native boolean isImageDex2OatEnabled(); 6789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 6889df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_isImageDex2OatEnabled(JNIEnv* env ATTRIBUTE_UNUSED, 6989df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe jclass cls ATTRIBUTE_UNUSED) { 7089df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe return Runtime::Current()->IsImageDex2OatEnabled(); 7189df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} 7289df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe 730dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe// public static native boolean compiledWithOptimizing(); 740dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe// Did we use the optimizing compiler to compile this? 750dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 760dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampeextern "C" JNIEXPORT jboolean JNICALL Java_Main_compiledWithOptimizing(JNIEnv* env, jclass cls) { 770dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe ScopedObjectAccess soa(env); 780dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 790dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe mirror::Class* klass = soa.Decode<mirror::Class*>(cls); 800dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const DexFile& dex_file = klass->GetDexFile(); 810dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); 820dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe if (oat_dex_file == nullptr) { 830dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // Could be JIT, which also uses optimizing, but conservatively say no. 840dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe return JNI_FALSE; 850dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe } 860dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const OatFile* oat_file = oat_dex_file->GetOatFile(); 870dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe CHECK(oat_file != nullptr); 880dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 890dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey); 900dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe CHECK(cmd_line != nullptr); // Huh? This should not happen. 910dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 920dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // Check the backend. 930dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe constexpr const char* kCompilerBackend = "--compiler-backend="; 940dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const char* backend = strstr(cmd_line, kCompilerBackend); 950dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe if (backend != nullptr) { 960dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // If it's set, make sure it's optimizing. 970dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe backend += strlen(kCompilerBackend); 980dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe if (strncmp(backend, "Optimizing", strlen("Optimizing")) != 0) { 990dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe return JNI_FALSE; 1000dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe } 1010dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe } 1020dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 1030dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // Check the filter. 1040dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe constexpr const char* kCompilerFilter = "--compiler-filter="; 1050dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe const char* filter = strstr(cmd_line, kCompilerFilter); 1060dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe if (filter != nullptr) { 1070dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // If it's set, make sure it's not interpret-only|verify-none|verify-at-runtime. 1080dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe // Note: The space filter might have an impact on the test, but ignore that for now. 1090dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe filter += strlen(kCompilerFilter); 1100dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe constexpr const char* kInterpretOnly = "interpret-only"; 1110dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe constexpr const char* kVerifyNone = "verify-none"; 1120dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe constexpr const char* kVerifyAtRuntime = "verify-at-runtime"; 1130dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe if (strncmp(filter, kInterpretOnly, strlen(kInterpretOnly)) == 0 || 1140dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe strncmp(filter, kVerifyNone, strlen(kVerifyNone)) == 0 || 1150dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe strncmp(filter, kVerifyAtRuntime, strlen(kVerifyAtRuntime)) == 0) { 1160dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe return JNI_FALSE; 1170dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe } 1180dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe } 1190dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 1200dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe return JNI_TRUE; 1210dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe} 1220dfc9bc0cca3ae15dc75bbea3ca9b6d7508ce893Andreas Gampe 123ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffrayextern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env, 124ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jclass, 125ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jclass cls, 126ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jstring method_name) { 127ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jit::Jit* jit = Runtime::Current()->GetJit(); 128ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray if (jit == nullptr) { 129ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray return; 130ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray } 131ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray 132ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray ScopedObjectAccess soa(Thread::Current()); 133ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray 134ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray ScopedUtfChars chars(env, method_name); 135ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray CHECK(chars.c_str() != nullptr); 136ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray 137ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray mirror::Class* klass = soa.Decode<mirror::Class*>(cls); 138ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray ArtMethod* method = klass->FindDeclaredDirectMethodByName(chars.c_str(), sizeof(void*)); 139ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray 140ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jit::JitCodeCache* code_cache = jit->GetCodeCache(); 141ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray OatQuickMethodHeader* header = nullptr; 142ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray // Make sure there is a profiling info, required by the compiler. 143ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray ProfilingInfo::Create(soa.Self(), method, /* retry_allocation */ true); 144ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray while (true) { 145ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray header = OatQuickMethodHeader::FromEntryPoint(method->GetEntryPointFromQuickCompiledCode()); 146ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray if (code_cache->ContainsPc(header->GetCode())) { 147ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray break; 148ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray } else { 149ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray // Sleep to yield to the compiler thread. 150ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray usleep(1000); 151ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray // Will either ensure it's compiled or do the compilation itself. 152ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray jit->CompileMethod(method, soa.Self(), /* osr */ false); 153ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray } 154ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray } 155ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray} 156ae093d69f58c2b6257c3e5b82a32c135a1f33641Nicolas Geoffray 15789df7bfc41a4de9685f84e7db07f77db3fd485fcAndreas Gampe} // namespace art 158