• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,art::ArtMethod * method)46   void MethodEntered([[maybe_unused]] art::Thread* thread,
47                      [[maybe_unused]] art::ArtMethod* method) override
48       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
49 
MethodExited(art::Thread * thread,art::ArtMethod * method,art::instrumentation::OptionalFrame frame,art::MutableHandle<art::mirror::Object> & return_value)50   void MethodExited([[maybe_unused]] art::Thread* thread,
51                     [[maybe_unused]] art::ArtMethod* method,
52                     [[maybe_unused]] art::instrumentation::OptionalFrame frame,
53                     [[maybe_unused]] art::MutableHandle<art::mirror::Object>& return_value) override
54       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
55 
MethodExited(art::Thread * thread,art::ArtMethod * method,art::instrumentation::OptionalFrame frame,art::JValue & return_value)56   void MethodExited([[maybe_unused]] art::Thread* thread,
57                     [[maybe_unused]] art::ArtMethod* method,
58                     [[maybe_unused]] art::instrumentation::OptionalFrame frame,
59                     [[maybe_unused]] art::JValue& return_value) override
60       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
61 
MethodUnwind(art::Thread * thread,art::ArtMethod * method,uint32_t dex_pc)62   void MethodUnwind([[maybe_unused]] art::Thread* thread,
63                     [[maybe_unused]] art::ArtMethod* method,
64                     [[maybe_unused]] uint32_t dex_pc) override
65       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
66 
DexPcMoved(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t new_dex_pc)67   void DexPcMoved([[maybe_unused]] art::Thread* thread,
68                   [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
69                   [[maybe_unused]] art::ArtMethod* method,
70                   [[maybe_unused]] uint32_t new_dex_pc) override
71       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
72 
FieldRead(art::Thread * thread,art::Handle<art::mirror::Object> this_object,art::ArtMethod * method,uint32_t dex_pc,art::ArtField * field)73   void FieldRead([[maybe_unused]] art::Thread* thread,
74                  [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
75                  [[maybe_unused]] art::ArtMethod* method,
76                  [[maybe_unused]] uint32_t dex_pc,
77                  [[maybe_unused]] art::ArtField* field) override
78       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
79 
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   void FieldWritten([[maybe_unused]] art::Thread* thread,
81                     [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
82                     [[maybe_unused]] art::ArtMethod* method,
83                     [[maybe_unused]] uint32_t dex_pc,
84                     [[maybe_unused]] art::ArtField* field,
85                     [[maybe_unused]] art::Handle<art::mirror::Object> field_value) override
86       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
87 
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   void FieldWritten([[maybe_unused]] art::Thread* thread,
89                     [[maybe_unused]] art::Handle<art::mirror::Object> this_object,
90                     [[maybe_unused]] art::ArtMethod* method,
91                     [[maybe_unused]] uint32_t dex_pc,
92                     [[maybe_unused]] art::ArtField* field,
93                     [[maybe_unused]] const art::JValue& field_value) override
94       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
95 
ExceptionThrown(art::Thread * thread,art::Handle<art::mirror::Throwable> exception_object)96   void ExceptionThrown([[maybe_unused]] art::Thread* thread,
97                        [[maybe_unused]] art::Handle<art::mirror::Throwable> exception_object)
98       override REQUIRES_SHARED(art::Locks::mutator_lock_) {}
99 
ExceptionHandled(art::Thread * self,art::Handle<art::mirror::Throwable> throwable)100   void ExceptionHandled([[maybe_unused]] art::Thread* self,
101                         [[maybe_unused]] art::Handle<art::mirror::Throwable> throwable) override
102       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
103 
Branch(art::Thread * thread,art::ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset)104   void Branch([[maybe_unused]] art::Thread* thread,
105               [[maybe_unused]] art::ArtMethod* method,
106               [[maybe_unused]] uint32_t dex_pc,
107               [[maybe_unused]] int32_t dex_pc_offset) override
108       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
109 
WatchedFramePop(art::Thread * thread,const art::ShadowFrame & frame)110   void WatchedFramePop([[maybe_unused]] art::Thread* thread,
111                        [[maybe_unused]] const art::ShadowFrame& frame) override
112       REQUIRES_SHARED(art::Locks::mutator_lock_) {}
113 
114  private:
115   DISALLOW_COPY_AND_ASSIGN(Tracer);
116 };
117 
118 Tracer gEmptyTracer;
119 
StartTracing()120 static void StartTracing() REQUIRES(!art::Locks::mutator_lock_,
121                                     !art::Locks::thread_list_lock_,
122                                     !art::Locks::thread_suspend_count_lock_) {
123   art::Thread* self = art::Thread::Current();
124   art::Runtime* runtime = art::Runtime::Current();
125   art::gc::ScopedGCCriticalSection gcs(self,
126                                        art::gc::kGcCauseInstrumentation,
127                                        art::gc::kCollectorTypeInstrumentation);
128   art::ScopedSuspendAll ssa("starting fast tracing");
129   runtime->GetInstrumentation()->AddListener(&gEmptyTracer,
130                                              art::instrumentation::Instrumentation::kMethodEntered |
131                                              art::instrumentation::Instrumentation::kMethodExited |
132                                              art::instrumentation::Instrumentation::kMethodUnwind);
133   runtime->GetInstrumentation()->EnableMethodTracing(
134       kTracerInstrumentationKey, &gEmptyTracer, kNeedsInterpreter);
135 }
136 
137 class TraceFastPhaseCB : public art::RuntimePhaseCallback {
138  public:
TraceFastPhaseCB()139   TraceFastPhaseCB() {}
140 
NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)141   void NextRuntimePhase(art::RuntimePhaseCallback::RuntimePhase phase)
142       override REQUIRES_SHARED(art::Locks::mutator_lock_) {
143     if (phase == art::RuntimePhaseCallback::RuntimePhase::kInit) {
144       art::ScopedThreadSuspension sts(art::Thread::Current(),
145                                       art::ThreadState::kWaitingForMethodTracingStart);
146       StartTracing();
147     }
148   }
149 };
150 TraceFastPhaseCB gPhaseCallback;
151 
152 // The plugin initialization function.
ArtPlugin_Initialize()153 extern "C" bool ArtPlugin_Initialize() {
154   art::Runtime* runtime = art::Runtime::Current();
155   art::ScopedThreadStateChange stsc(art::Thread::Current(),
156                                     art::ThreadState::kWaitingForMethodTracingStart);
157   art::ScopedSuspendAll ssa("Add phase callback");
158   runtime->GetRuntimeCallbacks()->AddRuntimePhaseCallback(&gPhaseCallback);
159   return true;
160 }
161 
ArtPlugin_Deinitialize()162 extern "C" bool ArtPlugin_Deinitialize() {
163   // Don't need to bother doing anything.
164   return true;
165 }
166 
167 }  // namespace tracefast
168