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