/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "runtime_callbacks.h"

#include <algorithm>

#include "art_method.h"
#include "base/macros.h"
#include "base/mutex-inl.h"
#include "class_linker.h"
#include "monitor.h"
#include "thread-current-inl.h"

namespace art {

RuntimeCallbacks::RuntimeCallbacks()
    : callback_lock_(new ReaderWriterMutex("Runtime callbacks lock",
                                           LockLevel::kGenericBottomLock)) {}

// We don't want to be holding any locks when the actual event is called so we use this to define a
// helper that gets a copy of the current event list and returns it.
#define COPY(T)                                                   \
  ([this]() -> decltype(this->T) {                                \
    ReaderMutexLock mu(Thread::Current(), *this->callback_lock_); \
    return std::vector<decltype(this->T)::value_type>(this->T);   \
  })()

template <typename T>
ALWAYS_INLINE
static inline void Remove(T* cb, std::vector<T*>* data) {
  auto it = std::find(data->begin(), data->end(), cb);
  if (it != data->end()) {
    data->erase(it);
  }
}

void RuntimeCallbacks::AddDdmCallback(DdmCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  ddm_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveDdmCallback(DdmCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &ddm_callbacks_);
}

void RuntimeCallbacks::DdmPublishChunk(uint32_t type, const ArrayRef<const uint8_t>& data) {
  for (DdmCallback* cb : COPY(ddm_callbacks_)) {
    cb->DdmPublishChunk(type, data);
  }
}

void RuntimeCallbacks::AddDebuggerControlCallback(DebuggerControlCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  debugger_control_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveDebuggerControlCallback(DebuggerControlCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &debugger_control_callbacks_);
}

bool RuntimeCallbacks::IsDebuggerConfigured() {
  for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
    if (cb->IsDebuggerConfigured()) {
      return true;
    }
  }
  return false;
}

void RuntimeCallbacks::StartDebugger() {
  for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
    cb->StartDebugger();
  }
}

void RuntimeCallbacks::StopDebugger() {
  for (DebuggerControlCallback* cb : COPY(debugger_control_callbacks_)) {
    cb->StopDebugger();
  }
}

void RuntimeCallbacks::AddMethodInspectionCallback(MethodInspectionCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  method_inspection_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveMethodInspectionCallback(MethodInspectionCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &method_inspection_callbacks_);
}

bool RuntimeCallbacks::HaveLocalsChanged() {
  for (MethodInspectionCallback* cb : COPY(method_inspection_callbacks_)) {
    if (cb->HaveLocalsChanged()) {
      return true;
    }
  }
  return false;
}

void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  thread_callbacks_.push_back(cb);
}

void RuntimeCallbacks::MonitorContendedLocking(Monitor* m) {
  for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
    cb->MonitorContendedLocking(m);
  }
}

void RuntimeCallbacks::MonitorContendedLocked(Monitor* m) {
  for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
    cb->MonitorContendedLocked(m);
  }
}

void RuntimeCallbacks::ObjectWaitStart(Handle<mirror::Object> m, int64_t timeout) {
  for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
    cb->ObjectWaitStart(m, timeout);
  }
}

void RuntimeCallbacks::MonitorWaitFinished(Monitor* m, bool timeout) {
  for (MonitorCallback* cb : COPY(monitor_callbacks_)) {
    cb->MonitorWaitFinished(m, timeout);
  }
}

void RuntimeCallbacks::AddMonitorCallback(MonitorCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  monitor_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveMonitorCallback(MonitorCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &monitor_callbacks_);
}

void RuntimeCallbacks::ThreadParkStart(bool is_absolute, int64_t timeout) {
  for (ParkCallback * cb : COPY(park_callbacks_)) {
    cb->ThreadParkStart(is_absolute, timeout);
  }
}

void RuntimeCallbacks::ThreadParkFinished(bool timeout) {
  for (ParkCallback * cb : COPY(park_callbacks_)) {
    cb->ThreadParkFinished(timeout);
  }
}

void RuntimeCallbacks::AddParkCallback(ParkCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  park_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveParkCallback(ParkCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &park_callbacks_);
}

void RuntimeCallbacks::RemoveThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &thread_callbacks_);
}

void RuntimeCallbacks::ThreadStart(Thread* self) {
  for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
    cb->ThreadStart(self);
  }
}

void RuntimeCallbacks::ThreadDeath(Thread* self) {
  for (ThreadLifecycleCallback* cb : COPY(thread_callbacks_)) {
    cb->ThreadDeath(self);
  }
}

void RuntimeCallbacks::AddClassLoadCallback(ClassLoadCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  class_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveClassLoadCallback(ClassLoadCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &class_callbacks_);
}

void RuntimeCallbacks::ClassLoad(Handle<mirror::Class> klass) {
  for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
    cb->ClassLoad(klass);
  }
}

void RuntimeCallbacks::EndDefineClass() {
  for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
    cb->EndDefineClass();
  }
}

void RuntimeCallbacks::BeginDefineClass() {
  for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
    cb->BeginDefineClass();
  }
}


void RuntimeCallbacks::ClassPreDefine(const char* descriptor,
                                      Handle<mirror::Class> temp_class,
                                      Handle<mirror::ClassLoader> loader,
                                      const DexFile& initial_dex_file,
                                      const dex::ClassDef& initial_class_def,
                                      /*out*/DexFile const** final_dex_file,
                                      /*out*/dex::ClassDef const** final_class_def) {
  DexFile const* current_dex_file = &initial_dex_file;
  dex::ClassDef const* current_class_def = &initial_class_def;
  for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
    DexFile const* new_dex_file = nullptr;
    dex::ClassDef const* new_class_def = nullptr;
    cb->ClassPreDefine(descriptor,
                       temp_class,
                       loader,
                       *current_dex_file,
                       *current_class_def,
                       &new_dex_file,
                       &new_class_def);
    if ((new_dex_file != nullptr && new_dex_file != current_dex_file) ||
        (new_class_def != nullptr && new_class_def != current_class_def)) {
      DCHECK(new_dex_file != nullptr && new_class_def != nullptr);
      current_dex_file = new_dex_file;
      current_class_def = new_class_def;
    }
  }
  *final_dex_file = current_dex_file;
  *final_class_def = current_class_def;
}

void RuntimeCallbacks::ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass) {
  for (ClassLoadCallback* cb : COPY(class_callbacks_)) {
    cb->ClassPrepare(temp_klass, klass);
  }
}

void RuntimeCallbacks::AddRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  sigquit_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveRuntimeSigQuitCallback(RuntimeSigQuitCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &sigquit_callbacks_);
}

void RuntimeCallbacks::SigQuit() {
  for (RuntimeSigQuitCallback* cb : COPY(sigquit_callbacks_)) {
    cb->SigQuit();
  }
}

void RuntimeCallbacks::AddRuntimePhaseCallback(RuntimePhaseCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  phase_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveRuntimePhaseCallback(RuntimePhaseCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &phase_callbacks_);
}

void RuntimeCallbacks::NextRuntimePhase(RuntimePhaseCallback::RuntimePhase phase) {
  for (RuntimePhaseCallback* cb : COPY(phase_callbacks_)) {
    cb->NextRuntimePhase(phase);
  }
}

void RuntimeCallbacks::AddMethodCallback(MethodCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  method_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveMethodCallback(MethodCallback* cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &method_callbacks_);
}

void RuntimeCallbacks::RegisterNativeMethod(ArtMethod* method,
                                            const void* in_cur_method,
                                            /*out*/void** new_method) {
  void* cur_method = const_cast<void*>(in_cur_method);
  *new_method = cur_method;
  for (MethodCallback* cb : COPY(method_callbacks_)) {
    cb->RegisterNativeMethod(method, cur_method, new_method);
    if (*new_method != nullptr) {
      cur_method = *new_method;
    }
  }
}

void RuntimeCallbacks::AddReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  reflective_value_visit_callbacks_.push_back(cb);
}

void RuntimeCallbacks::RemoveReflectiveValueVisitCallback(ReflectiveValueVisitCallback *cb) {
  WriterMutexLock mu(Thread::Current(), *callback_lock_);
  Remove(cb, &reflective_value_visit_callbacks_);
}

void RuntimeCallbacks::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) {
  for (ReflectiveValueVisitCallback* cb : COPY(reflective_value_visit_callbacks_)) {
    cb->VisitReflectiveTargets(visitor);
  }
}

}  // namespace art
