• 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 
IsMethodSafeToJit(ArtMethod * m)108 bool RuntimeCallbacks::IsMethodSafeToJit(ArtMethod* m) {
109   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
110     if (!cb->IsMethodSafeToJit(m)) {
111       DCHECK(cb->IsMethodBeingInspected(m))
112           << "Contract requires that !IsMethodSafeToJit(m) -> IsMethodBeingInspected(m)";
113       return false;
114     }
115   }
116   return true;
117 }
118 
IsMethodBeingInspected(ArtMethod * m)119 bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
120   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
121     if (cb->IsMethodBeingInspected(m)) {
122       return true;
123     }
124   }
125   return false;
126 }
127 
MethodNeedsDebugVersion(ArtMethod * m)128 bool RuntimeCallbacks::MethodNeedsDebugVersion(ArtMethod* m) {
129   for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
130     if (cb->MethodNeedsDebugVersion(m)) {
131       return true;
132     }
133   }
134   return false;
135 }
136 
AddThreadLifecycleCallback(ThreadLifecycleCallback * cb)137 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
138   WriterMutexLock mu(Thread::Current(), *callback_lock_);
139   thread_callbacks_.push_back(cb);
140 }
141 
MonitorContendedLocking(Monitor * m)142 void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
143   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
144     cb->MonitorContendedLocking(m);
145   }
146 }
147 
MonitorContendedLocked(Monitor * m)148 void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) {
149   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
150     cb->MonitorContendedLocked(m);
151   }
152 }
153 
ObjectWaitStart(Handle<mirror::Object> m,int64_t timeout)154 void RuntimeCallbacks::ObjectWaitStart(Handle<mirror::Object> m, int64_t timeout) {
155   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
156     cb->ObjectWaitStart(m, timeout);
157   }
158 }
159 
MonitorWaitFinished(Monitor * m,bool timeout)160 void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) {
161   for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
162     cb->MonitorWaitFinished(m, timeout);
163   }
164 }
165 
AddMonitorCallback(MonitorCallback * cb)166 void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) {
167   WriterMutexLock mu(Thread::Current(), *callback_lock_);
168   monitor_callbacks_.push_back(cb);
169 }
170 
RemoveMonitorCallback(MonitorCallback * cb)171 void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) {
172   WriterMutexLock mu(Thread::Current(), *callback_lock_);
173   Remove(cb, &monitor_callbacks_);
174 }
175 
ThreadParkStart(bool is_absolute,int64_t timeout)176 void RuntimeCallbacks::ThreadParkStart(bool is_absolute, int64_t timeout) {
177   for (ParkCallback * cb : COPY(park_callbacks_)) {
178     cb->ThreadParkStart(is_absolute, timeout);
179   }
180 }
181 
ThreadParkFinished(bool timeout)182 void RuntimeCallbacks::ThreadParkFinished(bool timeout) {
183   for (ParkCallback * cb : COPY(park_callbacks_)) {
184     cb->ThreadParkFinished(timeout);
185   }
186 }
187 
AddParkCallback(ParkCallback * cb)188 void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) {
189   WriterMutexLock mu(Thread::Current(), *callback_lock_);
190   park_callbacks_.push_back(cb);
191 }
192 
RemoveParkCallback(ParkCallback * cb)193 void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) {
194   WriterMutexLock mu(Thread::Current(), *callback_lock_);
195   Remove(cb, &park_callbacks_);
196 }
197 
RemoveThreadLifecycleCallback(ThreadLifecycleCallback * cb)198 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
199   WriterMutexLock mu(Thread::Current(), *callback_lock_);
200   Remove(cb, &thread_callbacks_);
201 }
202 
ThreadStart(Thread * self)203 void RuntimeCallbacks::ThreadStart(Thread* self) {
204   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
205     cb->ThreadStart(self);
206   }
207 }
208 
ThreadDeath(Thread * self)209 void RuntimeCallbacks::ThreadDeath(Thread* self) {
210   for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
211     cb->ThreadDeath(self);
212   }
213 }
214 
AddClassLoadCallback(ClassLoadCallback * cb)215 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
216   WriterMutexLock mu(Thread::Current(), *callback_lock_);
217   class_callbacks_.push_back(cb);
218 }
219 
RemoveClassLoadCallback(ClassLoadCallback * cb)220 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
221   WriterMutexLock mu(Thread::Current(), *callback_lock_);
222   Remove(cb, &class_callbacks_);
223 }
224 
ClassLoad(Handle<mirror::Class> klass)225 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
226   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
227     cb->ClassLoad(klass);
228   }
229 }
230 
EndDefineClass()231 void RuntimeCallbacks::EndDefineClass() {
232   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
233     cb->EndDefineClass();
234   }
235 }
236 
BeginDefineClass()237 void RuntimeCallbacks::BeginDefineClass() {
238   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
239     cb->BeginDefineClass();
240   }
241 }
242 
243 
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)244 void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
245                                       Handle<mirror::Class> temp_class,
246                                       Handle<mirror::ClassLoader> loader,
247                                       const DexFile& initial_dex_file,
248                                       const dex::ClassDef& initial_class_def,
249                                       /*out*/DexFile const** final_dex_file,
250                                       /*out*/dex::ClassDef const** final_class_def) {
251   DexFile const* current_dex_file = &initial_dex_file;
252   dex::ClassDef const* current_class_def = &initial_class_def;
253   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
254     DexFile const* new_dex_file = nullptr;
255     dex::ClassDef const* new_class_def = nullptr;
256     cb->ClassPreDefine(descriptor,
257                        temp_class,
258                        loader,
259                        *current_dex_file,
260                        *current_class_def,
261                        &new_dex_file,
262                        &new_class_def);
263     if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
264         (new_class_def != nullptr && new_class_def != current_class_def)) {
265       DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
266       current_dex_file = new_dex_file;
267       current_class_def = new_class_def;
268     }
269   }
270   *final_dex_file = current_dex_file;
271   *final_class_def = current_class_def;
272 }
273 
ClassPrepare(Handle<mirror::Class> temp_klass,Handle<mirror::Class> klass)274 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
275   for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
276     cb->ClassPrepare(temp_klass, klass);
277   }
278 }
279 
AddRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)280 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
281   WriterMutexLock mu(Thread::Current(), *callback_lock_);
282   sigquit_callbacks_.push_back(cb);
283 }
284 
RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback * cb)285 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
286   WriterMutexLock mu(Thread::Current(), *callback_lock_);
287   Remove(cb, &sigquit_callbacks_);
288 }
289 
SigQuit()290 void RuntimeCallbacks::SigQuit() {
291   for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) {
292     cb->SigQuit();
293   }
294 }
295 
AddRuntimePhaseCallback(RuntimePhaseCallback * cb)296 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
297   WriterMutexLock mu(Thread::Current(), *callback_lock_);
298   phase_callbacks_.push_back(cb);
299 }
300 
RemoveRuntimePhaseCallback(RuntimePhaseCallback * cb)301 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
302   WriterMutexLock mu(Thread::Current(), *callback_lock_);
303   Remove(cb, &phase_callbacks_);
304 }
305 
NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase)306 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
307   for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) {
308     cb->NextRuntimePhase(phase);
309   }
310 }
311 
AddMethodCallback(MethodCallback * cb)312 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
313   WriterMutexLock mu(Thread::Current(), *callback_lock_);
314   method_callbacks_.push_back(cb);
315 }
316 
RemoveMethodCallback(MethodCallback * cb)317 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
318   WriterMutexLock mu(Thread::Current(), *callback_lock_);
319   Remove(cb, &method_callbacks_);
320 }
321 
RegisterNativeMethod(ArtMethod * method,const void * in_cur_method,void ** new_method)322 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
323                                             const void* in_cur_method,
324                                             /*out*/void** new_method) {
325   void* cur_method = const_cast<void*>(in_cur_method);
326   *new_method = cur_method;
327   for (MethodCallback* cb : COPY(method_callbacks_)) {
328     cb->RegisterNativeMethod(method, cur_method, new_method);
329     if (*new_method != nullptr) {
330       cur_method = *new_method;
331     }
332   }
333 }
334 
AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)335 void RuntimeCallbacks::AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
336   WriterMutexLock mu(Thread::Current(), *callback_lock_);
337   reflective_value_visit_callbacks_.push_back(cb);
338 }
339 
RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback * cb)340 void RuntimeCallbacks::RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
341   WriterMutexLock mu(Thread::Current(), *callback_lock_);
342   Remove(cb, &reflective_value_visit_callbacks_);
343 }
344 
VisitReflectiveTargets(ReflectiveValueVisitor * visitor)345 void RuntimeCallbacks::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) {
346   for (ReflectiveValueVisitCallback* cb : COPY(reflective_value_visit_callbacks_)) {
347     cb->VisitReflectiveTargets(visitor);
348   }
349 }
350 
351 }  // namespace art
352