/* Copyright (C) 2017 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. */ #ifndef ART_OPENJDKJVMTI_DEOPT_MANAGER_H_ #define ART_OPENJDKJVMTI_DEOPT_MANAGER_H_ #include #include "jni.h" #include "jvmti.h" #include "base/mutex.h" #include "runtime_callbacks.h" #include "ti_breakpoint.h" namespace art { class ArtMethod; namespace mirror { class Class; } // namespace mirror } // namespace art namespace openjdkjvmti { class DeoptManager; struct JvmtiMethodInspectionCallback : public art::MethodInspectionCallback { public: explicit JvmtiMethodInspectionCallback(DeoptManager* manager) : manager_(manager) {} bool IsMethodBeingInspected(art::ArtMethod* method) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_); bool IsMethodSafeToJit(art::ArtMethod* method) OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_); private: DeoptManager* manager_; }; class ScopedDeoptimizationContext; class DeoptManager { public: DeoptManager(); void Setup(); void Shutdown(); void RemoveDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_); void AddDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_); bool MethodHasBreakpoints(art::ArtMethod* method) REQUIRES(!deoptimization_status_lock_); void RemoveMethodBreakpoint(art::ArtMethod* method) REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_) REQUIRES_SHARED(art::Locks::mutator_lock_); void AddMethodBreakpoint(art::ArtMethod* method) REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_) REQUIRES_SHARED(art::Locks::mutator_lock_); void AddDeoptimizeAllMethods() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_) REQUIRES_SHARED(art::Locks::mutator_lock_); void RemoveDeoptimizeAllMethods() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_) REQUIRES_SHARED(art::Locks::mutator_lock_); void DeoptimizeThread(art::Thread* target) REQUIRES_SHARED(art::Locks::mutator_lock_); void DeoptimizeAllThreads() REQUIRES_SHARED(art::Locks::mutator_lock_); static DeoptManager* Get(); private: bool MethodHasBreakpointsLocked(art::ArtMethod* method) REQUIRES(deoptimization_status_lock_); // Wait until nothing is currently in the middle of deoptimizing/undeoptimizing something. This is // needed to ensure that everything is synchronized since threads need to drop the // deoptimization_status_lock_ while deoptimizing methods. void WaitForDeoptimizationToFinish(art::Thread* self) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Locks::mutator_lock_); void WaitForDeoptimizationToFinishLocked(art::Thread* self) REQUIRES(deoptimization_status_lock_, !art::Locks::mutator_lock_); void AddDeoptimizeAllMethodsLocked(art::Thread* self) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); void RemoveDeoptimizeAllMethodsLocked(art::Thread* self) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); void PerformGlobalDeoptimization(art::Thread* self) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); void PerformGlobalUndeoptimization(art::Thread* self) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); void PerformLimitedDeoptimization(art::Thread* self, art::ArtMethod* method) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); void PerformLimitedUndeoptimization(art::Thread* self, art::ArtMethod* method) RELEASE(deoptimization_status_lock_) REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_); static constexpr const char* kDeoptManagerInstrumentationKey = "JVMTI_DeoptManager"; // static constexpr const char* kDeoptManagerThreadName = "JVMTI_DeoptManagerWorkerThread"; art::Mutex deoptimization_status_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; art::ConditionVariable deoptimization_condition_ GUARDED_BY(deoptimization_status_lock_); bool performing_deoptimization_ GUARDED_BY(deoptimization_status_lock_); // Number of times we have gotten requests to deopt everything. uint32_t global_deopt_count_ GUARDED_BY(deoptimization_status_lock_); // Number of users of deoptimization there currently are. uint32_t deopter_count_ GUARDED_BY(deoptimization_status_lock_); // A map from methods to the number of breakpoints in them from all envs. std::unordered_map breakpoint_status_ GUARDED_BY(deoptimization_status_lock_); // The MethodInspectionCallback we use to tell the runtime if we care about particular methods. JvmtiMethodInspectionCallback inspection_callback_; // Helper for setting up/tearing-down for deoptimization. friend class ScopedDeoptimizationContext; }; } // namespace openjdkjvmti #endif // ART_OPENJDKJVMTI_DEOPT_MANAGER_H_