/*
 * 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 suitably provisioned. 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)                       \
  fn(ObsoleteObjectCreated,     ArtJvmtiEvent::kObsoleteObjectCreated)                 \
  fn(StructuralDexFileLoadHook, ArtJvmtiEvent::kStructuralDexFileLoadHook)

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 ||
                kEvent == ArtJvmtiEvent::kStructuralDexFileLoadHook, "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 <>
inline void EventHandler::DispatchEventOnEnv<ArtJvmtiEvent::kObsoleteObjectCreated>(
    ArtJvmTiEnv* env, art::Thread* thread, jlong* obsolete_tag, jlong* new_tag) const {
  static constexpr ArtJvmtiEvent kEvent = ArtJvmtiEvent::kObsoleteObjectCreated;
  DCHECK(env != nullptr);
  if (ShouldDispatch<kEvent>(env, thread, obsolete_tag, new_tag)) {
    art::ScopedThreadStateChange stsc(thread, art::ThreadState::kNative);
    impl::EventHandlerFunc<kEvent> func(env);
    ExecuteCallback<kEvent>(func, obsolete_tag, new_tag);
  } else {
    // Unlike most others this has a default action to make sure that agents without knowledge of
    // this extension get reasonable behavior.
    jlong temp = *obsolete_tag;
    *obsolete_tag = *new_tag;
    *new_tag = temp;
  }
}

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,

    [[maybe_unused]] JNIEnv* jnienv,
    [[maybe_unused]] jthread jni_thread,
    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,
    [[maybe_unused]] JNIEnv* jnienv,
    [[maybe_unused]] jthread jni_thread,
    [[maybe_unused]] jmethodID jmethod,
    [[maybe_unused]] jboolean is_exception,
    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,
    [[maybe_unused]] JNIEnv* jnienv,
    [[maybe_unused]] jthread jni_thread,
    [[maybe_unused]] jmethodID method,
    [[maybe_unused]] jlocation location,
    [[maybe_unused]] jclass field_klass,
    [[maybe_unused]] jobject object,
    jfieldID field,
    [[maybe_unused]] char type_char,
    [[maybe_unused]] jvalue val) 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,
    [[maybe_unused]] JNIEnv* jnienv,
    [[maybe_unused]] jthread jni_thread,
    [[maybe_unused]] jmethodID method,
    [[maybe_unused]] jlocation location,
    [[maybe_unused]] jclass field_klass,
    [[maybe_unused]] jobject object,
    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,
    [[maybe_unused]] const art::ShadowFrame* frame) {
  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_;
    // Check that we cleaned up any old disables. This should only increase (or be equals if we do
    // another ClassLoad/Prepare recursively).
    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 <>
inline void EventHandler::DispatchEvent<ArtJvmtiEvent::kStructuralDexFileLoadHook>(
    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::kStructuralDexFileLoadHook>(
      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,
                                         [[maybe_unused]] Args... args) 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_
