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