/*
 * 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)                       \
  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,
    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_;
    // 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,
                                         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_
