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 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 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 51 void RuntimeCallbacks::AddDdmCallback(DdmCallback* cb) { 52 WriterMutexLock mu(Thread::Current(), *callback_lock_); 53 ddm_callbacks_.push_back(cb); 54 } 55 56 void RuntimeCallbacks::RemoveDdmCallback(DdmCallback* cb) { 57 WriterMutexLock mu(Thread::Current(), *callback_lock_); 58 Remove(cb, &ddm_callbacks_); 59 } 60 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 67 void RuntimeCallbacks::AddDebuggerControlCallback(DebuggerControlCallback* cb) { 68 WriterMutexLock mu(Thread::Current(), *callback_lock_); 69 debugger_control_callbacks_.push_back(cb); 70 } 71 72 void RuntimeCallbacks::RemoveDebuggerControlCallback(DebuggerControlCallback* cb) { 73 WriterMutexLock mu(Thread::Current(), *callback_lock_); 74 Remove(cb, &debugger_control_callbacks_); 75 } 76 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 86 void RuntimeCallbacks::StartDebugger() { 87 for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) { 88 cb->StartDebugger(); 89 } 90 } 91 92 void RuntimeCallbacks::StopDebugger() { 93 for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) { 94 cb->StopDebugger(); 95 } 96 } 97 98 void RuntimeCallbacks::AddMethodInspectionCallback(MethodInspectionCallback* cb) { 99 WriterMutexLock mu(Thread::Current(), *callback_lock_); 100 method_inspection_callbacks_.push_back(cb); 101 } 102 103 void RuntimeCallbacks::RemoveMethodInspectionCallback(MethodInspectionCallback* cb) { 104 WriterMutexLock mu(Thread::Current(), *callback_lock_); 105 Remove(cb, &method_inspection_callbacks_); 106 } 107 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 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 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 137 void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) { 138 WriterMutexLock mu(Thread::Current(), *callback_lock_); 139 thread_callbacks_.push_back(cb); 140 } 141 142 void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) { 143 for (MonitorCallback* cb : COPY(monitor_callbacks_)) { 144 cb->MonitorContendedLocking(m); 145 } 146 } 147 148 void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) { 149 for (MonitorCallback* cb : COPY(monitor_callbacks_)) { 150 cb->MonitorContendedLocked(m); 151 } 152 } 153 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 160 void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) { 161 for (MonitorCallback* cb : COPY(monitor_callbacks_)) { 162 cb->MonitorWaitFinished(m, timeout); 163 } 164 } 165 166 void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) { 167 WriterMutexLock mu(Thread::Current(), *callback_lock_); 168 monitor_callbacks_.push_back(cb); 169 } 170 171 void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) { 172 WriterMutexLock mu(Thread::Current(), *callback_lock_); 173 Remove(cb, &monitor_callbacks_); 174 } 175 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 182 void RuntimeCallbacks::ThreadParkFinished(bool timeout) { 183 for (ParkCallback * cb : COPY(park_callbacks_)) { 184 cb->ThreadParkFinished(timeout); 185 } 186 } 187 188 void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) { 189 WriterMutexLock mu(Thread::Current(), *callback_lock_); 190 park_callbacks_.push_back(cb); 191 } 192 193 void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) { 194 WriterMutexLock mu(Thread::Current(), *callback_lock_); 195 Remove(cb, &park_callbacks_); 196 } 197 198 void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) { 199 WriterMutexLock mu(Thread::Current(), *callback_lock_); 200 Remove(cb, &thread_callbacks_); 201 } 202 203 void RuntimeCallbacks::ThreadStart(Thread* self) { 204 for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) { 205 cb->ThreadStart(self); 206 } 207 } 208 209 void RuntimeCallbacks::ThreadDeath(Thread* self) { 210 for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) { 211 cb->ThreadDeath(self); 212 } 213 } 214 215 void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) { 216 WriterMutexLock mu(Thread::Current(), *callback_lock_); 217 class_callbacks_.push_back(cb); 218 } 219 220 void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) { 221 WriterMutexLock mu(Thread::Current(), *callback_lock_); 222 Remove(cb, &class_callbacks_); 223 } 224 225 void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) { 226 for (ClassLoadCallback* cb : COPY(class_callbacks_)) { 227 cb->ClassLoad(klass); 228 } 229 } 230 231 void RuntimeCallbacks::ClassPreDefine(const char* descriptor, 232 Handle<mirror::Class> temp_class, 233 Handle<mirror::ClassLoader> loader, 234 const DexFile& initial_dex_file, 235 const dex::ClassDef& initial_class_def, 236 /*out*/DexFile const** final_dex_file, 237 /*out*/dex::ClassDef const** final_class_def) { 238 DexFile const* current_dex_file = &initial_dex_file; 239 dex::ClassDef const* current_class_def = &initial_class_def; 240 for (ClassLoadCallback* cb : COPY(class_callbacks_)) { 241 DexFile const* new_dex_file = nullptr; 242 dex::ClassDef const* new_class_def = nullptr; 243 cb->ClassPreDefine(descriptor, 244 temp_class, 245 loader, 246 *current_dex_file, 247 *current_class_def, 248 &new_dex_file, 249 &new_class_def); 250 if ((new_dex_file != nullptr && new_dex_file != current_dex_file) || 251 (new_class_def != nullptr && new_class_def != current_class_def)) { 252 DCHECK(new_dex_file != nullptr && new_class_def != nullptr); 253 current_dex_file = new_dex_file; 254 current_class_def = new_class_def; 255 } 256 } 257 *final_dex_file = current_dex_file; 258 *final_class_def = current_class_def; 259 } 260 261 void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) { 262 for (ClassLoadCallback* cb : COPY(class_callbacks_)) { 263 cb->ClassPrepare(temp_klass, klass); 264 } 265 } 266 267 void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) { 268 WriterMutexLock mu(Thread::Current(), *callback_lock_); 269 sigquit_callbacks_.push_back(cb); 270 } 271 272 void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) { 273 WriterMutexLock mu(Thread::Current(), *callback_lock_); 274 Remove(cb, &sigquit_callbacks_); 275 } 276 277 void RuntimeCallbacks::SigQuit() { 278 for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) { 279 cb->SigQuit(); 280 } 281 } 282 283 void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) { 284 WriterMutexLock mu(Thread::Current(), *callback_lock_); 285 phase_callbacks_.push_back(cb); 286 } 287 288 void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) { 289 WriterMutexLock mu(Thread::Current(), *callback_lock_); 290 Remove(cb, &phase_callbacks_); 291 } 292 293 void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) { 294 for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) { 295 cb->NextRuntimePhase(phase); 296 } 297 } 298 299 void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) { 300 WriterMutexLock mu(Thread::Current(), *callback_lock_); 301 method_callbacks_.push_back(cb); 302 } 303 304 void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) { 305 WriterMutexLock mu(Thread::Current(), *callback_lock_); 306 Remove(cb, &method_callbacks_); 307 } 308 309 void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method, 310 const void* in_cur_method, 311 /*out*/void** new_method) { 312 void* cur_method = const_cast<void*>(in_cur_method); 313 *new_method = cur_method; 314 for (MethodCallback* cb : COPY(method_callbacks_)) { 315 cb->RegisterNativeMethod(method, cur_method, new_method); 316 if (*new_method != nullptr) { 317 cur_method = *new_method; 318 } 319 } 320 } 321 322 } // namespace art 323