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
27 namespace art {
28
29 class OsrVisitor : public StackVisitor {
30 public:
OsrVisitor(Thread * thread,const char * method_name)31 explicit OsrVisitor(Thread* thread, const char* method_name)
32 REQUIRES_SHARED(Locks::mutator_lock_)
33 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
34 method_name_(method_name),
35 in_osr_method_(false),
36 in_interpreter_(false) {}
37
VisitFrame()38 bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
39 ArtMethod* m = GetMethod();
40 std::string m_name(m->GetName());
41
42 if (m_name.compare(method_name_) == 0) {
43 const OatQuickMethodHeader* header =
44 Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m);
45 if (header != nullptr && header == GetCurrentOatQuickMethodHeader()) {
46 in_osr_method_ = true;
47 } else if (IsShadowFrame()) {
48 in_interpreter_ = true;
49 }
50 return false;
51 }
52 return true;
53 }
54
55 const char* const method_name_;
56 bool in_osr_method_;
57 bool in_interpreter_;
58 };
59
Java_Main_isInOsrCode(JNIEnv * env,jclass,jstring method_name)60 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInOsrCode(JNIEnv* env,
61 jclass,
62 jstring method_name) {
63 jit::Jit* jit = Runtime::Current()->GetJit();
64 if (jit == nullptr) {
65 // Just return true for non-jit configurations to stop the infinite loop.
66 return JNI_TRUE;
67 }
68 ScopedUtfChars chars(env, method_name);
69 CHECK(chars.c_str() != nullptr);
70 ScopedObjectAccess soa(Thread::Current());
71 OsrVisitor visitor(soa.Self(), chars.c_str());
72 visitor.WalkStack();
73 return visitor.in_osr_method_;
74 }
75
Java_Main_isInInterpreter(JNIEnv * env,jclass,jstring method_name)76 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInInterpreter(JNIEnv* env,
77 jclass,
78 jstring method_name) {
79 if (!Runtime::Current()->UseJitCompilation()) {
80 // The return value is irrelevant if we're not using JIT.
81 return false;
82 }
83 ScopedUtfChars chars(env, method_name);
84 CHECK(chars.c_str() != nullptr);
85 ScopedObjectAccess soa(Thread::Current());
86 OsrVisitor visitor(soa.Self(), chars.c_str());
87 visitor.WalkStack();
88 return visitor.in_interpreter_;
89 }
90
91 class ProfilingInfoVisitor : public StackVisitor {
92 public:
ProfilingInfoVisitor(Thread * thread,const char * method_name)93 explicit ProfilingInfoVisitor(Thread* thread, const char* method_name)
94 REQUIRES_SHARED(Locks::mutator_lock_)
95 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
96 method_name_(method_name) {}
97
VisitFrame()98 bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
99 ArtMethod* m = GetMethod();
100 std::string m_name(m->GetName());
101
102 if (m_name.compare(method_name_) == 0) {
103 ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true);
104 return false;
105 }
106 return true;
107 }
108
109 const char* const method_name_;
110 };
111
Java_Main_ensureHasProfilingInfo(JNIEnv * env,jclass,jstring method_name)112 extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasProfilingInfo(JNIEnv* env,
113 jclass,
114 jstring method_name) {
115 if (!Runtime::Current()->UseJitCompilation()) {
116 return;
117 }
118 ScopedUtfChars chars(env, method_name);
119 CHECK(chars.c_str() != nullptr);
120 ScopedObjectAccess soa(Thread::Current());
121 ProfilingInfoVisitor visitor(soa.Self(), chars.c_str());
122 visitor.WalkStack();
123 }
124
125 class OsrCheckVisitor : public StackVisitor {
126 public:
OsrCheckVisitor(Thread * thread,const char * method_name)127 OsrCheckVisitor(Thread* thread, const char* method_name)
128 REQUIRES_SHARED(Locks::mutator_lock_)
129 : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
130 method_name_(method_name) {}
131
VisitFrame()132 bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
133 ArtMethod* m = GetMethod();
134 std::string m_name(m->GetName());
135
136 jit::Jit* jit = Runtime::Current()->GetJit();
137 if (m_name.compare(method_name_) == 0) {
138 while (jit->GetCodeCache()->LookupOsrMethodHeader(m) == nullptr) {
139 // Sleep to yield to the compiler thread.
140 usleep(1000);
141 // Will either ensure it's compiled or do the compilation itself.
142 jit->CompileMethod(m, Thread::Current(), /* osr */ true);
143 }
144 return false;
145 }
146 return true;
147 }
148
149 const char* const method_name_;
150 };
151
Java_Main_ensureHasOsrCode(JNIEnv * env,jclass,jstring method_name)152 extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasOsrCode(JNIEnv* env,
153 jclass,
154 jstring method_name) {
155 if (!Runtime::Current()->UseJitCompilation()) {
156 return;
157 }
158 ScopedUtfChars chars(env, method_name);
159 CHECK(chars.c_str() != nullptr);
160 ScopedObjectAccess soa(Thread::Current());
161 OsrCheckVisitor visitor(soa.Self(), chars.c_str());
162 visitor.WalkStack();
163 }
164
165 } // namespace art
166