blob: a841f9e6a280b6e496ab8491e3015456d2f2258e [file] [log] [blame]
Andreas Gampe89df7bf2015-09-30 13:13:21 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni.h"
18
Andreas Gampe542451c2016-07-26 09:02:02 -070019#include "base/enums.h"
Andreas Gampe89df7bf2015-09-30 13:13:21 -070020#include "base/logging.h"
21#include "dex_file-inl.h"
Alex Lightdba61482016-12-21 08:20:29 -080022#include "instrumentation.h"
Nicolas Geoffray491617a2016-07-19 17:06:23 +010023#include "jit/jit.h"
24#include "jit/jit_code_cache.h"
Andreas Gampe89df7bf2015-09-30 13:13:21 -070025#include "mirror/class-inl.h"
Nicolas Geoffray491617a2016-07-19 17:06:23 +010026#include "oat_quick_method_header.h"
Andreas Gampe89df7bf2015-09-30 13:13:21 -070027#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070028#include "scoped_thread_state_change-inl.h"
Nicolas Geoffray491617a2016-07-19 17:06:23 +010029#include "ScopedUtfChars.h"
Andreas Gampe89df7bf2015-09-30 13:13:21 -070030#include "thread-inl.h"
31
32namespace art {
33
Alex Lightdba61482016-12-21 08:20:29 -080034// public static native boolean hasJit();
35
Alex Light4e03c522017-01-14 01:48:01 +000036static jit::Jit* GetJitIfEnabled() {
Alex Lightdba61482016-12-21 08:20:29 -080037 Runtime* runtime = Runtime::Current();
Alex Light4e03c522017-01-14 01:48:01 +000038 bool can_jit =
39 runtime != nullptr
Alex Lightdba61482016-12-21 08:20:29 -080040 && runtime->GetJit() != nullptr
41 && runtime->GetInstrumentation()->GetCurrentInstrumentationLevel() !=
42 instrumentation::Instrumentation::InstrumentationLevel::kInstrumentWithInterpreter;
Alex Light4e03c522017-01-14 01:48:01 +000043 return can_jit ? runtime->GetJit() : nullptr;
44}
45
46extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasJit(JNIEnv*, jclass) {
47 return GetJitIfEnabled() != nullptr;
Alex Lightdba61482016-12-21 08:20:29 -080048}
49
Andreas Gampe89df7bf2015-09-30 13:13:21 -070050// public static native boolean hasOatFile();
51
52extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasOatFile(JNIEnv* env, jclass cls) {
53 ScopedObjectAccess soa(env);
54
Mathieu Chartier0795f232016-09-27 18:43:30 -070055 ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
Andreas Gampe89df7bf2015-09-30 13:13:21 -070056 const DexFile& dex_file = klass->GetDexFile();
57 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
58 return (oat_dex_file != nullptr) ? JNI_TRUE : JNI_FALSE;
59}
60
61// public static native boolean runtimeIsSoftFail();
62
63extern "C" JNIEXPORT jboolean JNICALL Java_Main_runtimeIsSoftFail(JNIEnv* env ATTRIBUTE_UNUSED,
64 jclass cls ATTRIBUTE_UNUSED) {
65 return Runtime::Current()->IsVerificationSoftFail() ? JNI_TRUE : JNI_FALSE;
66}
67
68// public static native boolean isDex2OatEnabled();
69
70extern "C" JNIEXPORT jboolean JNICALL Java_Main_isDex2OatEnabled(JNIEnv* env ATTRIBUTE_UNUSED,
71 jclass cls ATTRIBUTE_UNUSED) {
72 return Runtime::Current()->IsDex2OatEnabled();
73}
74
75// public static native boolean hasImage();
76
77extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasImage(JNIEnv* env ATTRIBUTE_UNUSED,
78 jclass cls ATTRIBUTE_UNUSED) {
Jeff Haodcdc85b2015-12-04 14:06:18 -080079 return Runtime::Current()->GetHeap()->HasBootImageSpace();
Andreas Gampe89df7bf2015-09-30 13:13:21 -070080}
81
82// public static native boolean isImageDex2OatEnabled();
83
84extern "C" JNIEXPORT jboolean JNICALL Java_Main_isImageDex2OatEnabled(JNIEnv* env ATTRIBUTE_UNUSED,
85 jclass cls ATTRIBUTE_UNUSED) {
86 return Runtime::Current()->IsImageDex2OatEnabled();
87}
88
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -070089// public static native boolean compiledWithOptimizing();
90// Did we use the optimizing compiler to compile this?
91
92extern "C" JNIEXPORT jboolean JNICALL Java_Main_compiledWithOptimizing(JNIEnv* env, jclass cls) {
93 ScopedObjectAccess soa(env);
94
Mathieu Chartier0795f232016-09-27 18:43:30 -070095 ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -070096 const DexFile& dex_file = klass->GetDexFile();
97 const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
98 if (oat_dex_file == nullptr) {
99 // Could be JIT, which also uses optimizing, but conservatively say no.
100 return JNI_FALSE;
101 }
102 const OatFile* oat_file = oat_dex_file->GetOatFile();
103 CHECK(oat_file != nullptr);
104
105 const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
106 CHECK(cmd_line != nullptr); // Huh? This should not happen.
107
108 // Check the backend.
109 constexpr const char* kCompilerBackend = "--compiler-backend=";
110 const char* backend = strstr(cmd_line, kCompilerBackend);
111 if (backend != nullptr) {
112 // If it's set, make sure it's optimizing.
113 backend += strlen(kCompilerBackend);
114 if (strncmp(backend, "Optimizing", strlen("Optimizing")) != 0) {
115 return JNI_FALSE;
116 }
117 }
118
119 // Check the filter.
120 constexpr const char* kCompilerFilter = "--compiler-filter=";
121 const char* filter = strstr(cmd_line, kCompilerFilter);
122 if (filter != nullptr) {
123 // If it's set, make sure it's not interpret-only|verify-none|verify-at-runtime.
124 // Note: The space filter might have an impact on the test, but ignore that for now.
125 filter += strlen(kCompilerFilter);
126 constexpr const char* kInterpretOnly = "interpret-only";
127 constexpr const char* kVerifyNone = "verify-none";
128 constexpr const char* kVerifyAtRuntime = "verify-at-runtime";
129 if (strncmp(filter, kInterpretOnly, strlen(kInterpretOnly)) == 0 ||
130 strncmp(filter, kVerifyNone, strlen(kVerifyNone)) == 0 ||
131 strncmp(filter, kVerifyAtRuntime, strlen(kVerifyAtRuntime)) == 0) {
132 return JNI_FALSE;
133 }
134 }
135
136 return JNI_TRUE;
137}
138
Nicolas Geoffray51c17fa2016-11-25 15:56:12 +0000139extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAotCompiled(JNIEnv* env,
140 jclass,
141 jclass cls,
142 jstring method_name) {
143 Thread* self = Thread::Current();
144 ScopedObjectAccess soa(self);
145 ScopedUtfChars chars(env, method_name);
146 CHECK(chars.c_str() != nullptr);
147 ArtMethod* method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
148 chars.c_str(), kRuntimePointerSize);
149 const void* code = method->GetOatMethodQuickCode(kRuntimePointerSize);
150 jit::Jit* jit = Runtime::Current()->GetJit();
151 if (jit != nullptr && jit->GetCodeCache()->ContainsPc(code)) {
152 return true;
153 }
154 return code != nullptr;
155}
156
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100157extern "C" JNIEXPORT void JNICALL Java_Main_ensureJitCompiled(JNIEnv* env,
158 jclass,
159 jclass cls,
160 jstring method_name) {
Alex Light4e03c522017-01-14 01:48:01 +0000161 jit::Jit* jit = GetJitIfEnabled();
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100162 if (jit == nullptr) {
163 return;
164 }
165
Nicolas Geoffray44cea192016-08-03 20:48:13 +0100166 Thread* self = Thread::Current();
Nicolas Geoffrayd55f4ab2016-08-02 18:49:25 +0100167 ArtMethod* method = nullptr;
168 {
Nicolas Geoffray44cea192016-08-03 20:48:13 +0100169 ScopedObjectAccess soa(self);
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100170
Nicolas Geoffrayd55f4ab2016-08-02 18:49:25 +0100171 ScopedUtfChars chars(env, method_name);
172 CHECK(chars.c_str() != nullptr);
Mathieu Chartier0795f232016-09-27 18:43:30 -0700173 method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
Nicolas Geoffrayd55f4ab2016-08-02 18:49:25 +0100174 chars.c_str(), kRuntimePointerSize);
Alex Light4e03c522017-01-14 01:48:01 +0000175 if (method == nullptr) {
176 method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
177 chars.c_str(), kRuntimePointerSize);
178 }
179 DCHECK(method != nullptr) << "Unable to find method called " << chars.c_str();
Nicolas Geoffrayd55f4ab2016-08-02 18:49:25 +0100180 }
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100181
182 jit::JitCodeCache* code_cache = jit->GetCodeCache();
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100183 while (true) {
Yevgeny Rouband5f56272016-09-28 10:38:25 +0700184 const void* pc = method->GetEntryPointFromQuickCompiledCode();
185 if (code_cache->ContainsPc(pc)) {
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100186 break;
187 } else {
188 // Sleep to yield to the compiler thread.
189 usleep(1000);
Nicolas Geoffray44cea192016-08-03 20:48:13 +0100190 ScopedObjectAccess soa(self);
Nicolas Geoffrayd55f4ab2016-08-02 18:49:25 +0100191 // Make sure there is a profiling info, required by the compiler.
Nicolas Geoffray44cea192016-08-03 20:48:13 +0100192 ProfilingInfo::Create(self, method, /* retry_allocation */ true);
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100193 // Will either ensure it's compiled or do the compilation itself.
Nicolas Geoffray44cea192016-08-03 20:48:13 +0100194 jit->CompileMethod(method, self, /* osr */ false);
Nicolas Geoffray491617a2016-07-19 17:06:23 +0100195 }
196 }
197}
198
Mingyao Yang063fc772016-08-02 11:02:54 -0700199extern "C" JNIEXPORT jboolean JNICALL Java_Main_hasSingleImplementation(JNIEnv* env,
200 jclass,
201 jclass cls,
202 jstring method_name) {
203 ArtMethod* method = nullptr;
204 ScopedObjectAccess soa(Thread::Current());
205 ScopedUtfChars chars(env, method_name);
206 CHECK(chars.c_str() != nullptr);
207 method = soa.Decode<mirror::Class>(cls)->FindDeclaredVirtualMethodByName(
208 chars.c_str(), kRuntimePointerSize);
209 return method->HasSingleImplementation();
210}
211
Calin Juravle857f0582016-12-20 14:36:59 +0000212extern "C" JNIEXPORT int JNICALL Java_Main_getHotnessCounter(JNIEnv* env,
213 jclass,
214 jclass cls,
215 jstring method_name) {
216 jit::Jit* jit = Runtime::Current()->GetJit();
217 if (jit == nullptr) {
218 // The hotness counter is valid only under JIT.
219 // If we don't JIT return 0 to match test expectations.
220 return 0;
221 }
222
223 ArtMethod* method = nullptr;
224 {
225 ScopedObjectAccess soa(Thread::Current());
226
227 ScopedUtfChars chars(env, method_name);
228 CHECK(chars.c_str() != nullptr);
229 method = soa.Decode<mirror::Class>(cls)->FindDeclaredDirectMethodByName(
230 chars.c_str(), kRuntimePointerSize);
231 }
232
233 return method->GetCounter();
234}
235
Andreas Gampe89df7bf2015-09-30 13:13:21 -0700236} // namespace art