/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "art_method-inl.h" #include "jit/jit.h" #include "jit/jit_code_cache.h" #include "jit/profiling_info.h" #include "oat_quick_method_header.h" #include "scoped_thread_state_change.h" #include "ScopedUtfChars.h" #include "stack_map.h" namespace art { class OsrVisitor : public StackVisitor { public: explicit OsrVisitor(Thread* thread, const char* method_name) SHARED_REQUIRES(Locks::mutator_lock_) : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_name_(method_name), in_osr_method_(false), in_interpreter_(false) {} bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); if (m_name.compare(method_name_) == 0) { const OatQuickMethodHeader* header = Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m); if (header != nullptr && header == GetCurrentOatQuickMethodHeader()) { in_osr_method_ = true; } else if (IsCurrentFrameInInterpreter()) { in_interpreter_ = true; } return false; } return true; } const char* const method_name_; bool in_osr_method_; bool in_interpreter_; }; extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInOsrCode(JNIEnv* env, jclass, jstring method_name) { jit::Jit* jit = Runtime::Current()->GetJit(); if (jit == nullptr) { // Just return true for non-jit configurations to stop the infinite loop. return JNI_TRUE; } ScopedUtfChars chars(env, method_name); CHECK(chars.c_str() != nullptr); ScopedObjectAccess soa(Thread::Current()); OsrVisitor visitor(soa.Self(), chars.c_str()); visitor.WalkStack(); return visitor.in_osr_method_; } extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInInterpreter(JNIEnv* env, jclass, jstring method_name) { if (!Runtime::Current()->UseJitCompilation()) { // The return value is irrelevant if we're not using JIT. return false; } ScopedUtfChars chars(env, method_name); CHECK(chars.c_str() != nullptr); ScopedObjectAccess soa(Thread::Current()); OsrVisitor visitor(soa.Self(), chars.c_str()); visitor.WalkStack(); return visitor.in_interpreter_; } class ProfilingInfoVisitor : public StackVisitor { public: explicit ProfilingInfoVisitor(Thread* thread, const char* method_name) SHARED_REQUIRES(Locks::mutator_lock_) : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_name_(method_name) {} bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); if (m_name.compare(method_name_) == 0) { ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true); return false; } return true; } const char* const method_name_; }; extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasProfilingInfo(JNIEnv* env, jclass, jstring method_name) { if (!Runtime::Current()->UseJitCompilation()) { return; } ScopedUtfChars chars(env, method_name); CHECK(chars.c_str() != nullptr); ScopedObjectAccess soa(Thread::Current()); ProfilingInfoVisitor visitor(soa.Self(), chars.c_str()); visitor.WalkStack(); } class OsrCheckVisitor : public StackVisitor { public: OsrCheckVisitor(Thread* thread, const char* method_name) SHARED_REQUIRES(Locks::mutator_lock_) : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), method_name_(method_name) {} bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { ArtMethod* m = GetMethod(); std::string m_name(m->GetName()); jit::Jit* jit = Runtime::Current()->GetJit(); if (m_name.compare(method_name_) == 0) { while (jit->GetCodeCache()->LookupOsrMethodHeader(m) == nullptr) { // Sleep to yield to the compiler thread. sleep(0); // Will either ensure it's compiled or do the compilation itself. jit->CompileMethod(m, Thread::Current(), /* osr */ true); } return false; } return true; } const char* const method_name_; }; extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasOsrCode(JNIEnv* env, jclass, jstring method_name) { if (!Runtime::Current()->UseJitCompilation()) { return; } ScopedUtfChars chars(env, method_name); CHECK(chars.c_str() != nullptr); ScopedObjectAccess soa(Thread::Current()); OsrCheckVisitor visitor(soa.Self(), chars.c_str()); visitor.WalkStack(); } } // namespace art