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::ArtMethod * method ATTRIBUTE_UNUSED)46 void MethodEntered(art::Thread* thread ATTRIBUTE_UNUSED,
47 art::ArtMethod* method ATTRIBUTE_UNUSED) override
48 REQUIRES_SHARED(art::Locks::mutator_lock_) {}
49
MethodExited(art::Thread * thread ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,art::MutableHandle<art::mirror::Object> & return_value ATTRIBUTE_UNUSED)50 void MethodExited(art::Thread* thread ATTRIBUTE_UNUSED,
51 art::ArtMethod* method ATTRIBUTE_UNUSED,
52 art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,
53 art::MutableHandle<art::mirror::Object>& return_value ATTRIBUTE_UNUSED)
54 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
55
MethodExited(art::Thread * thread ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,art::JValue & return_value ATTRIBUTE_UNUSED)56 void MethodExited(art::Thread* thread ATTRIBUTE_UNUSED,
57 art::ArtMethod* method ATTRIBUTE_UNUSED,
58 art::instrumentation::OptionalFrame frame ATTRIBUTE_UNUSED,
59 art::JValue& return_value ATTRIBUTE_UNUSED)
60 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
61
MethodUnwind(art::Thread * thread ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED)62 void MethodUnwind(art::Thread* thread ATTRIBUTE_UNUSED,
63 art::ArtMethod* method ATTRIBUTE_UNUSED,
64 uint32_t dex_pc ATTRIBUTE_UNUSED)
65 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
66
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)67 void DexPcMoved(art::Thread* thread ATTRIBUTE_UNUSED,
68 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
69 art::ArtMethod* method ATTRIBUTE_UNUSED,
70 uint32_t new_dex_pc ATTRIBUTE_UNUSED)
71 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
72
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)73 void FieldRead(art::Thread* thread ATTRIBUTE_UNUSED,
74 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
75 art::ArtMethod* method ATTRIBUTE_UNUSED,
76 uint32_t dex_pc ATTRIBUTE_UNUSED,
77 art::ArtField* field ATTRIBUTE_UNUSED)
78 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
79
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)80 void FieldWritten(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 art::Handle<art::mirror::Object> field_value ATTRIBUTE_UNUSED)
86 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
87
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)88 void FieldWritten(art::Thread* thread ATTRIBUTE_UNUSED,
89 art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
90 art::ArtMethod* method ATTRIBUTE_UNUSED,
91 uint32_t dex_pc ATTRIBUTE_UNUSED,
92 art::ArtField* field ATTRIBUTE_UNUSED,
93 const art::JValue& field_value ATTRIBUTE_UNUSED)
94 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
95
ExceptionThrown(art::Thread * thread ATTRIBUTE_UNUSED,art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)96 void ExceptionThrown(art::Thread* thread ATTRIBUTE_UNUSED,
97 art::Handle<art::mirror::Throwable> exception_object ATTRIBUTE_UNUSED)
98 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
99
ExceptionHandled(art::Thread * self ATTRIBUTE_UNUSED,art::Handle<art::mirror::Throwable> throwable ATTRIBUTE_UNUSED)100 void ExceptionHandled(art::Thread* self ATTRIBUTE_UNUSED,
101 art::Handle<art::mirror::Throwable> throwable ATTRIBUTE_UNUSED)
102 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
103
Branch(art::Thread * thread ATTRIBUTE_UNUSED,art::ArtMethod * method ATTRIBUTE_UNUSED,uint32_t dex_pc ATTRIBUTE_UNUSED,int32_t dex_pc_offset ATTRIBUTE_UNUSED)104 void Branch(art::Thread* thread ATTRIBUTE_UNUSED,
105 art::ArtMethod* method ATTRIBUTE_UNUSED,
106 uint32_t dex_pc ATTRIBUTE_UNUSED,
107 int32_t dex_pc_offset ATTRIBUTE_UNUSED)
108 override REQUIRES_SHARED(art::Locks::mutator_lock_) { }
109
WatchedFramePop(art::Thread * thread ATTRIBUTE_UNUSED,const art::ShadowFrame & frame ATTRIBUTE_UNUSED)110 void WatchedFramePop(art::Thread* thread ATTRIBUTE_UNUSED,
111 const art::ShadowFrame& frame ATTRIBUTE_UNUSED)
112 override 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