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