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