jit_instrumentation.cc revision 56869c1f6441f5ba05ee155c5d8fcf4b821e0be2
1/* 2 * Copyright 2014 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 "jit_instrumentation.h" 18 19#include "jit.h" 20#include "jit_code_cache.h" 21#include "mirror/art_method-inl.h" 22#include "scoped_thread_state_change.h" 23 24namespace art { 25namespace jit { 26 27class JitCompileTask : public Task { 28 public: 29 explicit JitCompileTask(mirror::ArtMethod* method, JitInstrumentationCache* cache) 30 : method_(method), cache_(cache) { 31 } 32 33 virtual void Run(Thread* self) OVERRIDE { 34 ScopedObjectAccess soa(self); 35 VLOG(jit) << "JitCompileTask compiling method " << PrettyMethod(method_); 36 if (Runtime::Current()->GetJit()->CompileMethod(method_, self)) { 37 cache_->SignalCompiled(self, method_); 38 } else { 39 VLOG(jit) << "Failed to compile method " << PrettyMethod(method_); 40 } 41 } 42 43 virtual void Finalize() OVERRIDE { 44 delete this; 45 } 46 47 private: 48 mirror::ArtMethod* const method_; 49 JitInstrumentationCache* const cache_; 50 51 DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask); 52}; 53 54JitInstrumentationCache::JitInstrumentationCache(size_t hot_method_threshold) 55 : lock_("jit instrumentation lock"), hot_method_threshold_(hot_method_threshold) { 56} 57 58void JitInstrumentationCache::CreateThreadPool() { 59 thread_pool_.reset(new ThreadPool("Jit thread pool", 1)); 60} 61 62void JitInstrumentationCache::DeleteThreadPool() { 63 thread_pool_.reset(); 64} 65 66void JitInstrumentationCache::SignalCompiled(Thread* self, mirror::ArtMethod* method) { 67 ScopedObjectAccessUnchecked soa(self); 68 jmethodID method_id = soa.EncodeMethod(method); 69 MutexLock mu(self, lock_); 70 auto it = samples_.find(method_id); 71 if (it != samples_.end()) { 72 samples_.erase(it); 73 } 74} 75 76void JitInstrumentationCache::AddSamples(Thread* self, mirror::ArtMethod* method, size_t count) { 77 ScopedObjectAccessUnchecked soa(self); 78 // Since we don't have on-stack replacement, some methods can remain in the interpreter longer 79 // than we want resulting in samples even after the method is compiled. 80 if (method->IsClassInitializer() || method->IsNative() || 81 Runtime::Current()->GetJit()->GetCodeCache()->ContainsMethod(method)) { 82 return; 83 } 84 jmethodID method_id = soa.EncodeMethod(method); 85 bool is_hot = false; 86 { 87 MutexLock mu(self, lock_); 88 size_t sample_count = 0; 89 auto it = samples_.find(method_id); 90 if (it != samples_.end()) { 91 it->second += count; 92 sample_count = it->second; 93 } else { 94 sample_count = count; 95 samples_.insert(std::make_pair(method_id, count)); 96 } 97 // If we have enough samples, mark as hot and request Jit compilation. 98 if (sample_count >= hot_method_threshold_ && sample_count - count < hot_method_threshold_) { 99 is_hot = true; 100 } 101 } 102 if (is_hot) { 103 if (thread_pool_.get() != nullptr) { 104 thread_pool_->AddTask(self, new JitCompileTask(method->GetInterfaceMethodIfProxy(), this)); 105 thread_pool_->StartWorkers(self); 106 } else { 107 VLOG(jit) << "Compiling hot method " << PrettyMethod(method); 108 Runtime::Current()->GetJit()->CompileMethod(method->GetInterfaceMethodIfProxy(), self); 109 } 110 } 111} 112 113JitInstrumentationListener::JitInstrumentationListener(JitInstrumentationCache* cache) 114 : instrumentation_cache_(cache) { 115 CHECK(instrumentation_cache_ != nullptr); 116} 117 118} // namespace jit 119} // namespace art 120