xref: /aosp_15_r20/art/tools/tracefast-plugin/tracefast.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
18*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
19*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
20*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
21*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
22*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace tracefast {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker #if ((!defined(TRACEFAST_INTERPRETER) && !defined(TRACEFAST_TRAMPOLINE)) || \
29*795d594fSAndroid Build Coastguard Worker      (defined(TRACEFAST_INTERPRETER) && defined(TRACEFAST_TRAMPOLINE)))
30*795d594fSAndroid Build Coastguard Worker #error Must set one of TRACEFAST_TRAMPOLINE or TRACEFAST_INTERPRETER during build
31*795d594fSAndroid Build Coastguard Worker #endif
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #ifdef TRACEFAST_INTERPRETER
35*795d594fSAndroid Build Coastguard Worker static constexpr const char* kTracerInstrumentationKey = "tracefast_INTERPRETER";
36*795d594fSAndroid Build Coastguard Worker static constexpr bool kNeedsInterpreter = true;
37*795d594fSAndroid Build Coastguard Worker #else  // defined(TRACEFAST_TRAMPOLINE)
38*795d594fSAndroid Build Coastguard Worker static constexpr const char* kTracerInstrumentationKey = "tracefast_TRAMPOLINE";
39*795d594fSAndroid Build Coastguard Worker static constexpr bool kNeedsInterpreter = false;
40*795d594fSAndroid Build Coastguard Worker #endif  // TRACEFAST_INITERPRETER
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker class Tracer final : public art::instrumentation::InstrumentationListener {
43*795d594fSAndroid Build Coastguard Worker  public:
Tracer()44*795d594fSAndroid Build Coastguard Worker   Tracer() {}
45*795d594fSAndroid Build Coastguard Worker 
MethodEntered(art::Thread * thread,art::ArtMethod * method)46*795d594fSAndroid Build Coastguard Worker   void MethodEntered([[maybe_unused]] art::Thread* thread,
47*795d594fSAndroid Build Coastguard Worker                      [[maybe_unused]] art::ArtMethod* method) override
48*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
49*795d594fSAndroid Build Coastguard Worker 
MethodExited(art::Thread * thread,art::ArtMethod * method,art::instrumentation::OptionalFrame frame,art::MutableHandle<art::mirror::Object> & return_value)50*795d594fSAndroid Build Coastguard Worker   void MethodExited([[maybe_unused]] art::Thread* thread,
51*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtMethod* method,
52*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::instrumentation::OptionalFrame frame,
53*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::MutableHandle<art::mirror::Object>& return_value) override
54*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
55*795d594fSAndroid Build Coastguard Worker 
MethodExited(art::Thread * thread,art::ArtMethod * method,art::instrumentation::OptionalFrame frame,art::JValue & return_value)56*795d594fSAndroid Build Coastguard Worker   void MethodExited([[maybe_unused]] art::Thread* thread,
57*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtMethod* method,
58*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::instrumentation::OptionalFrame frame,
59*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::JValue& return_value) override
60*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
61*795d594fSAndroid Build Coastguard Worker 
MethodUnwind(art::Thread * thread,art::ArtMethod * method,uint32_t dex_pc)62*795d594fSAndroid Build Coastguard Worker   void MethodUnwind([[maybe_unused]] art::Thread* thread,
63*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtMethod* method,
64*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc) override
65*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
66*795d594fSAndroid Build Coastguard Worker 
DexPcMoved(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t new_dex_pc)67*795d594fSAndroid Build Coastguard Worker   void DexPcMoved([[maybe_unused]] art::Thread* thread,
68*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
69*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] art::ArtMethod* method,
70*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] uint32_t new_dex_pc) override
71*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
72*795d594fSAndroid Build Coastguard Worker 
FieldRead(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t dex_pc,art::ArtField * field)73*795d594fSAndroid Build Coastguard Worker   void FieldRead([[maybe_unused]] art::Thread* thread,
74*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
75*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] art::ArtMethod* method,
76*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] uint32_t dex_pc,
77*795d594fSAndroid Build Coastguard Worker                  [[maybe_unused]] art::ArtField* field) override
78*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
79*795d594fSAndroid Build Coastguard Worker 
FieldWritten(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t dex_pc,art::ArtField * field,art::Handle<art::mirror::Object> field_value)80*795d594fSAndroid Build Coastguard Worker   void FieldWritten([[maybe_unused]] art::Thread* thread,
81*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
82*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtMethod* method,
83*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc,
84*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtField* field,
85*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::Handle<art::mirror::Object> field_value) override
86*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
87*795d594fSAndroid Build Coastguard Worker 
FieldWritten(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t dex_pc,art::ArtField * field,const art::JValue & field_value)88*795d594fSAndroid Build Coastguard Worker   void FieldWritten([[maybe_unused]] art::Thread* thread,
89*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
90*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtMethod* method,
91*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] uint32_t dex_pc,
92*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] art::ArtField* field,
93*795d594fSAndroid Build Coastguard Worker                     [[maybe_unused]] const art::JValue& field_value) override
94*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
95*795d594fSAndroid Build Coastguard Worker 
ExceptionThrown(art::Thread * thread,art::Handle<art::mirror::Throwable> exception_object)96*795d594fSAndroid Build Coastguard Worker   void ExceptionThrown([[maybe_unused]] art::Thread* thread,
97*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] art::Handle<art::mirror::Throwable> exception_object)
98*795d594fSAndroid Build Coastguard Worker       override REQUIRES_SHARED(art::Locks::mutator_lock_) {}
99*795d594fSAndroid Build Coastguard Worker 
ExceptionHandled(art::Thread * self,art::Handle<art::mirror::Throwable> throwable)100*795d594fSAndroid Build Coastguard Worker   void ExceptionHandled([[maybe_unused]] art::Thread* self,
101*795d594fSAndroid Build Coastguard Worker                         [[maybe_unused]] art::Handle<art::mirror::Throwable> throwable) override
102*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
103*795d594fSAndroid Build Coastguard Worker 
Branch(art::Thread * thread,art::ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset)104*795d594fSAndroid Build Coastguard Worker   void Branch([[maybe_unused]] art::Thread* thread,
105*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] art::ArtMethod* method,
106*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] uint32_t dex_pc,
107*795d594fSAndroid Build Coastguard Worker               [[maybe_unused]] int32_t dex_pc_offset) override
108*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
109*795d594fSAndroid Build Coastguard Worker 
WatchedFramePop(art::Thread * thread,const art::ShadowFrame & frame)110*795d594fSAndroid Build Coastguard Worker   void WatchedFramePop([[maybe_unused]] art::Thread* thread,
111*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] const art::ShadowFrame& frame) override
112*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker  private:
115*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(Tracer);
116*795d594fSAndroid Build Coastguard Worker };
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker Tracer gEmptyTracer;
119*795d594fSAndroid Build Coastguard Worker 
StartTracing()120*795d594fSAndroid Build Coastguard Worker static void StartTracing() REQUIRES(!art::Locks::mutator_lock_,
121*795d594fSAndroid Build Coastguard Worker                                     !art::Locks::thread_list_lock_,
122*795d594fSAndroid Build Coastguard Worker                                     !art::Locks::thread_suspend_count_lock_) {
123*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
124*795d594fSAndroid Build Coastguard Worker   art::Runtime* runtime = art::Runtime::Current();
125*795d594fSAndroid Build Coastguard Worker   art::gc::ScopedGCCriticalSection gcs(self,
126*795d594fSAndroid Build Coastguard Worker                                        art::gc::kGcCauseInstrumentation,
127*795d594fSAndroid Build Coastguard Worker                                        art::gc::kCollectorTypeInstrumentation);
128*795d594fSAndroid Build Coastguard Worker   art::ScopedSuspendAll ssa("starting fast tracing");
129*795d594fSAndroid Build Coastguard Worker   runtime->GetInstrumentation()->AddListener(&gEmptyTracer,
130*795d594fSAndroid Build Coastguard Worker                                              art::instrumentation::Instrumentation::kMethodEntered |
131*795d594fSAndroid Build Coastguard Worker                                              art::instrumentation::Instrumentation::kMethodExited |
132*795d594fSAndroid Build Coastguard Worker                                              art::instrumentation::Instrumentation::kMethodUnwind);
133*795d594fSAndroid Build Coastguard Worker   runtime->GetInstrumentation()->EnableMethodTracing(
134*795d594fSAndroid Build Coastguard Worker       kTracerInstrumentationKey, &gEmptyTracer, kNeedsInterpreter);
135*795d594fSAndroid Build Coastguard Worker }
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker class TraceFastPhaseCB : public art::RuntimePhaseCallback {
138*795d594fSAndroid Build Coastguard Worker  public:
TraceFastPhaseCB()139*795d594fSAndroid Build Coastguard Worker   TraceFastPhaseCB() {}
140*795d594fSAndroid Build Coastguard Worker 
NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)141*795d594fSAndroid Build Coastguard Worker   void NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)
142*795d594fSAndroid Build Coastguard Worker       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
143*795d594fSAndroid Build Coastguard Worker     if (phase == art::RuntimePhaseCallback::RuntimePhase::kInit) {
144*795d594fSAndroid Build Coastguard Worker       art::ScopedThreadSuspension sts(art::Thread::Current(),
145*795d594fSAndroid Build Coastguard Worker                                       art::ThreadState::kWaitingForMethodTracingStart);
146*795d594fSAndroid Build Coastguard Worker       StartTracing();
147*795d594fSAndroid Build Coastguard Worker     }
148*795d594fSAndroid Build Coastguard Worker   }
149*795d594fSAndroid Build Coastguard Worker };
150*795d594fSAndroid Build Coastguard Worker TraceFastPhaseCB gPhaseCallback;
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker // The plugin initialization function.
ArtPlugin_Initialize()153*795d594fSAndroid Build Coastguard Worker extern "C" bool ArtPlugin_Initialize() {
154*795d594fSAndroid Build Coastguard Worker   art::Runtime* runtime = art::Runtime::Current();
155*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadStateChange stsc(art::Thread::Current(),
156*795d594fSAndroid Build Coastguard Worker                                     art::ThreadState::kWaitingForMethodTracingStart);
157*795d594fSAndroid Build Coastguard Worker   art::ScopedSuspendAll ssa("Add phase callback");
158*795d594fSAndroid Build Coastguard Worker   runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
159*795d594fSAndroid Build Coastguard Worker   return true;
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker 
ArtPlugin_Deinitialize()162*795d594fSAndroid Build Coastguard Worker extern "C" bool ArtPlugin_Deinitialize() {
163*795d594fSAndroid Build Coastguard Worker   // Don't need to bother doing anything.
164*795d594fSAndroid Build Coastguard Worker   return true;
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker }  // namespace tracefast
168