/*
 * Copyright (C) 2016 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.
 */

#ifndef ART_OPENJDKJVMTI_EVENTS_INL_H_
#define ART_OPENJDKJVMTI_EVENTS_INL_H_

#include <array>

#include "events.h"
#include "jni_internal.h"
#include "nativehelper/ScopedLocalRef.h"
#include "ti_breakpoint.h"

#include "art_jvmti.h"

namespace openjdkjvmti {

static inline ArtJvmtiEvent GetArtJvmtiEvent(ArtJvmTiEnv* env, jvmtiEvent e) {
  if (UNLIKELY(e == JVMTI_EVENT_CLASS_FILE_LOAD_HOOK)) {
    if (env->capabilities.can_retransform_classes) {
      return ArtJvmtiEvent::kClassFileLoadHookRetransformable;
    } else {
      return ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
    }
  } else {
    return static_cast<ArtJvmtiEvent>(e);
  }
}

namespace impl {

// Infrastructure to achieve type safety for event dispatch.

#define FORALL_EVENT_TYPES(fn)                                                       \
  fn(VMInit,                  ArtJvmtiEvent::kVmInit)                                \
  fn(VMDeath,                 ArtJvmtiEvent::kVmDeath)                               \
  fn(ThreadStart,             ArtJvmtiEvent::kThreadStart)                           \
  fn(ThreadEnd,               ArtJvmtiEvent::kThreadEnd)                             \
  fn(ClassFileLoadHook,       ArtJvmtiEvent::kClassFileLoadHookRetransformable)      \
  fn(ClassFileLoadHook,       ArtJvmtiEvent::kClassFileLoadHookNonRetransformable)   \
  fn(ClassLoad,               ArtJvmtiEvent::kClassLoad)                             \
  fn(ClassPrepare,            ArtJvmtiEvent::kClassPrepare)                          \
  fn(VMStart,                 ArtJvmtiEvent::kVmStart)                               \
  fn(Exception,               ArtJvmtiEvent::kException)                             \
  fn(ExceptionCatch,          ArtJvmtiEvent::kExceptionCatch)                        \
  fn(SingleStep,              ArtJvmtiEvent::kSingleStep)                            \
  fn(FramePop,                ArtJvmtiEvent::kFramePop)                              \
  fn(Breakpoint,              ArtJvmtiEvent::kBreakpoint)                            \
  fn(FieldAccess,             ArtJvmtiEvent::kFieldAccess)                           \
  fn(FieldModification,       ArtJvmtiEvent::kFieldModification)                     \
  fn(MethodEntry,             ArtJvmtiEvent::kMethodEntry)                           \
  fn(MethodExit,              ArtJvmtiEvent::kMethodExit)                            \
  fn(NativeMethodBind,        ArtJvmtiEvent::kNativeMethodBind)                      \
  fn(CompiledMethodLoad,      ArtJvmtiEvent::kCompiledMethodLoad)                    \
  fn(CompiledMethodUnload,    ArtJvmtiEvent::kCompiledMethodUnload)                  \
  fn(DynamicCodeGenerated,    ArtJvmtiEvent::kDynamicCodeGenerated)                  \
  fn(DataDumpRequest,         ArtJvmtiEvent::kDataDumpRequest)                       \
  fn(MonitorWait,             ArtJvmtiEvent::kMonitorWait)                           \
  fn(MonitorWaited,           ArtJvmtiEvent::kMonitorWaited)                         \
  fn(MonitorContendedEnter,   ArtJvmtiEvent::kMonitorContendedEnter)                 \
  fn(MonitorContendedEntered, ArtJvmtiEvent::kMonitorContendedEntered)               \
  fn(ResourceExhausted,       ArtJvmtiEvent::kResourceExhausted)                     \
  fn(GarbageCollectionStart,  ArtJvmtiEvent::kGarbageCollectionStart)                \
  fn(GarbageCollectionFinish, ArtJvmtiEvent::kGarbageCollectionFinish)               \
  fn(ObjectFree,              ArtJvmtiEvent::kObjectFree)                            \
  fn(VMObjectAlloc,           ArtJvmtiEvent::kVmObjectAlloc)

template <ArtJvmtiEvent kEvent>
struct EventFnType {
};

#define EVENT_FN_TYPE(name, enum_name)               \
template <>                                          \
struct EventFnType<enum_name> {                      \
  using type = decltype(jvmtiEventCallbacks().name); \
};

FORALL_EVENT_TYPES(EVENT_FN_TYPE)

#undef EVENT_FN_TYPE

template <ArtJvmtiEvent kEvent>
ALWAYS_INLINE inline typename EventFnType<kEvent>::type GetCallback(ArtJvmTiEnv* env);

#define GET_CALLBACK(name, enum_name)                                     \
template <>                                                               \
ALWAYS_INLINE inline EventFnType<enum_name>::type GetCallback<enum_name>( \
    ArtJvmTiEnv* env) {                                                   \
  if (env->event_callbacks == nullptr) {                                  \
    return nullptr;                                                       \
  }                                                                       \
  return env->event_callbacks->name;                                      \
}

FORALL_EVENT_TYPES(GET_CALLBACK)

#undef GET_CALLBACK

#undef FORALL_EVENT_TYPES

}  // namespace impl

// C++ does not allow partial template function specialization. The dispatch for our separated
// ClassFileLoadHook event types is the same, so use this helper for code deduplication.
// TODO Locking of some type!
template <ArtJvmtiEvent kEvent>
inline void EventHandler::DispatchClassFileLoadHookEvent(art::Thread* thread,
                                                         JNIEnv* jnienv,
                                                         jclass class_being_redefined,
                                                         jobject loader,
                                                         const char* name,
                                                         jobject protection_domain,
                                                         jint class_data_len,
                                                         const unsigned char* class_data,
                                                         jint* new_class_data_len,
                                                         unsigned char** new_class_data) const {
  static_assert(kEvent == ArtJvmtiEvent::kClassFileLoadHookRetransformable ||
                kEvent == ArtJvmtiEvent::kClassFileLoadHookNonRetransformable, "Unsupported event");
  DCHECK(*new_class_data == nullptr);
  jint current_len = class_data_len;
  unsigned char* current_class_data = const_cast<unsigned char*>(class_data);
  ArtJvmTiEnv* last_env = nullptr;
  for (ArtJvmTiEnv* env : envs) {
    if (env == nullptr) {
      continue;
    }
    if (ShouldDispatch<kEvent>(env, thread)) {
      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
      jnienv->ExceptionClear();
      jint new_len = 0;
      unsigned char* new_data = nullptr;
      auto callback = impl::GetCallback<kEvent>(env);
      callback(env,
               jnienv,
               class_being_redefined,
               loader,
               name,
               protection_domain,
               current_len,
               current_class_data,
               &new_len,
               &new_data);
      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
        jnienv->Throw(thr.get());
      }
      if (new_data != nullptr && new_data != current_class_data) {
        // Destroy the data the last transformer made. We skip this if the previous state was the
        // initial one since we don't know here which jvmtiEnv allocated it.
        // NB Currently this doesn't matter since all allocations just go to malloc but in the
        // future we might have jvmtiEnv's keep track of their allocations for leak-checking.
        if (last_env != nullptr) {
          last_env->Deallocate(current_class_data);
        }
        last_env = env;
        current_class_data = new_data;
        current_len = new_len;
      }
    }
  }
  if (last_env != nullptr) {
    *new_class_data_len = current_len;
    *new_class_data = current_class_data;
  }
}

// Our goal for DispatchEvent: Do not allow implicit type conversion. Types of ...args must match
// exactly the argument types of the corresponding Jvmti kEvent function pointer.

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEvent(art::Thread* thread, Args... args) const {
  for (ArtJvmTiEnv* env : envs) {
    if (env != nullptr) {
      DispatchEvent<kEvent, Args...>(env, thread, args...);
    }
  }
}

// Events with JNIEnvs need to stash pending exceptions since they can cause new ones to be thrown.
// In accordance with the JVMTI specification we allow exceptions originating from events to
// overwrite the current exception, including exceptions originating from earlier events.
// TODO It would be nice to add the overwritten exceptions to the suppressed exceptions list of the
// newest exception.
template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const {
  for (ArtJvmTiEnv* env : envs) {
    if (env != nullptr) {
      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
      jnienv->ExceptionClear();
      DispatchEvent<kEvent, JNIEnv*, Args...>(env, thread, jnienv, args...);
      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
        jnienv->Throw(thr.get());
      }
    }
  }
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEvent(ArtJvmTiEnv* env, art::Thread* thread, Args... args) const {
  using FnType = void(jvmtiEnv*, Args...);
  if (ShouldDispatch<kEvent>(env, thread)) {
    FnType* callback = impl::GetCallback<kEvent>(env);
    if (callback != nullptr) {
      (*callback)(env, args...);
    }
  }
}

// Need to give custom specializations for Breakpoint since it needs to filter out which particular
// methods/dex_pcs agents get notified on.
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kBreakpoint>(art::Thread* thread,
                                                                    JNIEnv* jnienv,
                                                                    jthread jni_thread,
                                                                    jmethodID jmethod,
                                                                    jlocation location) const {
  art::ArtMethod* method = art::jni::DecodeArtMethod(jmethod);
  for (ArtJvmTiEnv* env : envs) {
    // Search for a breakpoint on this particular method and location.
    if (env != nullptr &&
        ShouldDispatch<ArtJvmtiEvent::kBreakpoint>(env, thread) &&
        env->breakpoints.find({method, location}) != env->breakpoints.end()) {
      // We temporarily clear any pending exceptions so the event can call back into java code.
      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
      jnienv->ExceptionClear();
      auto callback = impl::GetCallback<ArtJvmtiEvent::kBreakpoint>(env);
      (*callback)(env, jnienv, jni_thread, jmethod, location);
      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
        jnienv->Throw(thr.get());
      }
    }
  }
}

// Need to give custom specializations for FieldAccess and FieldModification since they need to
// filter out which particular fields agents want to get notified on.
// TODO The spec allows us to do shortcuts like only allow one agent to ever set these watches. This
// could make the system more performant.
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kFieldModification>(art::Thread* thread,
                                                                           JNIEnv* jnienv,
                                                                           jthread jni_thread,
                                                                           jmethodID method,
                                                                           jlocation location,
                                                                           jclass field_klass,
                                                                           jobject object,
                                                                           jfieldID field,
                                                                           char type_char,
                                                                           jvalue val) const {
  for (ArtJvmTiEnv* env : envs) {
    if (env != nullptr &&
        ShouldDispatch<ArtJvmtiEvent::kFieldModification>(env, thread) &&
        env->modify_watched_fields.find(
            art::jni::DecodeArtField(field)) != env->modify_watched_fields.end()) {
      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
      jnienv->ExceptionClear();
      auto callback = impl::GetCallback<ArtJvmtiEvent::kFieldModification>(env);
      (*callback)(env,
                  jnienv,
                  jni_thread,
                  method,
                  location,
                  field_klass,
                  object,
                  field,
                  type_char,
                  val);
      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
        jnienv->Throw(thr.get());
      }
    }
  }
}

template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kFieldAccess>(art::Thread* thread,
                                                                     JNIEnv* jnienv,
                                                                     jthread jni_thread,
                                                                     jmethodID method,
                                                                     jlocation location,
                                                                     jclass field_klass,
                                                                     jobject object,
                                                                     jfieldID field) const {
  for (ArtJvmTiEnv* env : envs) {
    if (env != nullptr &&
        ShouldDispatch<ArtJvmtiEvent::kFieldAccess>(env, thread) &&
        env->access_watched_fields.find(
            art::jni::DecodeArtField(field)) != env->access_watched_fields.end()) {
      ScopedLocalRef<jthrowable> thr(jnienv, jnienv->ExceptionOccurred());
      jnienv->ExceptionClear();
      auto callback = impl::GetCallback<ArtJvmtiEvent::kFieldAccess>(env);
      (*callback)(env, jnienv, jni_thread, method, location, field_klass, object, field);
      if (thr.get() != nullptr && !jnienv->ExceptionCheck()) {
        jnienv->Throw(thr.get());
      }
    }
  }
}

// Need to give a custom specialization for NativeMethodBind since it has to deal with an out
// variable.
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>(art::Thread* thread,
                                                                          JNIEnv* jnienv,
                                                                          jthread jni_thread,
                                                                          jmethodID method,
                                                                          void* cur_method,
                                                                          void** new_method) const {
  *new_method = cur_method;
  for (ArtJvmTiEnv* env : envs) {
    if (env != nullptr && ShouldDispatch<ArtJvmtiEvent::kNativeMethodBind>(env, thread)) {
      auto callback = impl::GetCallback<ArtJvmtiEvent::kNativeMethodBind>(env);
      (*callback)(env, jnienv, jni_thread, method, cur_method, new_method);
      if (*new_method != nullptr) {
        cur_method = *new_method;
      }
    }
  }
}

// C++ does not allow partial template function specialization. The dispatch for our separated
// ClassFileLoadHook event types is the same, and in the DispatchClassFileLoadHookEvent helper.
// The following two DispatchEvent specializations dispatch to it.
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
    art::Thread* thread,
    JNIEnv* jnienv,
    jclass class_being_redefined,
    jobject loader,
    const char* name,
    jobject protection_domain,
    jint class_data_len,
    const unsigned char* class_data,
    jint* new_class_data_len,
    unsigned char** new_class_data) const {
  return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookRetransformable>(
      thread,
      jnienv,
      class_being_redefined,
      loader,
      name,
      protection_domain,
      class_data_len,
      class_data,
      new_class_data_len,
      new_class_data);
}
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
    art::Thread* thread,
    JNIEnv* jnienv,
    jclass class_being_redefined,
    jobject loader,
    const char* name,
    jobject protection_domain,
    jint class_data_len,
    const unsigned char* class_data,
    jint* new_class_data_len,
    unsigned char** new_class_data) const {
  return DispatchClassFileLoadHookEvent<ArtJvmtiEvent::kClassFileLoadHookNonRetransformable>(
      thread,
      jnienv,
      class_being_redefined,
      loader,
      name,
      protection_domain,
      class_data_len,
      class_data,
      new_class_data_len,
      new_class_data);
}

template <ArtJvmtiEvent kEvent>
inline bool EventHandler::ShouldDispatch(ArtJvmTiEnv* env,
                                         art::Thread* thread) {
  bool dispatch = env->event_masks.global_event_mask.Test(kEvent);

  if (!dispatch && thread != nullptr && env->event_masks.unioned_thread_event_mask.Test(kEvent)) {
    EventMask* mask = env->event_masks.GetEventMaskOrNull(thread);
    dispatch = mask != nullptr && mask->Test(kEvent);
  }
  return dispatch;
}

inline void EventHandler::RecalculateGlobalEventMask(ArtJvmtiEvent event) {
  bool union_value = false;
  for (const ArtJvmTiEnv* stored_env : envs) {
    if (stored_env == nullptr) {
      continue;
    }
    union_value |= stored_env->event_masks.global_event_mask.Test(event);
    union_value |= stored_env->event_masks.unioned_thread_event_mask.Test(event);
    if (union_value) {
      break;
    }
  }
  global_mask.Set(event, union_value);
}

inline bool EventHandler::NeedsEventUpdate(ArtJvmTiEnv* env,
                                           const jvmtiCapabilities& caps,
                                           bool added) {
  ArtJvmtiEvent event = added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
                              : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
  return (added && caps.can_access_local_variables == 1) ||
      (caps.can_retransform_classes == 1 &&
       IsEventEnabledAnywhere(event) &&
       env->event_masks.IsEnabledAnywhere(event));
}

inline void EventHandler::HandleChangedCapabilities(ArtJvmTiEnv* env,
                                                    const jvmtiCapabilities& caps,
                                                    bool added) {
  if (UNLIKELY(NeedsEventUpdate(env, caps, added))) {
    env->event_masks.HandleChangedCapabilities(caps, added);
    if (caps.can_retransform_classes == 1) {
      RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookRetransformable);
      RecalculateGlobalEventMask(ArtJvmtiEvent::kClassFileLoadHookNonRetransformable);
    }
    if (added && caps.can_access_local_variables == 1) {
      HandleLocalAccessCapabilityAdded();
    }
  }
}

}  // namespace openjdkjvmti

#endif  // ART_OPENJDKJVMTI_EVENTS_INL_H_
