• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 "runtime_callbacks.h"
18 
19 #include <algorithm>
20 
21 #include "art_method.h"
22 #include "base/macros.h"
23 #include "base/mutex-inl.h"
24 #include "class_linker.h"
25 #include "monitor.h"
26 #include "thread-current-inl.h"
27 
28 namespace art {
29 
RuntimeCallbacks()30 RuntimeCallbacks::RuntimeCallbacks()
31     : callback_lock_(new ReaderWriterMutex("Runtime callbacks lock",
32                                            LockLevel::kGenericBottomLock)) {}
33 
34 // We don't want to be holding any locks when the actual event is called so we use this to define a
35 // helper that gets a copy of the current event list and returns it.
36 #define COPY(T)                                                   \
37   ([this]() -> decltype(this->T) {                                \
38     ReaderMutexLock mu(Thread::Current(), *this->callback_lock_); \
39     return std::vector<decltype(this->T)::value_type>(this->T);   \
40   })()
41 
42 template <typename T>
43 ALWAYS_INLINE
Remove(T * cb,std::vector<T * > * data)44 static inline void Remove(T* cb, std::vector<T*>* data) {
45   auto it = std::find(data->begin(), data->end(), cb);
46   if (it != data->end()) {
47     data->erase(it);
48   }
49 }
50 
AddDdmCallback(DdmCallback * cb)51 void RuntimeCallbacks::AddDdmCallback(DdmCallback* cb) {
52   WriterMutexLock mu(Thread::Current(), *callback_lock_);
53   ddm_callbacks_.push_back(cb);
54 }
55 
RemoveDdmCallback(DdmCallback * cb)56 void RuntimeCallbacks::RemoveDdmCallback(DdmCallback* cb) {
57   WriterMutexLock mu(Thread::Current(), *callback_lock_);
58   Remove(cb, &ddm_callbacks_);
59 }
60 
DdmPublishChunk(uint32_t type,const ArrayRef<const uint8_t> & data)61 void RuntimeCallbacks::DdmPublishChunk(uint32_t type, const ArrayRef<const uint8_t>& data) {
62   for (DdmCallback* cb : COPY(ddm_callbacks_)) {
63     cb->DdmPublishChunk(type, data);
64   }
65 }
66 
AddDebuggerControlCallback(DebuggerControlCallback * cb)67 void RuntimeCallbacks::AddDebuggerControlCallback(DebuggerControlCallback* cb) {
68   WriterMutexLock mu(Thread::Current(), *callback_lock_);
69   debugger_control_callbacks_.push_back(cb);
70 }
71 
RemoveDebuggerControlCallback(DebuggerControlCallback * cb)72 void RuntimeCallbacks::RemoveDebuggerControlCallback(DebuggerControlCallback* cb) {
73   WriterMutexLock mu(Thread::Current(), *callback_lock_);
74   Remove(cb, &debugger_control_callbacks_);
75 }
76 
IsDebuggerConfigured()77 bool RuntimeCallbacks::IsDebuggerConfigured() {
78   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
79     if (cb->IsDebuggerConfigured()) {
80       return true;
81     }
82   }
83   return false;
84 }
85 
StartDebugger()86 void RuntimeCallbacks::StartDebugger() {
87   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
88     cb->StartDebugger();
89   }
90 }
91 
StopDebugger()92 void RuntimeCallbacks::StopDebugger() {
93   for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
94     cb->StopDebugger();
95   }
96 }
97 
AddMethodInspectionCallback(MethodInspectionCallback * cb)98 void RuntimeCallbacks::AddMethodInspectionCallback(MethodInspectionCallback* cb) {
99   WriterMutexLock mu(Thread::Current(), *callback_lock_);
100   method_inspection_callbacks_.push_back(cb);
101 }
102 
RemoveMethodInspectionCallback(MethodInspectionCallback * cb)103 void RuntimeCallbacks::RemoveMethodInspectionCallback(MethodInspectionCallback* cb) {
104   WriterMutexLock mu(Thread::Current(), *callback_lock_);
105   Remove(cb, &method_inspection_callbacks_);
106 }
107 
IsMethodBeingInspected(ArtMethod * m)108 bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
109   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
110     if (cb->IsMethodBeingInspected(m)) {
111       return true;
112     }
113   }
114   return false;
115 }
116 
AddThreadLifecycleCallback(ThreadLifecycleCallback * cb)117 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
118   WriterMutexLock mu(Thread::Current(), *callback_lock_);
119   thread_callbacks_.push_back(cb);
120 }
121 
MonitorContendedLocking(Monitor * m)122 void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
123   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
124     cb->MonitorContendedLocking(m);
125   }
126 }
127 
MonitorContendedLocked(Monitor * m)128 void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) {
129   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
130     cb->MonitorContendedLocked(m);
131   }
132 }
133 
ObjectWaitStart(Handle<mirror::Object> m,int64_t timeout)134 void RuntimeCallbacks::ObjectWaitStart(Handle<mirror::Object> m, int64_t timeout) {
135   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
136     cb->ObjectWaitStart(m, timeout);
137   }
138 }
139 
MonitorWaitFinished(Monitor * m,bool timeout)140 void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) {
141   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
142     cb->MonitorWaitFinished(m, timeout);
143   }
144 }
145 
AddMonitorCallback(MonitorCallback * cb)146 void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) {
147   WriterMutexLock mu(Thread::Current(), *callback_lock_);
148   monitor_callbacks_.push_back(cb);
149 }
150 
RemoveMonitorCallback(MonitorCallback * cb)151 void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) {
152   WriterMutexLock mu(Thread::Current(), *callback_lock_);
153   Remove(cb, &monitor_callbacks_);
154 }
155 
ThreadParkStart(bool is_absolute,int64_t timeout)156 void RuntimeCallbacks::ThreadParkStart(bool is_absolute, int64_t timeout) {
157   for (ParkCallback * cb : COPY(park_callbacks_)) {
158     cb->ThreadParkStart(is_absolute, timeout);
159   }
160 }
161 
ThreadParkFinished(bool timeout)162 void RuntimeCallbacks::ThreadParkFinished(bool timeout) {
163   for (ParkCallback * cb : COPY(park_callbacks_)) {
164     cb->ThreadParkFinished(timeout);
165   }
166 }
167 
AddParkCallback(ParkCallback * cb)168 void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) {
169   WriterMutexLock mu(Thread::Current(), *callback_lock_);
170   park_callbacks_.push_back(cb);
171 }
172 
RemoveParkCallback(ParkCallback * cb)173 void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) {
174   WriterMutexLock mu(Thread::Current(), *callback_lock_);
175   Remove(cb, &park_callbacks_);
176 }
177 
RemoveThreadLifecycleCallback(ThreadLifecycleCallback * cb)178 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
179   WriterMutexLock mu(Thread::Current(), *callback_lock_);
180   Remove(cb, &thread_callbacks_);
181 }
182 
ThreadStart(Thread * self)183 void RuntimeCallbacks::ThreadStart(Thread* self) {
184   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
185     cb->ThreadStart(self);
186   }
187 }
188 
ThreadDeath(Thread * self)189 void RuntimeCallbacks::ThreadDeath(Thread* self) {
190   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
191     cb->ThreadDeath(self);
192   }
193 }
194 
AddClassLoadCallback(ClassLoadCallback * cb)195 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
196   WriterMutexLock mu(Thread::Current(), *callback_lock_);
197   class_callbacks_.push_back(cb);
198 }
199 
RemoveClassLoadCallback(ClassLoadCallback * cb)200 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
201   WriterMutexLock mu(Thread::Current(), *callback_lock_);
202   Remove(cb, &class_callbacks_);
203 }
204 
ClassLoad(Handle<mirror::Class> klass)205 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
206   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
207     cb->ClassLoad(klass);
208   }
209 }
210 
EndDefineClass()211 void RuntimeCallbacks::EndDefineClass() {
212   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
213     cb->EndDefineClass();
214   }
215 }
216 
BeginDefineClass()217 void RuntimeCallbacks::BeginDefineClass() {
218   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
219     cb->BeginDefineClass();
220   }
221 }
222 
223 
ClassPreDefine(const char * descriptor,Handle<mirror::Class> temp_class,Handle<mirror::ClassLoader> loader,const DexFile & initial_dex_file,const dex::ClassDef & initial_class_def,DexFile const ** final_dex_file,dex::ClassDef const ** final_class_def)224 void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
225                                       Handle<mirror::Class> temp_class,
226                                       Handle<mirror::ClassLoader> loader,
227                                       const DexFile& initial_dex_file,
228                                       const dex::ClassDef& initial_class_def,
229                                       /*out*/DexFile const** final_dex_file,
230                                       /*out*/dex::ClassDef const** final_class_def) {
231   DexFile const* current_dex_file = &initial_dex_file;
232   dex::ClassDef const* current_class_def = &initial_class_def;
233   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
234     DexFile const* new_dex_file = nullptr;
235     dex::ClassDef const* new_class_def = nullptr;
236     cb->ClassPreDefine(descriptor,
237                        temp_class,
238                        loader,
239                        *current_dex_file,
240                        *current_class_def,
241                        &new_dex_file,
242                        &new_class_def);
243     if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
244         (new_class_def != nullptr && new_class_def != current_class_def)) {
245       DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
246       current_dex_file = new_dex_file;
247       current_class_def = new_class_def;
248     }
249   }
250   *final_dex_file = current_dex_file;
251   *final_class_def = current_class_def;
252 }
253 
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)254 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
255   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
256     cb->ClassPrepare(temp_klass, klass);
257   }
258 }
259 
AddRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)260 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
261   WriterMutexLock mu(Thread::Current(), *callback_lock_);
262   sigquit_callbacks_.push_back(cb);
263 }
264 
RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)265 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
266   WriterMutexLock mu(Thread::Current(), *callback_lock_);
267   Remove(cb, &sigquit_callbacks_);
268 }
269 
SigQuit()270 void RuntimeCallbacks::SigQuit() {
271   for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) {
272     cb->SigQuit();
273   }
274 }
275 
AddRuntimePhaseCallback(RuntimePhaseCallback * cb)276 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
277   WriterMutexLock mu(Thread::Current(), *callback_lock_);
278   phase_callbacks_.push_back(cb);
279 }
280 
RemoveRuntimePhaseCallback(RuntimePhaseCallback * cb)281 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
282   WriterMutexLock mu(Thread::Current(), *callback_lock_);
283   Remove(cb, &phase_callbacks_);
284 }
285 
NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase)286 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
287   for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) {
288     cb->NextRuntimePhase(phase);
289   }
290 }
291 
AddMethodCallback(MethodCallback * cb)292 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
293   WriterMutexLock mu(Thread::Current(), *callback_lock_);
294   method_callbacks_.push_back(cb);
295 }
296 
RemoveMethodCallback(MethodCallback * cb)297 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
298   WriterMutexLock mu(Thread::Current(), *callback_lock_);
299   Remove(cb, &method_callbacks_);
300 }
301 
RegisterNativeMethod(ArtMethod * method,const void * in_cur_method,void ** new_method)302 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
303                                             const void* in_cur_method,
304                                             /*out*/void** new_method) {
305   void* cur_method = const_cast<void*>(in_cur_method);
306   *new_method = cur_method;
307   for (MethodCallback* cb : COPY(method_callbacks_)) {
308     cb->RegisterNativeMethod(method, cur_method, new_method);
309     if (*new_method != nullptr) {
310       cur_method = *new_method;
311     }
312   }
313 }
314 
AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)315 void RuntimeCallbacks::AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
316   WriterMutexLock mu(Thread::Current(), *callback_lock_);
317   reflective_value_visit_callbacks_.push_back(cb);
318 }
319 
RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)320 void RuntimeCallbacks::RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
321   WriterMutexLock mu(Thread::Current(), *callback_lock_);
322   Remove(cb, &reflective_value_visit_callbacks_);
323 }
324 
VisitReflectiveTargets(ReflectiveValueVisitor * visitor)325 void RuntimeCallbacks::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) {
326   for (ReflectiveValueVisitCallback* cb : COPY(reflective_value_visit_callbacks_)) {
327     cb->VisitReflectiveTargets(visitor);
328   }
329 }
330 
331 }  // namespace art
332