1 /*
2  * Copyright (C) 2018 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 "android-base/macros.h"
18 #include "gc/scoped_gc_critical_section.h"
19 #include "instrumentation.h"
20 #include "runtime.h"
21 #include "runtime_callbacks.h"
22 #include "scoped_thread_state_change-inl.h"
23 #include "thread-inl.h"
24 #include "thread_list.h"
25 
26 namespace tracefast {
27 
28 #if ((!defined(TRACEFAST_INTERPRETER) && !defined(TRACEFAST_TRAMPOLINE)) || \
29      (defined(TRACEFAST_INTERPRETER) && defined(TRACEFAST_TRAMPOLINE)))
30 #error Must set one of TRACEFAST_TRAMPOLINE or TRACEFAST_INTERPRETER during build
31 #endif
32 
33 
34 #ifdef TRACEFAST_INTERPRETER
35 static constexpr const char* kTracerInstrumentationKey = "tracefast_INTERPRETER";
36 static constexpr bool kNeedsInterpreter = true;
37 #else  // defined(TRACEFAST_TRAMPOLINE)
38 static constexpr const char* kTracerInstrumentationKey = "tracefast_TRAMPOLINE";
39 static constexpr bool kNeedsInterpreter = false;
40 #endif  // TRACEFAST_INITERPRETER
41 
42 class Tracer final : public art::instrumentation::InstrumentationListener {
43  public:
Tracer()44   Tracer() {}
45 
MethodEntered(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)46   void MethodEntered(art::Thread* thread ATTRIBUTE_UNUSED,
47                      art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
48                      art::ArtMethod* method ATTRIBUTE_UNUSED,
49                      uint32_t dex_pc ATTRIBUTE_UNUSED)
50       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
51 
MethodExited(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,art::MutableHandle<art::mirror::Object> & return_value ATTRIBUTE_UNUSED)52   void MethodExited(art::Thread* thread ATTRIBUTE_UNUSED,
53                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
54                     art::ArtMethod* method ATTRIBUTE_UNUSED,
55                     uint32_t dex_pc ATTRIBUTE_UNUSED,
56                     art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,
57                     art::MutableHandle<art::mirror::Object>& return_value ATTRIBUTE_UNUSED)
58       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
59 
MethodExited(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,art::JValue & return_value ATTRIBUTE_UNUSED)60   void MethodExited(art::Thread* thread ATTRIBUTE_UNUSED,
61                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
62                     art::ArtMethod* method ATTRIBUTE_UNUSED,
63                     uint32_t dex_pc ATTRIBUTE_UNUSED,
64                     art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,
65                     art::JValue& return_value ATTRIBUTE_UNUSED)
66       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
67 
MethodUnwind(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)68   void MethodUnwind(art::Thread* thread ATTRIBUTE_UNUSED,
69                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
70                     art::ArtMethod* method ATTRIBUTE_UNUSED,
71                     uint32_t dex_pc ATTRIBUTE_UNUSED)
72       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
73 
DexPcMoved(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t new_dex_pc ATTRIBUTE_UNUSED)74   void DexPcMoved(art::Thread* thread ATTRIBUTE_UNUSED,
75                   art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
76                   art::ArtMethod* method ATTRIBUTE_UNUSED,
77                   uint32_t new_dex_pc ATTRIBUTE_UNUSED)
78       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
79 
FieldRead(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,art::ArtField * field ATTRIBUTE_UNUSED)80   void FieldRead(art::Thread* thread ATTRIBUTE_UNUSED,
81                  art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
82                  art::ArtMethod* method ATTRIBUTE_UNUSED,
83                  uint32_t dex_pc ATTRIBUTE_UNUSED,
84                  art::ArtField* field ATTRIBUTE_UNUSED)
85       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
86 
FieldWritten(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,art::ArtField * field ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> field_value ATTRIBUTE_UNUSED)87   void FieldWritten(art::Thread* thread ATTRIBUTE_UNUSED,
88                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
89                     art::ArtMethod* method ATTRIBUTE_UNUSED,
90                     uint32_t dex_pc ATTRIBUTE_UNUSED,
91                     art::ArtField* field ATTRIBUTE_UNUSED,
92                     art::Handle<art::mirror::Object> field_value ATTRIBUTE_UNUSED)
93       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
94 
FieldWritten(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,art::ArtField * field ATTRIBUTE_UNUSED,const art::JValue & field_value ATTRIBUTE_UNUSED)95   void FieldWritten(art::Thread* thread ATTRIBUTE_UNUSED,
96                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
97                     art::ArtMethod* method ATTRIBUTE_UNUSED,
98                     uint32_t dex_pc ATTRIBUTE_UNUSED,
99                     art::ArtField* field ATTRIBUTE_UNUSED,
100                     const art::JValue& field_value ATTRIBUTE_UNUSED)
101       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
102 
ExceptionThrown(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)103   void ExceptionThrown(art::Thread* thread ATTRIBUTE_UNUSED,
104                        art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)
105       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
106 
ExceptionHandled(art::Thread * self ATTRIBUTE_UNUSED,art::Handle<art::mirror::Throwable> throwable ATTRIBUTE_UNUSED)107   void ExceptionHandled(art::Thread* self ATTRIBUTE_UNUSED,
108                         art::Handle<art::mirror::Throwable> throwable ATTRIBUTE_UNUSED)
109       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
110 
Branch(art::Thread * thread ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,int32_t dex_pc_offset ATTRIBUTE_UNUSED)111   void Branch(art::Thread* thread ATTRIBUTE_UNUSED,
112               art::ArtMethod* method ATTRIBUTE_UNUSED,
113               uint32_t dex_pc ATTRIBUTE_UNUSED,
114               int32_t dex_pc_offset ATTRIBUTE_UNUSED)
115       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
116 
WatchedFramePop(art::Thread * thread ATTRIBUTE_UNUSED,const art::ShadowFrame & frame ATTRIBUTE_UNUSED)117   void WatchedFramePop(art::Thread* thread ATTRIBUTE_UNUSED,
118                        const art::ShadowFrame& frame ATTRIBUTE_UNUSED)
119       override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
120 
121  private:
122   DISALLOW_COPY_AND_ASSIGN(Tracer);
123 };
124 
125 Tracer gEmptyTracer;
126 
StartTracing()127 static void StartTracing() REQUIRES(!art::Locks::mutator_lock_,
128                                     !art::Locks::thread_list_lock_,
129                                     !art::Locks::thread_suspend_count_lock_) {
130   art::Thread* self = art::Thread::Current();
131   art::Runtime* runtime = art::Runtime::Current();
132   art::gc::ScopedGCCriticalSection gcs(self,
133                                        art::gc::kGcCauseInstrumentation,
134                                        art::gc::kCollectorTypeInstrumentation);
135   art::ScopedSuspendAll ssa("starting fast tracing");
136   runtime->GetInstrumentation()->AddListener(&gEmptyTracer,
137                                              art::instrumentation::Instrumentation::kMethodEntered |
138                                              art::instrumentation::Instrumentation::kMethodExited |
139                                              art::instrumentation::Instrumentation::kMethodUnwind);
140   runtime->GetInstrumentation()->EnableMethodTracing(kTracerInstrumentationKey, kNeedsInterpreter);
141 }
142 
143 class TraceFastPhaseCB : public art::RuntimePhaseCallback {
144  public:
TraceFastPhaseCB()145   TraceFastPhaseCB() {}
146 
NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)147   void NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)
148       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
149     if (phase == art::RuntimePhaseCallback::RuntimePhase::kInit) {
150       art::ScopedThreadSuspension sts(art::Thread::Current(),
151                                       art::ThreadState::kWaitingForMethodTracingStart);
152       StartTracing();
153     }
154   }
155 };
156 TraceFastPhaseCB gPhaseCallback;
157 
158 // The plugin initialization function.
ArtPlugin_Initialize()159 extern "C" bool ArtPlugin_Initialize() {
160   art::Runtime* runtime = art::Runtime::Current();
161   art::ScopedThreadStateChange stsc(art::Thread::Current(),
162                                     art::ThreadState::kWaitingForMethodTracingStart);
163   art::ScopedSuspendAll ssa("Add phase callback");
164   runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
165   return true;
166 }
167 
ArtPlugin_Deinitialize()168 extern "C" bool ArtPlugin_Deinitialize() {
169   // Don't need to bother doing anything.
170   return true;
171 }
172 
173 }  // namespace tracefast
174