Home | History | Annotate | Download | only in runtime
      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