1e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier/* 2e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Copyright 2014 The Android Open Source Project 3e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 4e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 5e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * you may not use this file except in compliance with the License. 6e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * You may obtain a copy of the License at 7e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 8e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 9e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * 10e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * Unless required by applicable law or agreed to in writing, software 11e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 12e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * See the License for the specific language governing permissions and 14e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier * limitations under the License. 15e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier */ 16e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 17e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit_instrumentation.h" 18e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h" 20e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit.h" 21e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "jit_code_cache.h" 22e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "scoped_thread_state_change.h" 23e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 24e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace art { 25e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiernamespace jit { 26e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 27e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartierclass JitCompileTask : public Task { 28e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier public: 293d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier explicit JitCompileTask(ArtMethod* method, JitInstrumentationCache* cache) 30e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier : method_(method), cache_(cache) { 31e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 32e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 33e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier virtual void Run(Thread* self) OVERRIDE { 34e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier ScopedObjectAccess soa(self); 35e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier VLOG(jit) << "JitCompileTask compiling method " << PrettyMethod(method_); 36e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (Runtime::Current()->GetJit()->CompileMethod(method_, self)) { 37e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier cache_->SignalCompiled(self, method_); 38e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } else { 39e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier VLOG(jit) << "Failed to compile method " << PrettyMethod(method_); 40e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 41e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 42e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 43e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier virtual void Finalize() OVERRIDE { 44e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier delete this; 45e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 46e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 47e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier private: 483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier ArtMethod* const method_; 49e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier JitInstrumentationCache* const cache_; 50414369a2e3f23e1408fc1cbf4f623014bd95cb8fMathieu Chartier 51414369a2e3f23e1408fc1cbf4f623014bd95cb8fMathieu Chartier DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask); 52e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}; 53e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 54e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJitInstrumentationCache::JitInstrumentationCache(size_t hot_method_threshold) 55e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier : lock_("jit instrumentation lock"), hot_method_threshold_(hot_method_threshold) { 56e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 57e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 58e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid JitInstrumentationCache::CreateThreadPool() { 59e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier thread_pool_.reset(new ThreadPool("Jit thread pool", 1)); 60e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 61e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 62e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiervoid JitInstrumentationCache::DeleteThreadPool() { 63e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier thread_pool_.reset(); 64e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 65e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 663d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid JitInstrumentationCache::SignalCompiled(Thread* self, ArtMethod* method) { 67e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier ScopedObjectAccessUnchecked soa(self); 68e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jmethodID method_id = soa.EncodeMethod(method); 69e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier MutexLock mu(self, lock_); 70e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier auto it = samples_.find(method_id); 71e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (it != samples_.end()) { 72e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier samples_.erase(it); 73e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 74e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 75e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 763d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid JitInstrumentationCache::AddSamples(Thread* self, ArtMethod* method, size_t count) { 77e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier ScopedObjectAccessUnchecked soa(self); 78e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // Since we don't have on-stack replacement, some methods can remain in the interpreter longer 79e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // than we want resulting in samples even after the method is compiled. 8056869c1f6441f5ba05ee155c5d8fcf4b821e0be2Mathieu Chartier if (method->IsClassInitializer() || method->IsNative() || 81e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier Runtime::Current()->GetJit()->GetCodeCache()->ContainsMethod(method)) { 82e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier return; 83e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 84e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier jmethodID method_id = soa.EncodeMethod(method); 85e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier bool is_hot = false; 86e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier { 87e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier MutexLock mu(self, lock_); 88e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier size_t sample_count = 0; 89e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier auto it = samples_.find(method_id); 90e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (it != samples_.end()) { 91e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier it->second += count; 92e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier sample_count = it->second; 93e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } else { 94e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier sample_count = count; 95e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier samples_.insert(std::make_pair(method_id, count)); 96e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 97e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier // If we have enough samples, mark as hot and request Jit compilation. 98e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (sample_count >= hot_method_threshold_ && sample_count - count < hot_method_threshold_) { 99e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier is_hot = true; 100e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 101e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 102e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (is_hot) { 103e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier if (thread_pool_.get() != nullptr) { 1043d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier thread_pool_->AddTask(self, new JitCompileTask( 1053d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier method->GetInterfaceMethodIfProxy(sizeof(void*)), this)); 106e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier thread_pool_->StartWorkers(self); 107e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } else { 108e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier VLOG(jit) << "Compiling hot method " << PrettyMethod(method); 1093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier Runtime::Current()->GetJit()->CompileMethod( 1103d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier method->GetInterfaceMethodIfProxy(sizeof(void*)), self); 111e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 112e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 113e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 114e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 115e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierJitInstrumentationListener::JitInstrumentationListener(JitInstrumentationCache* cache) 116e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier : instrumentation_cache_(cache) { 117e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier CHECK(instrumentation_cache_ != nullptr); 118e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} 119e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier 120e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace jit 121e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier} // namespace art 122