/* Copyright (C) 2016 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include <android-base/thread_annotations.h>

#include "base/locks.h"
#include "base/mutex.h"
#include "events-inl.h"

#include <array>
#include <functional>
#include <sys/time.h>

#include "arch/context.h"
#include "art_field-inl.h"
#include "art_jvmti.h"
#include "art_method-inl.h"
#include "base/mutex.h"
#include "deopt_manager.h"
#include "dex/dex_file_types.h"
#include "events.h"
#include "gc/allocation_listener.h"
#include "gc/gc_pause_listener.h"
#include "gc/heap.h"
#include "gc/scoped_gc_critical_section.h"
#include "handle_scope-inl.h"
#include "indirect_reference_table.h"
#include "instrumentation.h"
#include "interpreter/shadow_frame.h"
#include "jni/jni_env_ext-inl.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
#include "jvalue.h"
#include "jvmti.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "monitor-inl.h"
#include "nativehelper/scoped_local_ref.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "scoped_thread_state_change.h"
#include "stack.h"
#include "thread.h"
#include "thread-inl.h"
#include "thread_list.h"
#include "ti_phase.h"
#include "ti_thread.h"
#include "well_known_classes.h"

namespace openjdkjvmti {

void ArtJvmtiEventCallbacks::CopyExtensionsFrom(const ArtJvmtiEventCallbacks* cb) {
  if (art::kIsDebugBuild) {
    ArtJvmtiEventCallbacks clean;
    DCHECK_EQ(memcmp(&clean, this, sizeof(clean)), 0)
        << "CopyExtensionsFrom called with initialized eventsCallbacks!";
  }
  if (cb != nullptr) {
    memcpy(this, cb, sizeof(*this));
  } else {
    memset(this, 0, sizeof(*this));
  }
}

jvmtiError ArtJvmtiEventCallbacks::Set(jint index, jvmtiExtensionEvent cb) {
  switch (index) {
    case static_cast<jint>(ArtJvmtiEvent::kDdmPublishChunk):
      DdmPublishChunk = reinterpret_cast<ArtJvmtiEventDdmPublishChunk>(cb);
      return OK;
    default:
      return ERR(ILLEGAL_ARGUMENT);
  }
}


bool IsExtensionEvent(jint e) {
  return e >= static_cast<jint>(ArtJvmtiEvent::kMinEventTypeVal) &&
      e <= static_cast<jint>(ArtJvmtiEvent::kMaxEventTypeVal) &&
      IsExtensionEvent(static_cast<ArtJvmtiEvent>(e));
}

bool IsExtensionEvent(ArtJvmtiEvent e) {
  switch (e) {
    case ArtJvmtiEvent::kDdmPublishChunk:
      return true;
    default:
      return false;
  }
}

bool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
  return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
}

EventMask& EventMasks::GetEventMask(art::Thread* thread) {
  if (thread == nullptr) {
    return global_event_mask;
  }

  for (auto& pair : thread_event_masks) {
    const UniqueThread& unique_thread = pair.first;
    if (unique_thread.first == thread &&
        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
      return pair.second;
    }
  }

  // TODO: Remove old UniqueThread with the same pointer, if exists.

  thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
  return thread_event_masks.back().second;
}

EventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
  if (thread == nullptr) {
    return &global_event_mask;
  }

  for (auto& pair : thread_event_masks) {
    const UniqueThread& unique_thread = pair.first;
    if (unique_thread.first == thread &&
        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
      return &pair.second;
    }
  }

  return nullptr;
}


void EventMasks::EnableEvent(ArtJvmTiEnv* env, art::Thread* thread, ArtJvmtiEvent event) {
  DCHECK_EQ(&env->event_masks, this);
  env->event_info_mutex_.AssertExclusiveHeld(art::Thread::Current());
  DCHECK(EventMask::EventIsInRange(event));
  GetEventMask(thread).Set(event);
  if (thread != nullptr) {
    unioned_thread_event_mask.Set(event, true);
  }
}

void EventMasks::DisableEvent(ArtJvmTiEnv* env, art::Thread* thread, ArtJvmtiEvent event) {
  DCHECK_EQ(&env->event_masks, this);
  env->event_info_mutex_.AssertExclusiveHeld(art::Thread::Current());
  DCHECK(EventMask::EventIsInRange(event));
  GetEventMask(thread).Set(event, false);
  if (thread != nullptr) {
    // Regenerate union for the event.
    bool union_value = false;
    for (auto& pair : thread_event_masks) {
      union_value |= pair.second.Test(event);
      if (union_value) {
        break;
      }
    }
    unioned_thread_event_mask.Set(event, union_value);
  }
}

void EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
  if (UNLIKELY(caps.can_retransform_classes == 1)) {
    // If we are giving this env the retransform classes cap we need to switch all events of
    // NonTransformable to Transformable and vice versa.
    ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
                                         : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
    ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
                                      : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
    if (global_event_mask.Test(to_remove)) {
      CHECK(!global_event_mask.Test(to_add));
      global_event_mask.Set(to_remove, false);
      global_event_mask.Set(to_add, true);
    }

    if (unioned_thread_event_mask.Test(to_remove)) {
      CHECK(!unioned_thread_event_mask.Test(to_add));
      unioned_thread_event_mask.Set(to_remove, false);
      unioned_thread_event_mask.Set(to_add, true);
    }
    for (auto thread_mask : thread_event_masks) {
      if (thread_mask.second.Test(to_remove)) {
        CHECK(!thread_mask.second.Test(to_add));
        thread_mask.second.Set(to_remove, false);
        thread_mask.second.Set(to_add, true);
      }
    }
  }
}

void EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
  art::WriterMutexLock mu(art::Thread::Current(), envs_lock_);
  envs.push_back(env);
}

void EventHandler::RemoveArtJvmTiEnv(ArtJvmTiEnv* env) {
  art::WriterMutexLock mu(art::Thread::Current(), envs_lock_);
  // Since we might be currently iterating over the envs list we cannot actually erase elements.
  // Instead we will simply replace them with 'nullptr' and skip them manually.
  auto it = std::find(envs.begin(), envs.end(), env);
  if (it != envs.end()) {
    envs.erase(it);
    for (size_t i = static_cast<size_t>(ArtJvmtiEvent::kMinEventTypeVal);
         i <= static_cast<size_t>(ArtJvmtiEvent::kMaxEventTypeVal);
         ++i) {
      RecalculateGlobalEventMaskLocked(static_cast<ArtJvmtiEvent>(i));
    }
  }
}

static bool IsThreadControllable(ArtJvmtiEvent event) {
  switch (event) {
    case ArtJvmtiEvent::kVmInit:
    case ArtJvmtiEvent::kVmStart:
    case ArtJvmtiEvent::kVmDeath:
    case ArtJvmtiEvent::kThreadStart:
    case ArtJvmtiEvent::kCompiledMethodLoad:
    case ArtJvmtiEvent::kCompiledMethodUnload:
    case ArtJvmtiEvent::kDynamicCodeGenerated:
    case ArtJvmtiEvent::kDataDumpRequest:
      return false;

    default:
      return true;
  }
}

template<typename Type>
static Type AddLocalRef(art::JNIEnvExt* e, art::ObjPtr<art::mirror::Object> obj)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  return (obj == nullptr) ? nullptr : e->AddLocalReference<Type>(obj);
}

template<ArtJvmtiEvent kEvent, typename ...Args>
static void RunEventCallback(EventHandler* handler,
                             art::Thread* self,
                             art::JNIEnvExt* jnienv,
                             Args... args)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  ScopedLocalRef<jthread> thread_jni(jnienv, AddLocalRef<jthread>(jnienv, self->GetPeer()));
  handler->DispatchEvent<kEvent>(self,
                                 static_cast<JNIEnv*>(jnienv),
                                 thread_jni.get(),
                                 args...);
}

static void SetupDdmTracking(art::DdmCallback* listener, bool enable) {
  art::ScopedObjectAccess soa(art::Thread::Current());
  if (enable) {
    art::Runtime::Current()->GetRuntimeCallbacks()->AddDdmCallback(listener);
  } else {
    art::Runtime::Current()->GetRuntimeCallbacks()->RemoveDdmCallback(listener);
  }
}

class JvmtiDdmChunkListener : public art::DdmCallback {
 public:
  explicit JvmtiDdmChunkListener(EventHandler* handler) : handler_(handler) {}

  void DdmPublishChunk(uint32_t type, const art::ArrayRef<const uint8_t>& data)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kDdmPublishChunk)) {
      art::Thread* self = art::Thread::Current();
      handler_->DispatchEvent<ArtJvmtiEvent::kDdmPublishChunk>(
          self,
          static_cast<JNIEnv*>(self->GetJniEnv()),
          static_cast<jint>(type),
          static_cast<jint>(data.size()),
          reinterpret_cast<const jbyte*>(data.data()));
    }
  }

 private:
  EventHandler* handler_;

  DISALLOW_COPY_AND_ASSIGN(JvmtiDdmChunkListener);
};

class JvmtiAllocationListener : public art::gc::AllocationListener {
 public:
  explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}

  void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    DCHECK_EQ(self, art::Thread::Current());

    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
      art::StackHandleScope<1> hs(self);
      auto h = hs.NewHandleWrapper(obj);
      // jvmtiEventVMObjectAlloc parameters:
      //      jvmtiEnv *jvmti_env,
      //      JNIEnv* jni_env,
      //      jthread thread,
      //      jobject object,
      //      jclass object_klass,
      //      jlong size
      art::JNIEnvExt* jni_env = self->GetJniEnv();
      ScopedLocalRef<jobject> object(
          jni_env, jni_env->AddLocalReference<jobject>(*obj));
      ScopedLocalRef<jclass> klass(
          jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));

      RunEventCallback<ArtJvmtiEvent::kVmObjectAlloc>(handler_,
                                                      self,
                                                      jni_env,
                                                      object.get(),
                                                      klass.get(),
                                                      static_cast<jlong>(byte_count));
    }
  }

 private:
  EventHandler* handler_;
};

static void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
  // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
  // now, do a workaround: (possibly) acquire and release.
  art::ScopedObjectAccess soa(art::Thread::Current());
  art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
  if (enable) {
    art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
  } else {
    art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
  }
}

class JvmtiMonitorListener : public art::MonitorCallback {
 public:
  explicit JvmtiMonitorListener(EventHandler* handler) : handler_(handler) {}

  void MonitorContendedLocking(art::Monitor* m)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorContendedEnter)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      ScopedLocalRef<jobject> mon(jnienv, AddLocalRef<jobject>(jnienv, m->GetObject()));
      RunEventCallback<ArtJvmtiEvent::kMonitorContendedEnter>(
          handler_,
          self,
          jnienv,
          mon.get());
    }
  }

  void MonitorContendedLocked(art::Monitor* m)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorContendedEntered)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      ScopedLocalRef<jobject> mon(jnienv, AddLocalRef<jobject>(jnienv, m->GetObject()));
      RunEventCallback<ArtJvmtiEvent::kMonitorContendedEntered>(
          handler_,
          self,
          jnienv,
          mon.get());
    }
  }

  void ObjectWaitStart(art::Handle<art::mirror::Object> obj, int64_t timeout)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorWait)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      ScopedLocalRef<jobject> mon(jnienv, AddLocalRef<jobject>(jnienv, obj.Get()));
      RunEventCallback<ArtJvmtiEvent::kMonitorWait>(
          handler_,
          self,
          jnienv,
          mon.get(),
          static_cast<jlong>(timeout));
    }
  }


  // Our interpretation of the spec is that the JVMTI_EVENT_MONITOR_WAITED will be sent immediately
  // after a thread has woken up from a sleep caused by a call to Object#wait. If the thread will
  // never go to sleep (due to not having the lock, having bad arguments, or having an exception
  // propogated from JVMTI_EVENT_MONITOR_WAIT) we will not send this event.
  //
  // This does not fully match the RI semantics. Specifically, we will not send the
  // JVMTI_EVENT_MONITOR_WAITED event in one situation where the RI would, there was an exception in
  // the JVMTI_EVENT_MONITOR_WAIT event but otherwise the call was fine. In that case the RI would
  // send this event and return without going to sleep.
  //
  // See b/65558434 for more discussion.
  void MonitorWaitFinished(art::Monitor* m, bool timeout)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorWaited)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      ScopedLocalRef<jobject> mon(jnienv, AddLocalRef<jobject>(jnienv, m->GetObject()));
      RunEventCallback<ArtJvmtiEvent::kMonitorWaited>(
          handler_,
          self,
          jnienv,
          mon.get(),
          static_cast<jboolean>(timeout));
    }
  }

 private:
  EventHandler* handler_;
};

class JvmtiParkListener : public art::ParkCallback {
 public:
  explicit JvmtiParkListener(EventHandler* handler) : handler_(handler) {}

  void ThreadParkStart(bool is_absolute, int64_t timeout)
      override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorWait)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      art::ArtField* parkBlockerField = art::jni::DecodeArtField(
          art::WellKnownClasses::java_lang_Thread_parkBlocker);
      art::ObjPtr<art::mirror::Object> blocker_obj = parkBlockerField->GetObj(self->GetPeer());
      if (blocker_obj.IsNull()) {
        blocker_obj = self->GetPeer();
      }
      int64_t timeout_ms;
      if (!is_absolute) {
        if (timeout == 0) {
          timeout_ms = 0;
        } else {
          timeout_ms = timeout / 1000000;
          if (timeout_ms == 0) {
            // If we were instructed to park for a nonzero number of nanoseconds, but not enough
            // to be a full millisecond, round up to 1 ms. A nonzero park() call will return
            // soon, but a 0 wait or park call will wait indefinitely.
            timeout_ms = 1;
          }
        }
      } else {
        struct timeval tv;
        gettimeofday(&tv, (struct timezone *) nullptr);
        int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
        if (now < timeout) {
          timeout_ms = timeout - now;
        } else {
          // Waiting for 0 ms is an indefinite wait; parking until a time in
          // the past or the current time will return immediately, so emulate
          // the shortest possible wait event.
          timeout_ms = 1;
        }
      }
      ScopedLocalRef<jobject> blocker(jnienv, AddLocalRef<jobject>(jnienv, blocker_obj.Ptr()));
      RunEventCallback<ArtJvmtiEvent::kMonitorWait>(
          handler_,
          self,
          jnienv,
          blocker.get(),
          static_cast<jlong>(timeout_ms));
    }
  }


  // Our interpretation of the spec is that the JVMTI_EVENT_MONITOR_WAITED will be sent immediately
  // after a thread has woken up from a sleep caused by a call to Object#wait. If the thread will
  // never go to sleep (due to not having the lock, having bad arguments, or having an exception
  // propogated from JVMTI_EVENT_MONITOR_WAIT) we will not send this event.
  //
  // This does not fully match the RI semantics. Specifically, we will not send the
  // JVMTI_EVENT_MONITOR_WAITED event in one situation where the RI would, there was an exception in
  // the JVMTI_EVENT_MONITOR_WAIT event but otherwise the call was fine. In that case the RI would
  // send this event and return without going to sleep.
  //
  // See b/65558434 for more discussion.
  void ThreadParkFinished(bool timeout) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMonitorWaited)) {
      art::Thread* self = art::Thread::Current();
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      art::ArtField* parkBlockerField = art::jni::DecodeArtField(
          art::WellKnownClasses::java_lang_Thread_parkBlocker);
      art::ObjPtr<art::mirror::Object> blocker_obj = parkBlockerField->GetObj(self->GetPeer());
      if (blocker_obj.IsNull()) {
        blocker_obj = self->GetPeer();
      }
      ScopedLocalRef<jobject> blocker(jnienv, AddLocalRef<jobject>(jnienv, blocker_obj.Ptr()));
      RunEventCallback<ArtJvmtiEvent::kMonitorWaited>(
          handler_,
          self,
          jnienv,
          blocker.get(),
          static_cast<jboolean>(timeout));
    }
  }

 private:
  EventHandler* handler_;
};

static void SetupMonitorListener(art::MonitorCallback* monitor_listener, art::ParkCallback* park_listener, bool enable) {
  // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
  // now, do a workaround: (possibly) acquire and release.
  art::ScopedObjectAccess soa(art::Thread::Current());
  if (enable) {
    art::Runtime::Current()->GetRuntimeCallbacks()->AddMonitorCallback(monitor_listener);
    art::Runtime::Current()->GetRuntimeCallbacks()->AddParkCallback(park_listener);
  } else {
    art::Runtime::Current()->GetRuntimeCallbacks()->RemoveMonitorCallback(monitor_listener);
    art::Runtime::Current()->GetRuntimeCallbacks()->RemoveParkCallback(park_listener);
  }
}

// Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
class JvmtiGcPauseListener : public art::gc::GcPauseListener {
 public:
  explicit JvmtiGcPauseListener(EventHandler* handler)
      : handler_(handler),
        start_enabled_(false),
        finish_enabled_(false) {}

  void StartPause() override {
    handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionStart>(art::Thread::Current());
  }

  void EndPause() override {
    handler_->DispatchEvent<ArtJvmtiEvent::kGarbageCollectionFinish>(art::Thread::Current());
  }

  bool IsEnabled() {
    return start_enabled_ || finish_enabled_;
  }

  void SetStartEnabled(bool e) {
    start_enabled_ = e;
  }

  void SetFinishEnabled(bool e) {
    finish_enabled_ = e;
  }

 private:
  EventHandler* handler_;
  bool start_enabled_;
  bool finish_enabled_;
};

static void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
  bool old_state = listener->IsEnabled();

  if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
    listener->SetStartEnabled(enable);
  } else {
    listener->SetFinishEnabled(enable);
  }

  bool new_state = listener->IsEnabled();

  if (old_state != new_state) {
    if (new_state) {
      art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
    } else {
      art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
    }
  }
}

class JvmtiMethodTraceListener final : public art::instrumentation::InstrumentationListener {
 public:
  explicit JvmtiMethodTraceListener(EventHandler* handler)
      : event_handler_(handler),
        non_standard_exits_lock_("JVMTI NonStandard Exits list lock",
                                 art::LockLevel::kGenericBottomLock) {}

  void AddDelayedNonStandardExitEvent(const art::ShadowFrame* frame, bool is_object, jvalue val)
      REQUIRES_SHARED(art::Locks::mutator_lock_)
          REQUIRES(art::Locks::user_code_suspension_lock_, art::Locks::thread_list_lock_) {
    art::Thread* self = art::Thread::Current();
    jobject to_cleanup = nullptr;
    jobject new_val = is_object ? self->GetJniEnv()->NewGlobalRef(val.l) : nullptr;
    {
      art::MutexLock mu(self, non_standard_exits_lock_);
      NonStandardExitEventInfo saved{ nullptr, { .j = 0 } };
      if (is_object) {
        saved.return_val_obj_ = new_val;
        saved.return_val_.l = saved.return_val_obj_;
      } else {
        saved.return_val_.j = val.j;
      }
      // only objects need cleanup.
      if (UNLIKELY(is_object && non_standard_exits_.find(frame) != non_standard_exits_.end())) {
        to_cleanup = non_standard_exits_.find(frame)->second.return_val_obj_;
      }
      non_standard_exits_.insert_or_assign(frame, saved);
    }
    self->GetJniEnv()->DeleteGlobalRef(to_cleanup);
  }

  // Call-back for when a method is entered.
  void MethodEntered(art::Thread* self,
                     art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
                     art::ArtMethod* method,
                     uint32_t dex_pc ATTRIBUTE_UNUSED)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (!method->IsRuntimeMethod() &&
        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodEntry)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      RunEventCallback<ArtJvmtiEvent::kMethodEntry>(event_handler_,
                                                    self,
                                                    jnienv,
                                                    art::jni::EncodeArtMethod(method));
    }
  }

  // TODO Maybe try to combine this with below using templates?
  // Callback for when a method is exited with a reference return value.
  void MethodExited(art::Thread* self,
                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
                    art::ArtMethod* method,
                    uint32_t dex_pc ATTRIBUTE_UNUSED,
                    art::instrumentation::OptionalFrame frame,
                    art::MutableHandle<art::mirror::Object>& return_value)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (method->IsRuntimeMethod()) {
      return;
    }
    if (frame.has_value() && UNLIKELY(event_handler_->IsEventEnabledAnywhere(
                                 ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue))) {
      DCHECK(!frame->get().GetSkipMethodExitEvents());
      bool has_return = false;
      jobject ret_val = nullptr;
      {
        art::MutexLock mu(self, non_standard_exits_lock_);
        const art::ShadowFrame* sframe = &frame.value().get();
        const auto it = non_standard_exits_.find(sframe);
        if (it != non_standard_exits_.end()) {
          ret_val = it->second.return_val_obj_;
          return_value.Assign(self->DecodeJObject(ret_val));
          non_standard_exits_.erase(it);
          has_return = true;
        }
      }
      if (has_return) {
        ScopedLocalRef<jthread> thr(self->GetJniEnv(),
                                    self->GetJniEnv()->NewLocalRef(self->GetPeer()));
        art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
        self->GetJniEnv()->DeleteGlobalRef(ret_val);
        event_handler_->SetInternalEvent(
            thr.get(), ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue, JVMTI_DISABLE);
      }
    }
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
      DCHECK_EQ(
          method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize)->GetReturnTypePrimitive(),
          art::Primitive::kPrimNot) << method->PrettyMethod();
      DCHECK(!self->IsExceptionPending());
      jvalue val;
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      ScopedLocalRef<jobject> return_jobj(jnienv, AddLocalRef<jobject>(jnienv, return_value.Get()));
      val.l = return_jobj.get();
      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          /*was_popped_by_exception=*/ static_cast<jboolean>(JNI_FALSE),
          val);
    }
  }

  // Call-back for when a method is exited.
  void MethodExited(art::Thread* self,
                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
                    art::ArtMethod* method,
                    uint32_t dex_pc ATTRIBUTE_UNUSED,
                    art::instrumentation::OptionalFrame frame,
                    art::JValue& return_value) REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (frame.has_value() &&
        UNLIKELY(event_handler_->IsEventEnabledAnywhere(
            ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue))) {
      DCHECK(!frame->get().GetSkipMethodExitEvents());
      bool has_return = false;
      {
        art::MutexLock mu(self, non_standard_exits_lock_);
        const art::ShadowFrame* sframe = &frame.value().get();
        const auto it = non_standard_exits_.find(sframe);
        if (it != non_standard_exits_.end()) {
          return_value.SetJ(it->second.return_val_.j);
          non_standard_exits_.erase(it);
          has_return = true;
        }
      }
      if (has_return) {
        ScopedLocalRef<jthread> thr(self->GetJniEnv(),
                                    self->GetJniEnv()->NewLocalRef(self->GetPeer()));
        art::ScopedThreadSuspension sts(self, art::ThreadState::kNative);
        event_handler_->SetInternalEvent(
            thr.get(), ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue, JVMTI_DISABLE);
      }
    }
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
      DCHECK_NE(
          method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize)->GetReturnTypePrimitive(),
          art::Primitive::kPrimNot) << method->PrettyMethod();
      DCHECK(!self->IsExceptionPending()) << self->GetException()->Dump();
      jvalue val;
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      // 64bit integer is the largest value in the union so we should be fine simply copying it into
      // the union.
      val.j = return_value.GetJ();
      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          /*was_popped_by_exception=*/ static_cast<jboolean>(JNI_FALSE),
          val);
    }
  }

  // Call-back for when a method is popped due to an exception throw. A method will either cause a
  // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
  void MethodUnwind(art::Thread* self,
                    art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
                    art::ArtMethod* method,
                    uint32_t dex_pc ATTRIBUTE_UNUSED)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (!method->IsRuntimeMethod() &&
        event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kMethodExit)) {
      jvalue val;
      // Just set this to 0xffffffffffffffff so it's not uninitialized.
      val.j = static_cast<jlong>(-1);
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      art::StackHandleScope<1> hs(self);
      art::Handle<art::mirror::Throwable> old_exception(hs.NewHandle(self->GetException()));
      CHECK(!old_exception.IsNull());
      self->ClearException();
      RunEventCallback<ArtJvmtiEvent::kMethodExit>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          /*was_popped_by_exception=*/ static_cast<jboolean>(JNI_TRUE),
          val);
      // Match RI behavior of just throwing away original exception if a new one is thrown.
      if (LIKELY(!self->IsExceptionPending())) {
        self->SetException(old_exception.Get());
      }
    }
  }

  // Call-back for when the dex pc moves in a method.
  void DexPcMoved(art::Thread* self,
                  art::Handle<art::mirror::Object> this_object ATTRIBUTE_UNUSED,
                  art::ArtMethod* method,
                  uint32_t new_dex_pc)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    DCHECK(!method->IsRuntimeMethod());
    // Default methods might be copied to multiple classes. We need to get the canonical version of
    // this method so that we can check for breakpoints correctly.
    // TODO We should maybe do this on other events to ensure that we are consistent WRT default
    // methods. This could interact with obsolete methods if we ever let interface redefinition
    // happen though.
    method = method->GetCanonicalMethod();
    art::JNIEnvExt* jnienv = self->GetJniEnv();
    jmethodID jmethod = art::jni::EncodeArtMethod(method);
    jlocation location = static_cast<jlocation>(new_dex_pc);
    // Step event is reported first according to the spec.
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kSingleStep)) {
      RunEventCallback<ArtJvmtiEvent::kSingleStep>(event_handler_, self, jnienv, jmethod, location);
    }
    // Next we do the Breakpoint events. The Dispatch code will filter the individual
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kBreakpoint)) {
      RunEventCallback<ArtJvmtiEvent::kBreakpoint>(event_handler_, self, jnienv, jmethod, location);
    }
  }

  // Call-back for when we read from a field.
  void FieldRead(art::Thread* self,
                 art::Handle<art::mirror::Object> this_object,
                 art::ArtMethod* method,
                 uint32_t dex_pc,
                 art::ArtField* field)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldAccess)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      // DCHECK(!self->IsExceptionPending());
      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
      ScopedLocalRef<jobject> fklass(jnienv,
                                     AddLocalRef<jobject>(jnienv,
                                                          field->GetDeclaringClass().Ptr()));
      RunEventCallback<ArtJvmtiEvent::kFieldAccess>(event_handler_,
                                                    self,
                                                    jnienv,
                                                    art::jni::EncodeArtMethod(method),
                                                    static_cast<jlocation>(dex_pc),
                                                    static_cast<jclass>(fklass.get()),
                                                    this_ref.get(),
                                                    art::jni::EncodeArtField(field));
    }
  }

  void FieldWritten(art::Thread* self,
                    art::Handle<art::mirror::Object> this_object,
                    art::ArtMethod* method,
                    uint32_t dex_pc,
                    art::ArtField* field,
                    art::Handle<art::mirror::Object> new_val)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      // DCHECK(!self->IsExceptionPending());
      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
      ScopedLocalRef<jobject> fklass(jnienv,
                                     AddLocalRef<jobject>(jnienv,
                                                          field->GetDeclaringClass().Ptr()));
      ScopedLocalRef<jobject> fval(jnienv, AddLocalRef<jobject>(jnienv, new_val.Get()));
      jvalue val;
      val.l = fval.get();
      RunEventCallback<ArtJvmtiEvent::kFieldModification>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          static_cast<jlocation>(dex_pc),
          static_cast<jclass>(fklass.get()),
          field->IsStatic() ? nullptr :  this_ref.get(),
          art::jni::EncodeArtField(field),
          'L',  // type_char
          val);
    }
  }

  // Call-back for when we write into a field.
  void FieldWritten(art::Thread* self,
                    art::Handle<art::mirror::Object> this_object,
                    art::ArtMethod* method,
                    uint32_t dex_pc,
                    art::ArtField* field,
                    const art::JValue& field_value)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      DCHECK(!self->IsExceptionPending());
      ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get()));
      ScopedLocalRef<jobject> fklass(jnienv,
                                     AddLocalRef<jobject>(jnienv,
                                                          field->GetDeclaringClass().Ptr()));
      char type_char = art::Primitive::Descriptor(field->GetTypeAsPrimitiveType())[0];
      jvalue val;
      // 64bit integer is the largest value in the union so we should be fine simply copying it into
      // the union.
      val.j = field_value.GetJ();
      RunEventCallback<ArtJvmtiEvent::kFieldModification>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          static_cast<jlocation>(dex_pc),
          static_cast<jclass>(fklass.get()),
          field->IsStatic() ? nullptr :  this_ref.get(),  // nb static field modification get given
                                                          // the class as this_object for some
                                                          // reason.
          art::jni::EncodeArtField(field),
          type_char,
          val);
    }
  }

  void WatchedFramePop(art::Thread* self, const art::ShadowFrame& frame)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
    // Remove the force-interpreter added by the WatchFrame.
    {
      art::MutexLock mu(self, *art::Locks::thread_list_lock_);
      CHECK_GT(self->ForceInterpreterCount(), 0u);
      self->DecrementForceInterpreterCount();
    }
    jboolean is_exception_pending = self->IsExceptionPending();
    RunEventCallback<ArtJvmtiEvent::kFramePop>(
        event_handler_,
        self,
        jnienv,
        art::jni::EncodeArtMethod(frame.GetMethod()),
        is_exception_pending,
        &frame);
  }

  static void FindCatchMethodsFromThrow(art::Thread* self,
                                        art::Handle<art::mirror::Throwable> exception,
                                        /*out*/ art::ArtMethod** out_method,
                                        /*out*/ uint32_t* dex_pc)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    // Finds the location where this exception will most likely be caught. We ignore intervening
    // native frames (which could catch the exception) and return the closest java frame with a
    // compatible catch statement.
    class CatchLocationFinder final : public art::StackVisitor {
     public:
      CatchLocationFinder(art::Thread* target,
                          art::Handle<art::mirror::Class> exception_class,
                          art::Context* context,
                          /*out*/ art::ArtMethod** out_catch_method,
                          /*out*/ uint32_t* out_catch_pc)
          REQUIRES_SHARED(art::Locks::mutator_lock_)
        : StackVisitor(target, context, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
          exception_class_(exception_class),
          catch_method_ptr_(out_catch_method),
          catch_dex_pc_ptr_(out_catch_pc) {}

      bool VisitFrame() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
        art::ArtMethod* method = GetMethod();
        DCHECK(method != nullptr);
        if (method->IsRuntimeMethod()) {
          return true;
        }

        if (!method->IsNative()) {
          uint32_t cur_dex_pc = GetDexPc();
          if (cur_dex_pc == art::dex::kDexNoIndex) {
            // This frame looks opaque. Just keep on going.
            return true;
          }
          bool has_no_move_exception = false;
          uint32_t found_dex_pc = method->FindCatchBlock(
              exception_class_, cur_dex_pc, &has_no_move_exception);
          if (found_dex_pc != art::dex::kDexNoIndex) {
            // We found the catch. Store the result and return.
            *catch_method_ptr_ = method;
            *catch_dex_pc_ptr_ = found_dex_pc;
            return false;
          }
        }
        return true;
      }

     private:
      art::Handle<art::mirror::Class> exception_class_;
      art::ArtMethod** catch_method_ptr_;
      uint32_t* catch_dex_pc_ptr_;

      DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
    };

    art::StackHandleScope<1> hs(self);
    *out_method = nullptr;
    *dex_pc = 0;
    std::unique_ptr<art::Context> context(art::Context::Create());

    CatchLocationFinder clf(self,
                            hs.NewHandle(exception->GetClass()),
                            context.get(),
                            /*out*/ out_method,
                            /*out*/ dex_pc);
    clf.WalkStack(/* include_transitions= */ false);
  }

  // Call-back when an exception is thrown.
  void ExceptionThrown(art::Thread* self, art::Handle<art::mirror::Throwable> exception_object)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    DCHECK(self->IsExceptionThrownByCurrentMethod(exception_object.Get()));
    // The instrumentation events get rid of this for us.
    DCHECK(!self->IsExceptionPending());
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kException)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      art::ArtMethod* catch_method;
      uint32_t catch_pc;
      FindCatchMethodsFromThrow(self, exception_object, &catch_method, &catch_pc);
      uint32_t dex_pc = 0;
      art::ArtMethod* method = self->GetCurrentMethod(&dex_pc,
                                                      /* check_suspended= */ true,
                                                      /* abort_on_error= */ art::kIsDebugBuild);
      ScopedLocalRef<jobject> exception(jnienv,
                                        AddLocalRef<jobject>(jnienv, exception_object.Get()));
      RunEventCallback<ArtJvmtiEvent::kException>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          static_cast<jlocation>(dex_pc),
          exception.get(),
          art::jni::EncodeArtMethod(catch_method),
          static_cast<jlocation>(catch_pc));
    }
    return;
  }

  // Call-back when an exception is handled.
  void ExceptionHandled(art::Thread* self, art::Handle<art::mirror::Throwable> exception_object)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    // Since the exception has already been handled there shouldn't be one pending.
    DCHECK(!self->IsExceptionPending());
    if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kExceptionCatch)) {
      art::JNIEnvExt* jnienv = self->GetJniEnv();
      uint32_t dex_pc;
      art::ArtMethod* method = self->GetCurrentMethod(&dex_pc,
                                                      /* check_suspended= */ true,
                                                      /* abort_on_error= */ art::kIsDebugBuild);
      ScopedLocalRef<jobject> exception(jnienv,
                                        AddLocalRef<jobject>(jnienv, exception_object.Get()));
      RunEventCallback<ArtJvmtiEvent::kExceptionCatch>(
          event_handler_,
          self,
          jnienv,
          art::jni::EncodeArtMethod(method),
          static_cast<jlocation>(dex_pc),
          exception.get());
    }
    return;
  }

  // Call-back for when we execute a branch.
  void Branch(art::Thread* self ATTRIBUTE_UNUSED,
              art::ArtMethod* method ATTRIBUTE_UNUSED,
              uint32_t dex_pc ATTRIBUTE_UNUSED,
              int32_t dex_pc_offset ATTRIBUTE_UNUSED)
      REQUIRES_SHARED(art::Locks::mutator_lock_) override {
    return;
  }

 private:
  struct NonStandardExitEventInfo {
    // if non-null is a GlobalReference to the returned value.
    jobject return_val_obj_;
    // The return-value to be passed to the MethodExit event.
    jvalue return_val_;
  };

  EventHandler* const event_handler_;

  mutable art::Mutex non_standard_exits_lock_
      ACQUIRED_BEFORE(art::Locks::instrument_entrypoints_lock_);

  std::unordered_map<const art::ShadowFrame*, NonStandardExitEventInfo> non_standard_exits_
      GUARDED_BY(non_standard_exits_lock_);
};

uint32_t EventHandler::GetInstrumentationEventsFor(ArtJvmtiEvent event) {
  switch (event) {
    case ArtJvmtiEvent::kMethodEntry:
      return art::instrumentation::Instrumentation::kMethodEntered;
    case ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue:
      // TODO We want to do this but supporting only having a single one is difficult.
      // return art::instrumentation::Instrumentation::kMethodExited;
    case ArtJvmtiEvent::kMethodExit: {
      DCHECK(event == ArtJvmtiEvent::kMethodExit ||
            event == ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue)
          << "event = " << static_cast<uint32_t>(event);
      ArtJvmtiEvent other = event == ArtJvmtiEvent::kMethodExit
                                ? ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue
                                : ArtJvmtiEvent::kMethodExit;
      if (LIKELY(!IsEventEnabledAnywhere(other))) {
        return art::instrumentation::Instrumentation::kMethodExited |
               art::instrumentation::Instrumentation::kMethodUnwind;
      } else {
        // The event needs to be kept around/is already enabled by the other jvmti event that uses
        // the same instrumentation event.
        return 0u;
      }
    }
    case ArtJvmtiEvent::kFieldModification:
      return art::instrumentation::Instrumentation::kFieldWritten;
    case ArtJvmtiEvent::kFieldAccess:
      return art::instrumentation::Instrumentation::kFieldRead;
    case ArtJvmtiEvent::kBreakpoint:
    case ArtJvmtiEvent::kSingleStep: {
      // Need to skip adding the listeners if the event is breakpoint/single-step since those events
      // share the same art-instrumentation underlying event. We need to give them their own deopt
      // request though so the test waits until here.
      DCHECK(event == ArtJvmtiEvent::kBreakpoint || event == ArtJvmtiEvent::kSingleStep);
      ArtJvmtiEvent other = event == ArtJvmtiEvent::kBreakpoint ? ArtJvmtiEvent::kSingleStep
                                                                : ArtJvmtiEvent::kBreakpoint;
      if (LIKELY(!IsEventEnabledAnywhere(other))) {
        return art::instrumentation::Instrumentation::kDexPcMoved;
      } else {
        // The event needs to be kept around/is already enabled by the other jvmti event that uses
        // the same instrumentation event.
        return 0u;
      }
    }
    case ArtJvmtiEvent::kFramePop:
      return art::instrumentation::Instrumentation::kWatchedFramePop;
    case ArtJvmtiEvent::kException:
      return art::instrumentation::Instrumentation::kExceptionThrown;
    case ArtJvmtiEvent::kExceptionCatch:
      return art::instrumentation::Instrumentation::kExceptionHandled;
    default:
      LOG(FATAL) << "Unknown event ";
      UNREACHABLE();
  }
}

enum class DeoptRequirement {
  // No deoptimization work required.
  kNone,
  // Limited/no deopt required.
  kLimited,
  // A single thread must be put into interpret only.
  kThread,
  // All methods and all threads deopted.
  kFull,
};

static DeoptRequirement GetDeoptRequirement(ArtJvmtiEvent event, jthread thread) {
  switch (event) {
    case ArtJvmtiEvent::kBreakpoint:
    case ArtJvmtiEvent::kException:
      return DeoptRequirement::kLimited;
    // TODO MethodEntry is needed due to inconsistencies between the interpreter and the trampoline
    // in how to handle exceptions.
    case ArtJvmtiEvent::kMethodEntry:
    case ArtJvmtiEvent::kExceptionCatch:
      return DeoptRequirement::kFull;
    case ArtJvmtiEvent::kMethodExit:
    case ArtJvmtiEvent::kFieldModification:
    case ArtJvmtiEvent::kFieldAccess:
    case ArtJvmtiEvent::kSingleStep:
    case ArtJvmtiEvent::kFramePop:
    case ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue:
      return thread == nullptr ? DeoptRequirement::kFull : DeoptRequirement::kThread;
    case ArtJvmtiEvent::kVmInit:
    case ArtJvmtiEvent::kVmDeath:
    case ArtJvmtiEvent::kThreadStart:
    case ArtJvmtiEvent::kThreadEnd:
    case ArtJvmtiEvent::kClassFileLoadHookNonRetransformable:
    case ArtJvmtiEvent::kClassLoad:
    case ArtJvmtiEvent::kClassPrepare:
    case ArtJvmtiEvent::kVmStart:
    case ArtJvmtiEvent::kNativeMethodBind:
    case ArtJvmtiEvent::kCompiledMethodLoad:
    case ArtJvmtiEvent::kCompiledMethodUnload:
    case ArtJvmtiEvent::kDynamicCodeGenerated:
    case ArtJvmtiEvent::kDataDumpRequest:
    case ArtJvmtiEvent::kMonitorWait:
    case ArtJvmtiEvent::kMonitorWaited:
    case ArtJvmtiEvent::kMonitorContendedEnter:
    case ArtJvmtiEvent::kMonitorContendedEntered:
    case ArtJvmtiEvent::kResourceExhausted:
    case ArtJvmtiEvent::kGarbageCollectionStart:
    case ArtJvmtiEvent::kGarbageCollectionFinish:
    case ArtJvmtiEvent::kObjectFree:
    case ArtJvmtiEvent::kVmObjectAlloc:
    case ArtJvmtiEvent::kClassFileLoadHookRetransformable:
    case ArtJvmtiEvent::kDdmPublishChunk:
      return DeoptRequirement::kNone;
  }
}

jvmtiError EventHandler::HandleEventDeopt(ArtJvmtiEvent event, jthread thread, bool enable) {
  DeoptRequirement deopt_req = GetDeoptRequirement(event, thread);
  // Make sure we can deopt.
  if (deopt_req != DeoptRequirement::kNone) {
    art::ScopedObjectAccess soa(art::Thread::Current());
    DeoptManager* deopt_manager = DeoptManager::Get();
    jvmtiError err = OK;
    if (enable) {
      deopt_manager->AddDeoptimizationRequester();
      switch (deopt_req) {
        case DeoptRequirement::kFull:
          deopt_manager->AddDeoptimizeAllMethods();
          break;
        case DeoptRequirement::kThread:
          err = deopt_manager->AddDeoptimizeThreadMethods(soa, thread);
          break;
        default:
          break;
      }
      if (err != OK) {
        deopt_manager->RemoveDeoptimizationRequester();
        return err;
      }
    } else {
      switch (deopt_req) {
        case DeoptRequirement::kFull:
          deopt_manager->RemoveDeoptimizeAllMethods();
          break;
        case DeoptRequirement::kThread:
          err = deopt_manager->RemoveDeoptimizeThreadMethods(soa, thread);
          break;
        default:
          break;
      }
      deopt_manager->RemoveDeoptimizationRequester();
      if (err != OK) {
        return err;
      }
    }
  }
  return OK;
}

void EventHandler::SetupTraceListener(JvmtiMethodTraceListener* listener,
                                      ArtJvmtiEvent event,
                                      bool enable) {
  // Add the actual listeners.
  uint32_t new_events = GetInstrumentationEventsFor(event);
  if (new_events == 0) {
    return;
  }
  art::ScopedThreadStateChange stsc(art::Thread::Current(), art::ThreadState::kNative);
  art::instrumentation::Instrumentation* instr = art::Runtime::Current()->GetInstrumentation();
  art::ScopedSuspendAll ssa("jvmti method tracing installation");
  if (enable) {
    instr->AddListener(listener, new_events);
  } else {
    instr->RemoveListener(listener, new_events);
  }
  return;
}

// Makes sure that all compiled methods are AsyncDeoptimizable so we can deoptimize (and force to
// the switch interpreter) when we try to get or set a local variable.
void EventHandler::HandleLocalAccessCapabilityAdded() {
  class UpdateEntryPointsClassVisitor : public art::ClassVisitor {
   public:
    explicit UpdateEntryPointsClassVisitor(art::Runtime* runtime)
        : runtime_(runtime) {}

    bool operator()(art::ObjPtr<art::mirror::Class> klass)
        override REQUIRES(art::Locks::mutator_lock_) {
      if (!klass->IsLoaded()) {
        // Skip classes that aren't loaded since they might not have fully allocated and initialized
        // their methods. Furthemore since the jvmti-plugin must have been loaded by this point
        // these methods will definitately be using debuggable code.
        return true;
      }
      for (auto& m : klass->GetMethods(art::kRuntimePointerSize)) {
        const void* code = m.GetEntryPointFromQuickCompiledCode();
        if (m.IsNative() || m.IsProxyMethod()) {
          continue;
        } else if (!runtime_->GetClassLinker()->IsQuickToInterpreterBridge(code) &&
                   !runtime_->IsAsyncDeoptimizeable(reinterpret_cast<uintptr_t>(code))) {
          runtime_->GetInstrumentation()->UpdateMethodsCodeToInterpreterEntryPoint(&m);
        }
      }
      return true;
    }

   private:
    art::Runtime* runtime_;
  };
  art::ScopedObjectAccess soa(art::Thread::Current());
  UpdateEntryPointsClassVisitor visitor(art::Runtime::Current());
  art::Runtime::Current()->GetClassLinker()->VisitClasses(&visitor);
}

bool EventHandler::OtherMonitorEventsEnabledAnywhere(ArtJvmtiEvent event) {
  std::array<ArtJvmtiEvent, 4> events {
    {
      ArtJvmtiEvent::kMonitorContendedEnter,
      ArtJvmtiEvent::kMonitorContendedEntered,
      ArtJvmtiEvent::kMonitorWait,
      ArtJvmtiEvent::kMonitorWaited
    }
  };
  for (ArtJvmtiEvent e : events) {
    if (e != event && IsEventEnabledAnywhere(e)) {
      return true;
    }
  }
  return false;
}

void EventHandler::SetupFramePopTraceListener(bool enable) {
  if (enable) {
    frame_pop_enabled = true;
    SetupTraceListener(method_trace_listener_.get(), ArtJvmtiEvent::kFramePop, enable);
  } else {
    // remove the listener if we have no outstanding frames.
    {
      art::ReaderMutexLock mu(art::Thread::Current(), envs_lock_);
      for (ArtJvmTiEnv *env : envs) {
        art::ReaderMutexLock event_mu(art::Thread::Current(), env->event_info_mutex_);
        if (!env->notify_frames.empty()) {
          // Leaving FramePop listener since there are unsent FramePop events.
          return;
        }
      }
      frame_pop_enabled = false;
    }
    SetupTraceListener(method_trace_listener_.get(), ArtJvmtiEvent::kFramePop, enable);
  }
}

// Handle special work for the given event type, if necessary.
void EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
  switch (event) {
    case ArtJvmtiEvent::kDdmPublishChunk:
      SetupDdmTracking(ddm_listener_.get(), enable);
      return;
    case ArtJvmtiEvent::kVmObjectAlloc:
      SetupObjectAllocationTracking(alloc_listener_.get(), enable);
      return;
    case ArtJvmtiEvent::kGarbageCollectionStart:
    case ArtJvmtiEvent::kGarbageCollectionFinish:
      SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
      return;
    // FramePop can never be disabled once it's been turned on if it was turned off with outstanding
    // pop-events since we would either need to deal with dangling pointers or have missed events.
    case ArtJvmtiEvent::kFramePop:
      if (enable && frame_pop_enabled) {
        // The frame-pop event was held on by pending events so we don't need to do anything.
      } else {
        SetupFramePopTraceListener(enable);
      }
      return;
    case ArtJvmtiEvent::kMethodEntry:
    case ArtJvmtiEvent::kMethodExit:
    case ArtJvmtiEvent::kFieldAccess:
    case ArtJvmtiEvent::kFieldModification:
    case ArtJvmtiEvent::kException:
    case ArtJvmtiEvent::kExceptionCatch:
    case ArtJvmtiEvent::kBreakpoint:
    case ArtJvmtiEvent::kSingleStep:
    case ArtJvmtiEvent::kForceEarlyReturnUpdateReturnValue:
      SetupTraceListener(method_trace_listener_.get(), event, enable);
      return;
    case ArtJvmtiEvent::kMonitorContendedEnter:
    case ArtJvmtiEvent::kMonitorContendedEntered:
    case ArtJvmtiEvent::kMonitorWait:
    case ArtJvmtiEvent::kMonitorWaited:
      if (!OtherMonitorEventsEnabledAnywhere(event)) {
        SetupMonitorListener(monitor_listener_.get(), park_listener_.get(), enable);
      }
      return;
    default:
      break;
  }
  return;
}

// Checks to see if the env has the capabilities associated with the given event.
static bool HasAssociatedCapability(ArtJvmTiEnv* env,
                                    ArtJvmtiEvent event) {
  jvmtiCapabilities caps = env->capabilities;
  switch (event) {
    case ArtJvmtiEvent::kBreakpoint:
      return caps.can_generate_breakpoint_events == 1;

    case ArtJvmtiEvent::kCompiledMethodLoad:
    case ArtJvmtiEvent::kCompiledMethodUnload:
      return caps.can_generate_compiled_method_load_events == 1;

    case ArtJvmtiEvent::kException:
    case ArtJvmtiEvent::kExceptionCatch:
      return caps.can_generate_exception_events == 1;

    case ArtJvmtiEvent::kFieldAccess:
      return caps.can_generate_field_access_events == 1;

    case ArtJvmtiEvent::kFieldModification:
      return caps.can_generate_field_modification_events == 1;

    case ArtJvmtiEvent::kFramePop:
      return caps.can_generate_frame_pop_events == 1;

    case ArtJvmtiEvent::kGarbageCollectionStart:
    case ArtJvmtiEvent::kGarbageCollectionFinish:
      return caps.can_generate_garbage_collection_events == 1;

    case ArtJvmtiEvent::kMethodEntry:
      return caps.can_generate_method_entry_events == 1;

    case ArtJvmtiEvent::kMethodExit:
      return caps.can_generate_method_exit_events == 1;

    case ArtJvmtiEvent::kMonitorContendedEnter:
    case ArtJvmtiEvent::kMonitorContendedEntered:
    case ArtJvmtiEvent::kMonitorWait:
    case ArtJvmtiEvent::kMonitorWaited:
      return caps.can_generate_monitor_events == 1;

    case ArtJvmtiEvent::kNativeMethodBind:
      return caps.can_generate_native_method_bind_events == 1;

    case ArtJvmtiEvent::kObjectFree:
      return caps.can_generate_object_free_events == 1;

    case ArtJvmtiEvent::kSingleStep:
      return caps.can_generate_single_step_events == 1;

    case ArtJvmtiEvent::kVmObjectAlloc:
      return caps.can_generate_vm_object_alloc_events == 1;

    default:
      return true;
  }
}

static bool IsInternalEvent(ArtJvmtiEvent event) {
  return static_cast<uint32_t>(event) >=
         static_cast<uint32_t>(ArtJvmtiEvent::kMinInternalEventTypeVal);
}

jvmtiError EventHandler::SetInternalEvent(jthread thread,
                                          ArtJvmtiEvent event,
                                          jvmtiEventMode mode) {
  CHECK(IsInternalEvent(event)) << static_cast<uint32_t>(event);

  art::Thread* self = art::Thread::Current();
  art::Thread* target = nullptr;
  ScopedNoUserCodeSuspension snucs(self);
  // The overall state across all threads and jvmtiEnvs. This is used to control the state of the
  // instrumentation handlers since we only want each added once.
  bool old_state;
  bool new_state;
  // The state for just the current 'thread' (including null) across all jvmtiEnvs. This is used to
  // control the deoptimization state since we do refcounting for that and need to perform different
  // actions depending on if the event is limited to a single thread or global.
  bool old_thread_state;
  bool new_thread_state;
  {
    // From now on we know we cannot get suspended by user-code.
    // NB This does a SuspendCheck (during thread state change) so we need to
    // make sure we don't have the 'suspend_lock' locked here.
    art::ScopedObjectAccess soa(self);
    art::WriterMutexLock el_mu(self, envs_lock_);
    art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
    jvmtiError err = ERR(INTERNAL);
    if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
      return err;
    } else if (target->IsStillStarting() || target->GetState() == art::ThreadState::kStarting) {
      target->Dump(LOG_STREAM(WARNING) << "Is not alive: ");
      return ERR(THREAD_NOT_ALIVE);
    }

    // Make sure we have a valid jthread to pass to deopt-manager.
    ScopedLocalRef<jthread> thread_lr(
        soa.Env(), thread != nullptr ? nullptr : soa.AddLocalReference<jthread>(target->GetPeer()));
    if (thread == nullptr) {
      thread = thread_lr.get();
    }
    CHECK(thread != nullptr);

    {
      DCHECK_GE(GetInternalEventRefcount(event) + (mode == JVMTI_ENABLE ? 1 : -1), 0)
        << "Refcount: " << GetInternalEventRefcount(event);
      DCHECK_GE(GetInternalEventThreadRefcount(event, target) + (mode == JVMTI_ENABLE ? 1 : -1), 0)
        << "Refcount: " << GetInternalEventThreadRefcount(event, target);
      DCHECK_GE(GetInternalEventRefcount(event), GetInternalEventThreadRefcount(event, target));
      old_state = GetInternalEventRefcount(event) > 0;
      old_thread_state = GetInternalEventThreadRefcount(event, target) > 0;
      if (mode == JVMTI_ENABLE) {
        new_state = IncrInternalEventRefcount(event) > 0;
        new_thread_state = IncrInternalEventThreadRefcount(event, target) > 0;
      } else {
        new_state = DecrInternalEventRefcount(event) > 0;
        new_thread_state = DecrInternalEventThreadRefcount(event, target) > 0;
      }
      if (old_state != new_state) {
        global_mask.Set(event, new_state);
      }
    }
  }
  // Handle any special work required for the event type. We still have the
  // user_code_suspend_count_lock_ so there won't be any interleaving here.
  if (new_state != old_state) {
    HandleEventType(event, mode == JVMTI_ENABLE);
  }
  if (old_thread_state != new_thread_state) {
    HandleEventDeopt(event, thread, new_thread_state);
  }
  return OK;
}

static bool IsDirectlySettableEvent(ArtJvmtiEvent event) {
  return !IsInternalEvent(event);
}

static bool EventIsNormal(ArtJvmtiEvent event) {
  return EventMask::EventIsInRange(event) && IsDirectlySettableEvent(event);
}

jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
                                  jthread thread,
                                  ArtJvmtiEvent event,
                                  jvmtiEventMode mode) {
  if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
    return ERR(ILLEGAL_ARGUMENT);
  }

  if (!EventIsNormal(event)) {
    return ERR(INVALID_EVENT_TYPE);
  }

  if (!HasAssociatedCapability(env, event)) {
    return ERR(MUST_POSSESS_CAPABILITY);
  }

  if (thread != nullptr && !IsThreadControllable(event)) {
    return ERR(ILLEGAL_ARGUMENT);
  }

  art::Thread* self = art::Thread::Current();
  art::Thread* target = nullptr;
  ScopedNoUserCodeSuspension snucs(self);
  // The overall state across all threads and jvmtiEnvs. This is used to control the state of the
  // instrumentation handlers since we only want each added once.
  bool old_state;
  bool new_state;
  // The state for just the current 'thread' (including null) across all jvmtiEnvs. This is used to
  // control the deoptimization state since we do refcounting for that and need to perform different
  // actions depending on if the event is limited to a single thread or global.
  bool old_thread_state;
  bool new_thread_state;
  {
    // From now on we know we cannot get suspended by user-code.
    // NB This does a SuspendCheck (during thread state change) so we need to
    // make sure we don't have the 'suspend_lock' locked here.
    art::ScopedObjectAccess soa(self);
    art::WriterMutexLock el_mu(self, envs_lock_);
    art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
    jvmtiError err = ERR(INTERNAL);
    if (thread != nullptr) {
      if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) {
        return err;
      } else if (target->IsStillStarting() ||
                target->GetState() == art::ThreadState::kStarting) {
        target->Dump(LOG_STREAM(WARNING) << "Is not alive: ");
        return ERR(THREAD_NOT_ALIVE);
      }
    }


    art::WriterMutexLock ei_mu(self, env->event_info_mutex_);
    old_thread_state = GetThreadEventState(event, target);
    old_state = global_mask.Test(event);
    if (mode == JVMTI_ENABLE) {
      env->event_masks.EnableEvent(env, target, event);
      global_mask.Set(event);
      new_state = true;
      new_thread_state = true;
      DCHECK(GetThreadEventState(event, target));
    } else {
      DCHECK_EQ(mode, JVMTI_DISABLE);

      env->event_masks.DisableEvent(env, target, event);
      RecalculateGlobalEventMaskLocked(event);
      new_state = global_mask.Test(event);
      new_thread_state = GetThreadEventState(event, target);
      DCHECK(new_state || !new_thread_state);
    }
  }
  // Handle any special work required for the event type. We still have the
  // user_code_suspend_count_lock_ so there won't be any interleaving here.
  if (new_state != old_state) {
    HandleEventType(event, mode == JVMTI_ENABLE);
  }
  if (old_thread_state != new_thread_state) {
    return HandleEventDeopt(event, thread, new_thread_state);
  }
  return OK;
}

bool EventHandler::GetThreadEventState(ArtJvmtiEvent event, art::Thread* thread) {
  for (ArtJvmTiEnv* stored_env : envs) {
    if (stored_env == nullptr) {
      continue;
    }
    auto& masks = stored_env->event_masks;
    if (thread == nullptr && masks.global_event_mask.Test(event)) {
      return true;
    } else if (thread != nullptr) {
      EventMask* mask =  masks.GetEventMaskOrNull(thread);
      if (mask != nullptr && mask->Test(event)) {
        return true;
      }
    }
  }
  return false;
}

void EventHandler::HandleBreakpointEventsChanged(bool added) {
  if (added) {
    DeoptManager::Get()->AddDeoptimizationRequester();
  } else {
    DeoptManager::Get()->RemoveDeoptimizationRequester();
  }
}

void EventHandler::AddDelayedNonStandardExitEvent(const art::ShadowFrame *frame,
                                                  bool is_object,
                                                  jvalue val) {
  method_trace_listener_->AddDelayedNonStandardExitEvent(frame, is_object, val);
}

static size_t GetInternalEventIndex(ArtJvmtiEvent event) {
  CHECK(IsInternalEvent(event));
  return static_cast<size_t>(event) - static_cast<size_t>(ArtJvmtiEvent::kMinInternalEventTypeVal);
}

int32_t EventHandler::DecrInternalEventThreadRefcount(ArtJvmtiEvent event, art::Thread* target) {
  return --GetInternalEventThreadRefcount(event, target);
}

int32_t EventHandler::IncrInternalEventThreadRefcount(ArtJvmtiEvent event, art::Thread* target) {
  return ++GetInternalEventThreadRefcount(event, target);
}

int32_t& EventHandler::GetInternalEventThreadRefcount(ArtJvmtiEvent event, art::Thread* target) {
  auto& refs = internal_event_thread_refcount_[GetInternalEventIndex(event)];
  UniqueThread target_ut{target, target->GetTid()};
  if (refs.find(target_ut) == refs.end()) {
    refs.insert({target_ut, 0});
  }
  return refs.at(target_ut);
}

int32_t EventHandler::DecrInternalEventRefcount(ArtJvmtiEvent event) {
  return --internal_event_refcount_[GetInternalEventIndex(event)];
}

int32_t EventHandler::IncrInternalEventRefcount(ArtJvmtiEvent event) {
  return ++internal_event_refcount_[GetInternalEventIndex(event)];
}

int32_t EventHandler::GetInternalEventRefcount(ArtJvmtiEvent event) const {
  return internal_event_refcount_[GetInternalEventIndex(event)];
}

void EventHandler::Shutdown() {
  // Need to remove the method_trace_listener_ if it's there.
  art::Thread* self = art::Thread::Current();
  art::gc::ScopedGCCriticalSection gcs(self,
                                       art::gc::kGcCauseInstrumentation,
                                       art::gc::kCollectorTypeInstrumentation);
  art::ScopedSuspendAll ssa("jvmti method tracing uninstallation");
  // Just remove every possible event.
  art::Runtime::Current()->GetInstrumentation()->RemoveListener(method_trace_listener_.get(), ~0);
}

EventHandler::EventHandler()
  : envs_lock_("JVMTI Environment List Lock", art::LockLevel::kPostMutatorTopLockLevel),
    frame_pop_enabled(false),
    internal_event_refcount_({0}) {
  alloc_listener_.reset(new JvmtiAllocationListener(this));
  ddm_listener_.reset(new JvmtiDdmChunkListener(this));
  gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
  method_trace_listener_.reset(new JvmtiMethodTraceListener(this));
  monitor_listener_.reset(new JvmtiMonitorListener(this));
  park_listener_.reset(new JvmtiParkListener(this));
}

EventHandler::~EventHandler() {
}

}  // namespace openjdkjvmti
