summaryrefslogtreecommitdiffstats
path: root/runtime/jit/jit_instrumentation.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/jit/jit_instrumentation.cc')
-rw-r--r--runtime/jit/jit_instrumentation.cc117
1 files changed, 117 insertions, 0 deletions
diff --git a/runtime/jit/jit_instrumentation.cc b/runtime/jit/jit_instrumentation.cc
new file mode 100644
index 0000000..160e678
--- /dev/null
+++ b/runtime/jit/jit_instrumentation.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 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 "jit_instrumentation.h"
+
+#include "jit.h"
+#include "jit_code_cache.h"
+#include "mirror/art_method-inl.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+namespace jit {
+
+class JitCompileTask : public Task {
+ public:
+ explicit JitCompileTask(mirror::ArtMethod* method, JitInstrumentationCache* cache)
+ : method_(method), cache_(cache) {
+ }
+
+ virtual void Run(Thread* self) OVERRIDE {
+ ScopedObjectAccess soa(self);
+ VLOG(jit) << "JitCompileTask compiling method " << PrettyMethod(method_);
+ if (Runtime::Current()->GetJit()->CompileMethod(method_, self)) {
+ cache_->SignalCompiled(self, method_);
+ } else {
+ VLOG(jit) << "Failed to compile method " << PrettyMethod(method_);
+ }
+ }
+
+ virtual void Finalize() OVERRIDE {
+ delete this;
+ }
+
+ private:
+ mirror::ArtMethod* const method_;
+ JitInstrumentationCache* const cache_;
+};
+
+JitInstrumentationCache::JitInstrumentationCache(size_t hot_method_threshold)
+ : lock_("jit instrumentation lock"), hot_method_threshold_(hot_method_threshold) {
+}
+
+void JitInstrumentationCache::CreateThreadPool() {
+ thread_pool_.reset(new ThreadPool("Jit thread pool", 1));
+}
+
+void JitInstrumentationCache::DeleteThreadPool() {
+ thread_pool_.reset();
+}
+
+void JitInstrumentationCache::SignalCompiled(Thread* self, mirror::ArtMethod* method) {
+ ScopedObjectAccessUnchecked soa(self);
+ jmethodID method_id = soa.EncodeMethod(method);
+ MutexLock mu(self, lock_);
+ auto it = samples_.find(method_id);
+ if (it != samples_.end()) {
+ samples_.erase(it);
+ }
+}
+
+void JitInstrumentationCache::AddSamples(Thread* self, mirror::ArtMethod* method, size_t count) {
+ ScopedObjectAccessUnchecked soa(self);
+ // Since we don't have on-stack replacement, some methods can remain in the interpreter longer
+ // than we want resulting in samples even after the method is compiled.
+ if (method->IsClassInitializer() ||
+ Runtime::Current()->GetJit()->GetCodeCache()->ContainsMethod(method)) {
+ return;
+ }
+ jmethodID method_id = soa.EncodeMethod(method);
+ bool is_hot = false;
+ {
+ MutexLock mu(self, lock_);
+ size_t sample_count = 0;
+ auto it = samples_.find(method_id);
+ if (it != samples_.end()) {
+ it->second += count;
+ sample_count = it->second;
+ } else {
+ sample_count = count;
+ samples_.insert(std::make_pair(method_id, count));
+ }
+ // If we have enough samples, mark as hot and request Jit compilation.
+ if (sample_count >= hot_method_threshold_ && sample_count - count < hot_method_threshold_) {
+ is_hot = true;
+ }
+ }
+ if (is_hot) {
+ if (thread_pool_.get() != nullptr) {
+ thread_pool_->AddTask(self, new JitCompileTask(method->GetInterfaceMethodIfProxy(), this));
+ thread_pool_->StartWorkers(self);
+ } else {
+ VLOG(jit) << "Compiling hot method " << PrettyMethod(method);
+ Runtime::Current()->GetJit()->CompileMethod(method->GetInterfaceMethodIfProxy(), self);
+ }
+ }
+}
+
+JitInstrumentationListener::JitInstrumentationListener(JitInstrumentationCache* cache)
+ : instrumentation_cache_(cache) {
+ CHECK(instrumentation_cache_ != nullptr);
+}
+
+} // namespace jit
+} // namespace art