/*
 * 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 <type_traits>
#include <tuple>

#include "base/mutex-inl.h"
#include "events.h"
#include "jni/jni_internal.h"
#include "nativehelper/scoped_local_ref.h"
#include "runtime-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "ti_breakpoint.h"
#include "ti_thread.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 {

// Helper for ensuring that the dispatch environment is sane. 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.
class ScopedEventDispatchEnvironment final : public art::ValueObject {
 public:
  ScopedEventDispatchEnvironment() : env_(nullptr), throw_(nullptr, nullptr) {
    DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
  }

  explicit ScopedEventDispatchEnvironment(JNIEnv* env)
      : env_(env),
        throw_(env_, env_->ExceptionOccurred()) {
    DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
    // The spec doesn't say how much local data should be there, so we just give 128 which seems
    // likely to be enough for most cases.
    env_->PushLocalFrame(128);
    env_->ExceptionClear();
  }

  ~ScopedEventDispatchEnvironment() {
    if (env_ != nullptr) {
      if (throw_.get() != nullptr && !env_->ExceptionCheck()) {
        // TODO It would be nice to add the overwritten exceptions to the suppressed exceptions list
        // of the newest exception.
        env_->Throw(throw_.get());
      }
      env_->PopLocalFrame(nullptr);
    }
    DCHECK_EQ(art::Thread::Current()->GetState(), art::ThreadState::kNative);
  }

 private:
  JNIEnv* env_;
  ScopedLocalRef<jthrowable> throw_;

  DISALLOW_COPY_AND_ASSIGN(ScopedEventDispatchEnvironment);
};

// 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)                         \
  fn(DdmPublishChunk,         ArtJvmtiEvent::kDdmPublishChunk)

template <ArtJvmtiEvent kEvent>
struct EventFnType {
};

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

FORALL_EVENT_TYPES(EVENT_FN_TYPE)

#undef EVENT_FN_TYPE

#define MAKE_EVENT_HANDLER_FUNC(name, enum_name)                                          \
template<>                                                                                \
struct EventHandlerFunc<enum_name> {                                                      \
  using EventFnType = typename impl::EventFnType<enum_name>::type;                        \
  explicit EventHandlerFunc(ArtJvmTiEnv* env)                                             \
      : env_(env),                                                                        \
        fn_(env_->event_callbacks == nullptr ? nullptr : env_->event_callbacks->name) { } \
                                                                                          \
  template <typename ...Args>                                                             \
  ALWAYS_INLINE                                                                           \
  void ExecuteCallback(JNIEnv* jnienv, Args... args) const {                              \
    if (fn_ != nullptr) {                                                                 \
      ScopedEventDispatchEnvironment sede(jnienv);                                        \
      DoExecute(jnienv, args...);                                                         \
    }                                                                                     \
  }                                                                                       \
                                                                                          \
  template <typename ...Args>                                                             \
  ALWAYS_INLINE                                                                           \
  void ExecuteCallback(Args... args) const {                                              \
    if (fn_ != nullptr) {                                                                 \
      ScopedEventDispatchEnvironment sede;                                                \
      DoExecute(args...);                                                                 \
    }                                                                                     \
  }                                                                                       \
                                                                                          \
 private:                                                                                 \
  template <typename ...Args>                                                             \
  ALWAYS_INLINE                                                                           \
  inline void DoExecute(Args... args) const {                                             \
    static_assert(std::is_same<EventFnType, void(*)(jvmtiEnv*, Args...)>::value,          \
          "Unexpected different type of ExecuteCallback");                                \
    fn_(env_, args...);                                                                   \
  }                                                                                       \
                                                                                          \
 public:                                                                                  \
  ArtJvmTiEnv* env_;                                                                      \
  EventFnType fn_;                                                                        \
};

FORALL_EVENT_TYPES(MAKE_EVENT_HANDLER_FUNC)

#undef MAKE_EVENT_HANDLER_FUNC

#undef FORALL_EVENT_TYPES

}  // namespace impl

template <ArtJvmtiEvent kEvent, typename ...Args>
inline std::vector<impl::EventHandlerFunc<kEvent>> EventHandler::CollectEvents(art::Thread* thread,
                                                                               Args... args) const {
  art::ReaderMutexLock mu(thread, envs_lock_);
  std::vector<impl::EventHandlerFunc<kEvent>> handlers;
  for (ArtJvmTiEnv* env : envs) {
    if (ShouldDispatch<kEvent>(env, thread, args...)) {
      impl::EventHandlerFunc<kEvent> h(env);
      handlers.push_back(h);
    }
  }
  return handlers;
}

// 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.
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 {
  art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
  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);
  std::vector<impl::EventHandlerFunc<kEvent>> handlers =
      CollectEvents<kEvent>(thread,
                            jnienv,
                            class_being_redefined,
                            loader,
                            name,
                            protection_domain,
                            class_data_len,
                            class_data,
                            new_class_data_len,
                            new_class_data);
  ArtJvmTiEnv* last_env = nullptr;
  for (const impl::EventHandlerFunc<kEvent>& event : handlers) {
    jint new_len = 0;
    unsigned char* new_data = nullptr;
    ExecuteCallback<kEvent>(event,
                            jnienv,
                            class_being_redefined,
                            loader,
                            name,
                            protection_domain,
                            current_len,
                            static_cast<const unsigned char*>(current_class_data),
                            &new_len,
                            &new_data);
    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 = event.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 {
  art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
  static_assert(!std::is_same<JNIEnv*,
                              typename std::decay_t<
                                  std::tuple_element_t<0, std::tuple<Args..., nullptr_t>>>>::value,
                "Should be calling DispatchEvent with explicit JNIEnv* argument!");
  DCHECK(thread == nullptr || !thread->IsExceptionPending());
  std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread, args...);
  for (auto event : events) {
    ExecuteCallback<kEvent>(event, args...);
  }
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEvent(art::Thread* thread, JNIEnv* jnienv, Args... args) const {
  art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
  std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread,
                                                                             jnienv,
                                                                             args...);
  for (auto event : events) {
    ExecuteCallback<kEvent>(event, jnienv, args...);
  }
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEventOnEnv(
    ArtJvmTiEnv* env, art::Thread* thread, JNIEnv* jnienv, Args... args) const {
  DCHECK(env != nullptr);
  if (ShouldDispatch<kEvent, JNIEnv*, Args...>(env, thread, jnienv, args...)) {
    art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
    impl::EventHandlerFunc<kEvent> func(env);
    ExecuteCallback<kEvent>(func, jnienv, args...);
  }
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::DispatchEventOnEnv(
    ArtJvmTiEnv* env, art::Thread* thread, Args... args) const {
  static_assert(!std::is_same<JNIEnv*,
                              typename std::decay_t<
                                  std::tuple_element_t<0, std::tuple<Args..., nullptr_t>>>>::value,
                "Should be calling DispatchEventOnEnv with explicit JNIEnv* argument!");
  DCHECK(env != nullptr);
  if (ShouldDispatch<kEvent, Args...>(env, thread, args...)) {
    art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
    impl::EventHandlerFunc<kEvent> func(env);
    ExecuteCallback<kEvent>(func, args...);
  }
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::ExecuteCallback(impl::EventHandlerFunc<kEvent> handler, Args... args) {
  handler.ExecuteCallback(args...);
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline void EventHandler::ExecuteCallback(impl::EventHandlerFunc<kEvent> handler,
                                          JNIEnv* jnienv,
                                          Args... args) {
  handler.ExecuteCallback(jnienv, args...);
}

// Events that need custom logic for if we send the event but are otherwise normal. This includes
// the kBreakpoint, kFramePop, kFieldAccess, and kFieldModification events.

// Need to give custom specializations for Breakpoint since it needs to filter out which particular
// methods/dex_pcs agents get notified on.
template <>
inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kBreakpoint>(
    ArtJvmTiEnv* env,
    art::Thread* thread,
    JNIEnv* jnienv ATTRIBUTE_UNUSED,
    jthread jni_thread ATTRIBUTE_UNUSED,
    jmethodID jmethod,
    jlocation location) const {
  art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
  art::ArtMethod* method = art::jni::DecodeArtMethod(jmethod);
  return ShouldDispatchOnThread<ArtJvmtiEvent::kBreakpoint>(env, thread) &&
      env->breakpoints.find({method, location}) != env->breakpoints.end();
}

template <>
inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFramePop>(
    ArtJvmTiEnv* env,
    art::Thread* thread,
    JNIEnv* jnienv ATTRIBUTE_UNUSED,
    jthread jni_thread ATTRIBUTE_UNUSED,
    jmethodID jmethod ATTRIBUTE_UNUSED,
    jboolean is_exception ATTRIBUTE_UNUSED,
    const art::ShadowFrame* frame) const {
  // Search for the frame. Do this before checking if we need to send the event so that we don't
  // have to deal with use-after-free or the frames being reallocated later.
  art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
  return env->notify_frames.erase(frame) != 0 &&
      !frame->GetSkipMethodExitEvents() &&
      ShouldDispatchOnThread<ArtJvmtiEvent::kFramePop>(env, thread);
}

// 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 bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFieldModification>(
    ArtJvmTiEnv* env,
    art::Thread* thread,
    JNIEnv* jnienv ATTRIBUTE_UNUSED,
    jthread jni_thread ATTRIBUTE_UNUSED,
    jmethodID method ATTRIBUTE_UNUSED,
    jlocation location ATTRIBUTE_UNUSED,
    jclass field_klass ATTRIBUTE_UNUSED,
    jobject object ATTRIBUTE_UNUSED,
    jfieldID field,
    char type_char ATTRIBUTE_UNUSED,
    jvalue val ATTRIBUTE_UNUSED) const {
  art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
  return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldModification>(env, thread) &&
      env->modify_watched_fields.find(
          art::jni::DecodeArtField(field)) != env->modify_watched_fields.end();
}

template <>
inline bool EventHandler::ShouldDispatch<ArtJvmtiEvent::kFieldAccess>(
    ArtJvmTiEnv* env,
    art::Thread* thread,
    JNIEnv* jnienv ATTRIBUTE_UNUSED,
    jthread jni_thread ATTRIBUTE_UNUSED,
    jmethodID method ATTRIBUTE_UNUSED,
    jlocation location ATTRIBUTE_UNUSED,
    jclass field_klass ATTRIBUTE_UNUSED,
    jobject object ATTRIBUTE_UNUSED,
    jfieldID field) const {
  art::ReaderMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
  return ShouldDispatchOnThread<ArtJvmtiEvent::kFieldAccess>(env, thread) &&
      env->access_watched_fields.find(
          art::jni::DecodeArtField(field)) != env->access_watched_fields.end();
}

// Need to give custom specializations for FramePop since it needs to filter out which particular
// agents get the event. This specialization gets an extra argument so we can determine which (if
// any) environments have the frame pop.
// TODO It might be useful to use more template magic to have this only define ShouldDispatch or
// something.
template <>
inline void EventHandler::ExecuteCallback<ArtJvmtiEvent::kFramePop>(
    impl::EventHandlerFunc<ArtJvmtiEvent::kFramePop> event,
    JNIEnv* jnienv,
    jthread jni_thread,
    jmethodID jmethod,
    jboolean is_exception,
    const art::ShadowFrame* frame ATTRIBUTE_UNUSED) {
  ExecuteCallback<ArtJvmtiEvent::kFramePop>(event, jnienv, jni_thread, jmethod, is_exception);
}

struct ScopedDisablePopFrame {
 public:
  explicit ScopedDisablePopFrame(art::Thread* thread) : thread_(thread) {
    art::Locks::mutator_lock_->AssertSharedHeld(thread_);
    art::MutexLock mu(thread_, *art::Locks::thread_list_lock_);
    JvmtiGlobalTLSData* data = ThreadUtil::GetOrCreateGlobalTLSData(thread_);
    current_top_frame_ = art::StackVisitor::ComputeNumFrames(
        thread_, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames);
    old_disable_frame_pop_depth_ = data->disable_pop_frame_depth;
    data->disable_pop_frame_depth = current_top_frame_;
    DCHECK(old_disable_frame_pop_depth_ == JvmtiGlobalTLSData::kNoDisallowedPopFrame ||
           current_top_frame_ > old_disable_frame_pop_depth_)
        << "old: " << old_disable_frame_pop_depth_ << " current: " << current_top_frame_;
  }

  ~ScopedDisablePopFrame() {
    art::Locks::mutator_lock_->AssertSharedHeld(thread_);
    art::MutexLock mu(thread_, *art::Locks::thread_list_lock_);
    JvmtiGlobalTLSData* data = ThreadUtil::GetGlobalTLSData(thread_);
    DCHECK_EQ(data->disable_pop_frame_depth, current_top_frame_);
    data->disable_pop_frame_depth = old_disable_frame_pop_depth_;
  }

 private:
  art::Thread* thread_;
  size_t current_top_frame_;
  size_t old_disable_frame_pop_depth_;
};
// We want to prevent the use of PopFrame when reporting either of these events.
template <ArtJvmtiEvent kEvent>
inline void EventHandler::DispatchClassLoadOrPrepareEvent(art::Thread* thread,
                                                          JNIEnv* jnienv,
                                                          jthread jni_thread,
                                                          jclass klass) const {
  ScopedDisablePopFrame sdpf(thread);
  art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
  std::vector<impl::EventHandlerFunc<kEvent>> events = CollectEvents<kEvent>(thread,
                                                                             jnienv,
                                                                             jni_thread,
                                                                             klass);

  for (auto event : events) {
    ExecuteCallback<kEvent>(event, jnienv, jni_thread, klass);
  }
}

template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassLoad>(art::Thread* thread,
                                                                   JNIEnv* jnienv,
                                                                   jthread jni_thread,
                                                                   jclass klass) const {
  DispatchClassLoadOrPrepareEvent<ArtJvmtiEvent::kClassLoad>(thread, jnienv, jni_thread, klass);
}
template <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kClassPrepare>(art::Thread* thread,
                                                                      JNIEnv* jnienv,
                                                                      jthread jni_thread,
                                                                      jclass klass) const {
  DispatchClassLoadOrPrepareEvent<ArtJvmtiEvent::kClassPrepare>(thread, jnienv, jni_thread, klass);
}

// 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 {
  art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
  std::vector<impl::EventHandlerFunc<ArtJvmtiEvent::kNativeMethodBind>> events =
      CollectEvents<ArtJvmtiEvent::kNativeMethodBind>(thread,
                                                      jnienv,
                                                      jni_thread,
                                                      method,
                                                      cur_method,
                                                      new_method);
  *new_method = cur_method;
  for (auto event : events) {
    *new_method = cur_method;
    ExecuteCallback<ArtJvmtiEvent::kNativeMethodBind>(event,
                                                      jnienv,
                                                      jni_thread,
                                                      method,
                                                      cur_method,
                                                      new_method);
    if (*new_method != nullptr) {
      cur_method = *new_method;
    }
  }
  *new_method = cur_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::ShouldDispatchOnThread(ArtJvmTiEnv* env, art::Thread* thread) const {
  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;
}

template <ArtJvmtiEvent kEvent, typename ...Args>
inline bool EventHandler::ShouldDispatch(ArtJvmTiEnv* env,
                                         art::Thread* thread,
                                         Args... args ATTRIBUTE_UNUSED) const {
  static_assert(std::is_same<typename impl::EventFnType<kEvent>::type,
                             void(*)(jvmtiEnv*, Args...)>::value,
                "Unexpected different type of shouldDispatch");

  return ShouldDispatchOnThread<kEvent>(env, thread);
}

inline void EventHandler::RecalculateGlobalEventMask(ArtJvmtiEvent event) {
  art::WriterMutexLock mu(art::Thread::Current(), envs_lock_);
  RecalculateGlobalEventMaskLocked(event);
}

inline void EventHandler::RecalculateGlobalEventMaskLocked(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_generate_breakpoint_events == 1 ||
      caps.can_pop_frame == 1 ||
      caps.can_force_early_return == 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();
    }
    if (caps.can_generate_breakpoint_events == 1) {
      HandleBreakpointEventsChanged(added);
    }
    if ((caps.can_pop_frame == 1 || caps.can_force_early_return == 1) && added) {
      // TODO We should keep track of how many of these have been enabled and remove it if there are
      // no more possible users. This isn't expected to be too common.
      art::Runtime::Current()->SetNonStandardExitsEnabled();
    }
  }
}

}  // namespace openjdkjvmti

#endif  // ART_OPENJDKJVMTI_EVENTS_INL_H_
