• Home
  • History
  • Annotate
  • 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  #include "thread-current-inl.h"
27  
28  namespace art {
29  
30  namespace {
31  
32  template <typename Handler>
ProcessMethodWithName(JNIEnv * env,jstring method_name,const Handler & handler)33  void ProcessMethodWithName(JNIEnv* env, jstring method_name, const Handler& handler) {
34    ScopedUtfChars chars(env, method_name);
35    CHECK(chars.c_str() != nullptr);
36    ScopedObjectAccess soa(Thread::Current());
37    StackVisitor::WalkStack(
38        [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
39          std::string m_name(stack_visitor->GetMethod()->GetName());
40  
41          if (m_name.compare(chars.c_str()) == 0) {
42            handler(stack_visitor);
43            return false;
44          }
45          return true;
46        },
47        soa.Self(),
48        /* context= */ nullptr,
49        art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
50  }
51  
52  }  // namespace
53  
Java_Main_isInOsrCode(JNIEnv * env,jclass,jstring method_name)54  extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInOsrCode(JNIEnv* env,
55                                                              jclass,
56                                                              jstring method_name) {
57    jit::Jit* jit = Runtime::Current()->GetJit();
58    if (jit == nullptr) {
59      // Just return true for non-jit configurations to stop the infinite loop.
60      return JNI_TRUE;
61    }
62    bool in_osr_code = false;
63    ProcessMethodWithName(
64        env,
65        method_name,
66        [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
67          ArtMethod* m = stack_visitor->GetMethod();
68          const OatQuickMethodHeader* header =
69              Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m);
70          if (header != nullptr && header == stack_visitor->GetCurrentOatQuickMethodHeader()) {
71            in_osr_code = true;
72          }
73        });
74    return in_osr_code;
75  }
76  
Java_Main_isInInterpreter(JNIEnv * env,jclass,jstring method_name)77  extern "C" JNIEXPORT jboolean JNICALL Java_Main_isInInterpreter(JNIEnv* env,
78                                                                  jclass,
79                                                                  jstring method_name) {
80    if (!Runtime::Current()->UseJitCompilation()) {
81      // The return value is irrelevant if we're not using JIT.
82      return false;
83    }
84    bool in_interpreter = false;
85    ProcessMethodWithName(
86        env,
87        method_name,
88        [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
89          ArtMethod* m = stack_visitor->GetMethod();
90          const OatQuickMethodHeader* header =
91              Runtime::Current()->GetJit()->GetCodeCache()->LookupOsrMethodHeader(m);
92          if ((header == nullptr || header != stack_visitor->GetCurrentOatQuickMethodHeader()) &&
93              stack_visitor->IsShadowFrame()) {
94            in_interpreter = true;
95          }
96        });
97    return in_interpreter;
98  }
99  
Java_Main_ensureHasProfilingInfo(JNIEnv * env,jclass,jstring method_name)100  extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasProfilingInfo(JNIEnv* env,
101                                                                     jclass,
102                                                                     jstring method_name) {
103    if (!Runtime::Current()->UseJitCompilation()) {
104      return;
105    }
106    ProcessMethodWithName(
107        env,
108        method_name,
109        [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
110          ArtMethod* m = stack_visitor->GetMethod();
111          ProfilingInfo::Create(Thread::Current(), m, /* retry_allocation */ true);
112        });
113  }
114  
Java_Main_ensureHasOsrCode(JNIEnv * env,jclass,jstring method_name)115  extern "C" JNIEXPORT void JNICALL Java_Main_ensureHasOsrCode(JNIEnv* env,
116                                                               jclass,
117                                                               jstring method_name) {
118    if (!Runtime::Current()->UseJitCompilation()) {
119      return;
120    }
121    ProcessMethodWithName(
122        env,
123        method_name,
124        [&](const art::StackVisitor* stack_visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
125          ArtMethod* m = stack_visitor->GetMethod();
126          jit::Jit* jit = Runtime::Current()->GetJit();
127          while (jit->GetCodeCache()->LookupOsrMethodHeader(m) == nullptr) {
128            // Sleep to yield to the compiler thread.
129            usleep(1000);
130            // Will either ensure it's compiled or do the compilation itself.
131            jit->CompileMethod(m, Thread::Current(), /*baseline=*/ false, /*osr=*/ true);
132          }
133        });
134  }
135  
136  }  // namespace art
137