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: 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 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 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 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: 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 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 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: 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 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 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