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