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