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 #ifndef ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_
18 #define ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_
19 
20 #include <unordered_map>
21 
22 #include "instrumentation.h"
23 
24 #include "atomic.h"
25 #include "base/macros.h"
26 #include "base/mutex.h"
27 #include "gc_root.h"
28 #include "jni.h"
29 #include "object_callbacks.h"
30 #include "thread_pool.h"
31 
32 namespace art {
33 namespace mirror {
34   class Class;
35   class Object;
36   class Throwable;
37 }  // namespace mirror
38 class ArtField;
39 class ArtMethod;
40 union JValue;
41 class Thread;
42 
43 namespace jit {
44 
45 // Keeps track of which methods are hot.
46 class JitInstrumentationCache {
47  public:
48   explicit JitInstrumentationCache(size_t hot_method_threshold);
49   void AddSamples(Thread* self, ArtMethod* method, size_t samples)
50       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
51   void SignalCompiled(Thread* self, ArtMethod* method)
52       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
53   void CreateThreadPool();
54   void DeleteThreadPool();
55 
56  private:
57   Mutex lock_;
58   std::unordered_map<jmethodID, size_t> samples_;
59   size_t hot_method_threshold_;
60   std::unique_ptr<ThreadPool> thread_pool_;
61 
62   DISALLOW_IMPLICIT_CONSTRUCTORS(JitInstrumentationCache);
63 };
64 
65 class JitInstrumentationListener : public instrumentation::InstrumentationListener {
66  public:
67   explicit JitInstrumentationListener(JitInstrumentationCache* cache);
68 
MethodEntered(Thread * thread,mirror::Object *,ArtMethod * method,uint32_t)69   virtual void MethodEntered(Thread* thread, mirror::Object* /*this_object*/,
70                              ArtMethod* method, uint32_t /*dex_pc*/)
71       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
72     instrumentation_cache_->AddSamples(thread, method, 1);
73   }
MethodExited(Thread *,mirror::Object *,ArtMethod *,uint32_t,const JValue &)74   virtual void MethodExited(Thread* /*thread*/, mirror::Object* /*this_object*/,
75                             ArtMethod* /*method*/, uint32_t /*dex_pc*/,
76                             const JValue& /*return_value*/)
77       OVERRIDE { }
MethodUnwind(Thread *,mirror::Object *,ArtMethod *,uint32_t)78   virtual void MethodUnwind(Thread* /*thread*/, mirror::Object* /*this_object*/,
79                             ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { }
FieldRead(Thread *,mirror::Object *,ArtMethod *,uint32_t,ArtField *)80   virtual void FieldRead(Thread* /*thread*/, mirror::Object* /*this_object*/,
81                          ArtMethod* /*method*/, uint32_t /*dex_pc*/,
82                          ArtField* /*field*/) OVERRIDE { }
FieldWritten(Thread *,mirror::Object *,ArtMethod *,uint32_t,ArtField *,const JValue &)83   virtual void FieldWritten(Thread* /*thread*/, mirror::Object* /*this_object*/,
84                             ArtMethod* /*method*/, uint32_t /*dex_pc*/,
85                             ArtField* /*field*/, const JValue& /*field_value*/)
86       OVERRIDE { }
ExceptionCaught(Thread *,mirror::Throwable *)87   virtual void ExceptionCaught(Thread* /*thread*/,
88                                mirror::Throwable* /*exception_object*/) OVERRIDE { }
89 
DexPcMoved(Thread *,mirror::Object *,ArtMethod *,uint32_t)90   virtual void DexPcMoved(Thread* /*self*/, mirror::Object* /*this_object*/,
91                           ArtMethod* /*method*/, uint32_t /*new_dex_pc*/) OVERRIDE { }
92 
93   // We only care about how many dex instructions were executed in the Jit.
BackwardBranch(Thread * thread,ArtMethod * method,int32_t dex_pc_offset)94   virtual void BackwardBranch(Thread* thread, ArtMethod* method, int32_t dex_pc_offset)
95       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
96     CHECK_LE(dex_pc_offset, 0);
97     instrumentation_cache_->AddSamples(thread, method, 1);
98   }
99 
100  private:
101   JitInstrumentationCache* const instrumentation_cache_;
102 
103   DISALLOW_IMPLICIT_CONSTRUCTORS(JitInstrumentationListener);
104 };
105 
106 }  // namespace jit
107 }  // namespace art
108 
109 #endif  // ART_RUNTIME_JIT_JIT_INSTRUMENTATION_H_
110