1 /*
2 * Copyright (C) 2016 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 "art_method-inl.h"
18 #include "jit/jit.h"
19 #include "jit/jit_code_cache.h"
20 #include "jit/profiling_info.h"
21 #include "nativehelper/ScopedUtfChars.h"
22 #include "oat_quick_method_header.h"
23 #include "scoped_thread_state_change-inl.h"
24 #include "stack.h"
25 #include "stack_map.h"
26 #include "thread-current-inl.h"
27
28 namespace art {
29
30 namespace {
31
32 template <typename Handler>
ProcessMethodWithName(JNIEnv * env,jstring method_name,const Handler & handler)33 void ProcessMethodWithName(JNIEnv* env, jstring method_name, const Handler& handler) {
34 ScopedUtfChars chars(env, method_name);
35 CHECK(chars.c_str() != nullptr);
36 ScopedObjectAccess soa(Thread::Current());
37 StackVisitor::WalkStack(
38 [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
39 std::string m_name(stack_visitor->GetMethod()->GetName());
40
41 if (m_name.compare(chars.c_str()) == 0) {
42 handler(stack_visitor);
43 return false;
44 }
45 return true;
46 },
47 soa.Self(),
48 /* context= */ nullptr,
49 art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
50 }
51
52 } // namespace
53
Java_Main_isInOsrCode(JNIEnv * env,jclass,jstring method_name)54 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInOsrCode(JNIEnv* env,
55 jclass,
56 jstring method_name) {
57 jit::Jit* jit = Runtime::Current()->GetJit();
58 if (jit == nullptr) {
59 // Just return true for non-jit configurations to stop the infinite loop.
60 return JNI_TRUE;
61 }
62 bool in_osr_code = false;
63 ProcessMethodWithName(
64 env,
65 method_name,
66 [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
67 ArtMethod* m = stack_visitor->GetMethod();
68 const OatQuickMethodHeader* header =
69 Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m);
70 if (header != nullptr && header == stack_visitor->GetCurrentOatQuickMethodHeader()) {
71 in_osr_code = true;
72 }
73 });
74 return in_osr_code;
75 }
76
Java_Main_isInInterpreter(JNIEnv * env,jclass,jstring method_name)77 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInInterpreter(JNIEnv* env,
78 jclass,
79 jstring method_name) {
80 if (!Runtime::Current()->UseJitCompilation()) {
81 // The return value is irrelevant if we're not using JIT.
82 return false;
83 }
84 bool in_interpreter = false;
85 ProcessMethodWithName(
86 env,
87 method_name,
88 [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
89 ArtMethod* m = stack_visitor->GetMethod();
90 const OatQuickMethodHeader* header =
91 Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m);
92 if ((header == nullptr || header != stack_visitor->GetCurrentOatQuickMethodHeader()) &&
93 (stack_visitor->IsShadowFrame() ||
94 stack_visitor->GetCurrentOatQuickMethodHeader()->IsNterpMethodHeader())) {
95 in_interpreter = true;
96 }
97 });
98 return in_interpreter;
99 }
100
Java_Main_ensureHasProfilingInfo(JNIEnv * env,jclass,jstring method_name)101 extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasProfilingInfo(JNIEnv* env,
102 jclass,
103 jstring method_name) {
104 if (!Runtime::Current()->UseJitCompilation()) {
105 return;
106 }
107 ProcessMethodWithName(
108 env,
109 method_name,
110 [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
111 ArtMethod* m = stack_visitor->GetMethod();
112 ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true);
113 });
114 }
115
Java_Main_ensureHasOsrCode(JNIEnv * env,jclass,jstring method_name)116 extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasOsrCode(JNIEnv* env,
117 jclass,
118 jstring method_name) {
119 if (!Runtime::Current()->UseJitCompilation()) {
120 return;
121 }
122 ProcessMethodWithName(
123 env,
124 method_name,
125 [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
126 ArtMethod* m = stack_visitor->GetMethod();
127 jit::Jit* jit = Runtime::Current()->GetJit();
128 while (jit->GetCodeCache()->LookupOsrMethodHeader(m) == nullptr) {
129 // Sleep to yield to the compiler thread.
130 usleep(1000);
131 // Will either ensure it's compiled or do the compilation itself.
132 jit->CompileMethod(
133 m, Thread::Current(), CompilationKind::kOsr, /*prejit=*/ false);
134 }
135 });
136 }
137
138 } // namespace art
139