• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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