events.cc revision 73afd322e0e55ec4cda570cc240e1f22db215851
177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe/* Copyright (C) 2016 The Android Open Source Project
277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * This file implements interfaces from the file jvmti.h. This implementation
577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * is licensed under the same terms as the file jvmti.h.  The
677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * copyright and license information for the file jvmti.h follows.
777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
1177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * This code is free software; you can redistribute it and/or modify it
1277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * under the terms of the GNU General Public License version 2 only, as
1377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * published by the Free Software Foundation.  Oracle designates this
1477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * particular file as subject to the "Classpath" exception as provided
1577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * by Oracle in the LICENSE file that accompanied this code.
1677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
1777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * This code is distributed in the hope that it will be useful, but WITHOUT
1877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
2077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * version 2 for more details (a copy is included in the LICENSE file that
2177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * accompanied this code).
2277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
2377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * You should have received a copy of the GNU General Public License version
2477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * 2 along with this work; if not, write to the Free Software Foundation,
2577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe *
2777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * or visit www.oracle.com if you need additional information or have any
2977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe * questions.
3077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe */
3177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
3227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "events-inl.h"
3377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
3477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe#include "art_jvmti.h"
3527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "base/logging.h"
3627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "gc/allocation_listener.h"
379b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe#include "gc/gc_pause_listener.h"
389b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe#include "gc/heap.h"
3927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "instrumentation.h"
4027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "jni_env_ext-inl.h"
4127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "mirror/class.h"
4227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "mirror/object.h"
4327fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "runtime.h"
4427fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe#include "ScopedLocalRef.h"
45c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe#include "scoped_thread_state_change-inl.h"
46c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe#include "thread-inl.h"
4777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
4877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampenamespace openjdkjvmti {
4977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
5073afd322e0e55ec4cda570cc240e1f22db215851Alex Lightbool EventMasks::IsEnabledAnywhere(ArtJvmtiEvent event) {
5173afd322e0e55ec4cda570cc240e1f22db215851Alex Light  return global_event_mask.Test(event) || unioned_thread_event_mask.Test(event);
5273afd322e0e55ec4cda570cc240e1f22db215851Alex Light}
5373afd322e0e55ec4cda570cc240e1f22db215851Alex Light
5477708d9149b0a00247eb69ea4d5386cae4e40287Andreas GampeEventMask& EventMasks::GetEventMask(art::Thread* thread) {
5577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (thread == nullptr) {
5677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    return global_event_mask;
5777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
5877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
5977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  for (auto& pair : thread_event_masks) {
6077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    const UniqueThread& unique_thread = pair.first;
6177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    if (unique_thread.first == thread &&
6277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
6377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return pair.second;
6477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    }
6577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
6677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
6777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  // TODO: Remove old UniqueThread with the same pointer, if exists.
6877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
6977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  thread_event_masks.emplace_back(UniqueThread(thread, thread->GetTid()), EventMask());
7077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  return thread_event_masks.back().second;
7177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
7277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
7377708d9149b0a00247eb69ea4d5386cae4e40287Andreas GampeEventMask* EventMasks::GetEventMaskOrNull(art::Thread* thread) {
7477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (thread == nullptr) {
7577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    return &global_event_mask;
7677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
7777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
7877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  for (auto& pair : thread_event_masks) {
7977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    const UniqueThread& unique_thread = pair.first;
8077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    if (unique_thread.first == thread &&
8177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe        unique_thread.second == static_cast<uint32_t>(thread->GetTid())) {
8277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return &pair.second;
8377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    }
8477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
8577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
8677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  return nullptr;
8777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
8877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
8977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
9040d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Lightvoid EventMasks::EnableEvent(art::Thread* thread, ArtJvmtiEvent event) {
9177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  DCHECK(EventMask::EventIsInRange(event));
9277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  GetEventMask(thread).Set(event);
9377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (thread != nullptr) {
9477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    unioned_thread_event_mask.Set(event, true);
9577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
9677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
9777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
9840d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Lightvoid EventMasks::DisableEvent(art::Thread* thread, ArtJvmtiEvent event) {
9977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  DCHECK(EventMask::EventIsInRange(event));
10077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  GetEventMask(thread).Set(event, false);
10177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (thread != nullptr) {
10277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    // Regenerate union for the event.
10377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    bool union_value = false;
10477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    for (auto& pair : thread_event_masks) {
10577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      union_value |= pair.second.Test(event);
10677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      if (union_value) {
10777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe        break;
10877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      }
10977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    }
11077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    unioned_thread_event_mask.Set(event, union_value);
11177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
11277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
11377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
11473afd322e0e55ec4cda570cc240e1f22db215851Alex Lightvoid EventMasks::HandleChangedCapabilities(const jvmtiCapabilities& caps, bool caps_added) {
11573afd322e0e55ec4cda570cc240e1f22db215851Alex Light  if (UNLIKELY(caps.can_retransform_classes == 1)) {
11673afd322e0e55ec4cda570cc240e1f22db215851Alex Light    // If we are giving this env the retransform classes cap we need to switch all events of
11773afd322e0e55ec4cda570cc240e1f22db215851Alex Light    // NonTransformable to Transformable and vice versa.
11873afd322e0e55ec4cda570cc240e1f22db215851Alex Light    ArtJvmtiEvent to_remove = caps_added ? ArtJvmtiEvent::kClassFileLoadHookNonRetransformable
11973afd322e0e55ec4cda570cc240e1f22db215851Alex Light                                         : ArtJvmtiEvent::kClassFileLoadHookRetransformable;
12073afd322e0e55ec4cda570cc240e1f22db215851Alex Light    ArtJvmtiEvent to_add = caps_added ? ArtJvmtiEvent::kClassFileLoadHookRetransformable
12173afd322e0e55ec4cda570cc240e1f22db215851Alex Light                                      : ArtJvmtiEvent::kClassFileLoadHookNonRetransformable;
12273afd322e0e55ec4cda570cc240e1f22db215851Alex Light    if (global_event_mask.Test(to_remove)) {
12373afd322e0e55ec4cda570cc240e1f22db215851Alex Light      CHECK(!global_event_mask.Test(to_add));
12473afd322e0e55ec4cda570cc240e1f22db215851Alex Light      global_event_mask.Set(to_remove, false);
12573afd322e0e55ec4cda570cc240e1f22db215851Alex Light      global_event_mask.Set(to_add, true);
12673afd322e0e55ec4cda570cc240e1f22db215851Alex Light    }
12773afd322e0e55ec4cda570cc240e1f22db215851Alex Light
12873afd322e0e55ec4cda570cc240e1f22db215851Alex Light    if (unioned_thread_event_mask.Test(to_remove)) {
12973afd322e0e55ec4cda570cc240e1f22db215851Alex Light      CHECK(!unioned_thread_event_mask.Test(to_add));
13073afd322e0e55ec4cda570cc240e1f22db215851Alex Light      unioned_thread_event_mask.Set(to_remove, false);
13173afd322e0e55ec4cda570cc240e1f22db215851Alex Light      unioned_thread_event_mask.Set(to_add, true);
13273afd322e0e55ec4cda570cc240e1f22db215851Alex Light    }
13373afd322e0e55ec4cda570cc240e1f22db215851Alex Light    for (auto thread_mask : thread_event_masks) {
13473afd322e0e55ec4cda570cc240e1f22db215851Alex Light      if (thread_mask.second.Test(to_remove)) {
13573afd322e0e55ec4cda570cc240e1f22db215851Alex Light        CHECK(!thread_mask.second.Test(to_add));
13673afd322e0e55ec4cda570cc240e1f22db215851Alex Light        thread_mask.second.Set(to_remove, false);
13773afd322e0e55ec4cda570cc240e1f22db215851Alex Light        thread_mask.second.Set(to_add, true);
13873afd322e0e55ec4cda570cc240e1f22db215851Alex Light      }
13973afd322e0e55ec4cda570cc240e1f22db215851Alex Light    }
14073afd322e0e55ec4cda570cc240e1f22db215851Alex Light  }
14173afd322e0e55ec4cda570cc240e1f22db215851Alex Light}
14273afd322e0e55ec4cda570cc240e1f22db215851Alex Light
14377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampevoid EventHandler::RegisterArtJvmTiEnv(ArtJvmTiEnv* env) {
14477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  envs.push_back(env);
14577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
14677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
14740d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Lightstatic bool IsThreadControllable(ArtJvmtiEvent event) {
14877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  switch (event) {
14940d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kVmInit:
15040d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kVmStart:
15140d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kVmDeath:
15240d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kThreadStart:
15340d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kCompiledMethodLoad:
15440d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kCompiledMethodUnload:
15540d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kDynamicCodeGenerated:
15640d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kDataDumpRequest:
15777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return false;
15877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
15977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    default:
16077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return true;
16177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
16277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
16377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
16427fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampeclass JvmtiAllocationListener : public art::gc::AllocationListener {
16527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe public:
16627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  explicit JvmtiAllocationListener(EventHandler* handler) : handler_(handler) {}
16727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
1689d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier  void ObjectAllocated(art::Thread* self, art::ObjPtr<art::mirror::Object>* obj, size_t byte_count)
1699b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_) {
17027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe    DCHECK_EQ(self, art::Thread::Current());
17127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
17240d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    if (handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kVmObjectAlloc)) {
173a7118041322c99e5c951a8ec5dcedb7b1a96ba19Mathieu Chartier      art::StackHandleScope<1> hs(self);
174a7118041322c99e5c951a8ec5dcedb7b1a96ba19Mathieu Chartier      auto h = hs.NewHandleWrapper(obj);
17527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      // jvmtiEventVMObjectAlloc parameters:
17627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      jvmtiEnv *jvmti_env,
17727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      JNIEnv* jni_env,
17827fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      jthread thread,
17927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      jobject object,
18027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      jclass object_klass,
18127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      //      jlong size
18227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      art::JNIEnvExt* jni_env = self->GetJniEnv();
18327fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
18427fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      jthread thread_peer;
18527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      if (self->IsStillStarting()) {
18627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe        thread_peer = nullptr;
18727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      } else {
18827fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe        thread_peer = jni_env->AddLocalReference<jthread>(self->GetPeer());
18927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      }
19027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
19127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      ScopedLocalRef<jthread> thread(jni_env, thread_peer);
19227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      ScopedLocalRef<jobject> object(
19327fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe          jni_env, jni_env->AddLocalReference<jobject>(*obj));
19427fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      ScopedLocalRef<jclass> klass(
1959d156d500801accee919b6d51e22d6ddcdcd4a05Mathieu Chartier          jni_env, jni_env->AddLocalReference<jclass>(obj->Ptr()->GetClass()));
19627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
19727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe      handler_->DispatchEvent(self,
19840d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light                              ArtJvmtiEvent::kVmObjectAlloc,
19927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe                              jni_env,
20027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe                              thread.get(),
20127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe                              object.get(),
20227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe                              klass.get(),
20327fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe                              byte_count);
20427fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe    }
20527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  }
20627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
20727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe private:
20827fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  EventHandler* handler_;
20927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe};
21027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
21127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampestatic void SetupObjectAllocationTracking(art::gc::AllocationListener* listener, bool enable) {
212c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe  // We must not hold the mutator lock here, but if we're in FastJNI, for example, we might. For
213c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe  // now, do a workaround: (possibly) acquire and release.
214c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe  art::ScopedObjectAccess soa(art::Thread::Current());
215c02685c18904d41424942c956258a527f7b20bb0Andreas Gampe  art::ScopedThreadSuspension sts(soa.Self(), art::ThreadState::kSuspended);
21627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  if (enable) {
21727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe    art::Runtime::Current()->GetHeap()->SetAllocationListener(listener);
21827fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  } else {
21927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe    art::Runtime::Current()->GetHeap()->RemoveAllocationListener();
22027fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  }
22127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe}
22227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
2239b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe// Report GC pauses (see spec) as GARBAGE_COLLECTION_START and GARBAGE_COLLECTION_END.
2249b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampeclass JvmtiGcPauseListener : public art::gc::GcPauseListener {
2259b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe public:
2269b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  explicit JvmtiGcPauseListener(EventHandler* handler)
2279b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      : handler_(handler),
2289b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe        start_enabled_(false),
2299b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe        finish_enabled_(false) {}
2309b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2319b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  void StartPause() OVERRIDE {
23240d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    handler_->DispatchEvent(nullptr, ArtJvmtiEvent::kGarbageCollectionStart);
2339b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2349b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2359b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  void EndPause() OVERRIDE {
23640d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    handler_->DispatchEvent(nullptr, ArtJvmtiEvent::kGarbageCollectionFinish);
2379b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2389b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2399b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  bool IsEnabled() {
2409b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    return start_enabled_ || finish_enabled_;
2419b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2429b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2439b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  void SetStartEnabled(bool e) {
2449b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    start_enabled_ = e;
2459b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2469b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2479b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  void SetFinishEnabled(bool e) {
2489b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    finish_enabled_ = e;
2499b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2509b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2519b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe private:
2529b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  EventHandler* handler_;
2539b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  bool start_enabled_;
2549b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  bool finish_enabled_;
2559b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe};
2569b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
25740d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Lightstatic void SetupGcPauseTracking(JvmtiGcPauseListener* listener, ArtJvmtiEvent event, bool enable) {
2589b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  bool old_state = listener->IsEnabled();
2599b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
26040d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light  if (event == ArtJvmtiEvent::kGarbageCollectionStart) {
2619b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    listener->SetStartEnabled(enable);
2629b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  } else {
2639b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    listener->SetFinishEnabled(enable);
2649b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2659b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2669b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  bool new_state = listener->IsEnabled();
2679b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2689b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  if (old_state != new_state) {
2699b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    if (new_state) {
2709b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      art::Runtime::Current()->GetHeap()->SetGcPauseListener(listener);
2719b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    } else {
2729b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      art::Runtime::Current()->GetHeap()->RemoveGcPauseListener();
2739b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    }
2749b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  }
2759b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe}
2769b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
27777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe// Handle special work for the given event type, if necessary.
27840d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Lightvoid EventHandler::HandleEventType(ArtJvmtiEvent event, bool enable) {
2799b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  switch (event) {
28040d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kVmObjectAlloc:
2819b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      SetupObjectAllocationTracking(alloc_listener_.get(), enable);
2829b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      return;
2839b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
28440d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kGarbageCollectionStart:
28540d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light    case ArtJvmtiEvent::kGarbageCollectionFinish:
2869b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      SetupGcPauseTracking(gc_pause_listener_.get(), event, enable);
2879b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      return;
2889b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe
2899b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe    default:
2909b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe      break;
29127fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  }
29277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
29377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
29477708d9149b0a00247eb69ea4d5386cae4e40287Andreas GampejvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
29577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe                                  art::Thread* thread,
29640d87f450e6c1d38edd539405d4e79e4c64ad7c6Alex Light                                  ArtJvmtiEvent event,
29777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe                                  jvmtiEventMode mode) {
29877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (thread != nullptr) {
29977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    art::ThreadState state = thread->GetState();
30077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    if (state == art::ThreadState::kStarting ||
30177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe        state == art::ThreadState::kTerminated ||
30277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe        thread->IsStillStarting()) {
30377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return ERR(THREAD_NOT_ALIVE);
30477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    }
30577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    if (!IsThreadControllable(event)) {
30677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe      return ERR(ILLEGAL_ARGUMENT);
30777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    }
30877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
30977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
31077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  // TODO: Capability check.
31177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
31277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
31377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    return ERR(ILLEGAL_ARGUMENT);
31477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
31577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
31677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (!EventMask::EventIsInRange(event)) {
31777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    return ERR(INVALID_EVENT_TYPE);
31877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
31977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
3208b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe  bool old_state = global_mask.Test(event);
3218b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe
32277708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  if (mode == JVMTI_ENABLE) {
32377708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    env->event_masks.EnableEvent(thread, event);
32477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    global_mask.Set(event);
32577708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  } else {
32677708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    DCHECK_EQ(mode, JVMTI_DISABLE);
32777708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
32877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe    env->event_masks.DisableEvent(thread, event);
32973afd322e0e55ec4cda570cc240e1f22db215851Alex Light    RecalculateGlobalEventMask(event);
33077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  }
33177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
3328b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe  bool new_state = global_mask.Test(event);
3338b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe
33477708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  // Handle any special work required for the event type.
3358b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe  if (new_state != old_state) {
3368b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe    HandleEventType(event, mode == JVMTI_ENABLE);
3378b862ffa7ea7374e48329ae090c68c06a8c885bbAndreas Gampe  }
33877708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
33977708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe  return ERR(NONE);
34077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}
34177708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe
34227fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas GampeEventHandler::EventHandler() {
34327fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe  alloc_listener_.reset(new JvmtiAllocationListener(this));
3449b8c5880de9b0f7dd8b1b863520714a9700a8dc2Andreas Gampe  gc_pause_listener_.reset(new JvmtiGcPauseListener(this));
34527fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe}
34627fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
34727fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas GampeEventHandler::~EventHandler() {
34827fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe}
34927fa96c285c4aa2f64e9bb63a3f38ffdc98c282aAndreas Gampe
35077708d9149b0a00247eb69ea4d5386cae4e40287Andreas Gampe}  // namespace openjdkjvmti
351