Home | History | Annotate | Download | only in openjdkjvmti
      1 /* Copyright (C) 2017 The Android Open Source Project
      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      3  *
      4  * This file implements interfaces from the file jvmti.h. This implementation
      5  * is licensed under the same terms as the file jvmti.h.  The
      6  * copyright and license information for the file jvmti.h follows.
      7  *
      8  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
      9  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     10  *
     11  * This code is free software; you can redistribute it and/or modify it
     12  * under the terms of the GNU General Public License version 2 only, as
     13  * published by the Free Software Foundation.  Oracle designates this
     14  * particular file as subject to the "Classpath" exception as provided
     15  * by Oracle in the LICENSE file that accompanied this code.
     16  *
     17  * This code is distributed in the hope that it will be useful, but WITHOUT
     18  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     20  * version 2 for more details (a copy is included in the LICENSE file that
     21  * accompanied this code).
     22  *
     23  * You should have received a copy of the GNU General Public License version
     24  * 2 along with this work; if not, write to the Free Software Foundation,
     25  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     26  *
     27  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     28  * or visit www.oracle.com if you need additional information or have any
     29  * questions.
     30  */
     31 
     32 #ifndef ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
     33 #define ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
     34 
     35 #include <atomic>
     36 #include <unordered_map>
     37 
     38 #include "jni.h"
     39 #include "jvmti.h"
     40 
     41 #include "base/mutex.h"
     42 #include "runtime_callbacks.h"
     43 #include "ti_breakpoint.h"
     44 
     45 namespace art {
     46 class ArtMethod;
     47 namespace mirror {
     48 class Class;
     49 }  // namespace mirror
     50 }  // namespace art
     51 
     52 namespace openjdkjvmti {
     53 
     54 class DeoptManager;
     55 
     56 struct JvmtiMethodInspectionCallback : public art::MethodInspectionCallback {
     57  public:
     58   explicit JvmtiMethodInspectionCallback(DeoptManager* manager) : manager_(manager) {}
     59 
     60   bool IsMethodBeingInspected(art::ArtMethod* method)
     61       OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_);
     62 
     63   bool IsMethodSafeToJit(art::ArtMethod* method)
     64       OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_);
     65 
     66   bool MethodNeedsDebugVersion(art::ArtMethod* method)
     67       OVERRIDE REQUIRES_SHARED(art::Locks::mutator_lock_);
     68 
     69  private:
     70   DeoptManager* manager_;
     71 };
     72 
     73 class ScopedDeoptimizationContext;
     74 
     75 class DeoptManager {
     76  public:
     77   DeoptManager();
     78 
     79   void Setup();
     80   void Shutdown();
     81 
     82   void RemoveDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
     83                                                 !art::Roles::uninterruptible_);
     84   void AddDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
     85                                              !art::Roles::uninterruptible_);
     86   bool MethodHasBreakpoints(art::ArtMethod* method)
     87       REQUIRES(!deoptimization_status_lock_);
     88 
     89   void RemoveMethodBreakpoint(art::ArtMethod* method)
     90       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
     91       REQUIRES_SHARED(art::Locks::mutator_lock_);
     92 
     93   void AddMethodBreakpoint(art::ArtMethod* method)
     94       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
     95       REQUIRES_SHARED(art::Locks::mutator_lock_);
     96 
     97   void AddDeoptimizeAllMethods()
     98       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
     99       REQUIRES_SHARED(art::Locks::mutator_lock_);
    100 
    101   void RemoveDeoptimizeAllMethods()
    102       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
    103       REQUIRES_SHARED(art::Locks::mutator_lock_);
    104 
    105   void DeoptimizeThread(art::Thread* target) REQUIRES_SHARED(art::Locks::mutator_lock_);
    106   void DeoptimizeAllThreads() REQUIRES_SHARED(art::Locks::mutator_lock_);
    107 
    108   void FinishSetup()
    109       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
    110       REQUIRES_SHARED(art::Locks::mutator_lock_);
    111 
    112   static DeoptManager* Get();
    113 
    114   bool HaveLocalsChanged() const {
    115     return set_local_variable_called_.load();
    116   }
    117 
    118   void SetLocalsUpdated() {
    119     set_local_variable_called_.store(true);
    120   }
    121 
    122  private:
    123   bool MethodHasBreakpointsLocked(art::ArtMethod* method)
    124       REQUIRES(breakpoint_status_lock_);
    125 
    126   // Wait until nothing is currently in the middle of deoptimizing/undeoptimizing something. This is
    127   // needed to ensure that everything is synchronized since threads need to drop the
    128   // deoptimization_status_lock_ while deoptimizing methods.
    129   void WaitForDeoptimizationToFinish(art::Thread* self)
    130       RELEASE(deoptimization_status_lock_) REQUIRES(!art::Locks::mutator_lock_);
    131 
    132   void WaitForDeoptimizationToFinishLocked(art::Thread* self)
    133       REQUIRES(deoptimization_status_lock_, !art::Locks::mutator_lock_);
    134 
    135   void AddDeoptimizeAllMethodsLocked(art::Thread* self)
    136       RELEASE(deoptimization_status_lock_)
    137       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    138 
    139   void RemoveDeoptimizeAllMethodsLocked(art::Thread* self)
    140       RELEASE(deoptimization_status_lock_)
    141       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    142 
    143   void PerformGlobalDeoptimization(art::Thread* self)
    144       RELEASE(deoptimization_status_lock_)
    145       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    146 
    147   void PerformGlobalUndeoptimization(art::Thread* self)
    148       RELEASE(deoptimization_status_lock_)
    149       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    150 
    151   void PerformLimitedDeoptimization(art::Thread* self, art::ArtMethod* method)
    152       RELEASE(deoptimization_status_lock_)
    153       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    154 
    155   void PerformLimitedUndeoptimization(art::Thread* self, art::ArtMethod* method)
    156       RELEASE(deoptimization_status_lock_)
    157       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
    158 
    159   static constexpr const char* kDeoptManagerInstrumentationKey = "JVMTI_DeoptManager";
    160 
    161   art::Mutex deoptimization_status_lock_ ACQUIRED_BEFORE(art::Locks::classlinker_classes_lock_);
    162   art::ConditionVariable deoptimization_condition_ GUARDED_BY(deoptimization_status_lock_);
    163   bool performing_deoptimization_ GUARDED_BY(deoptimization_status_lock_);
    164 
    165   // Number of times we have gotten requests to deopt everything.
    166   uint32_t global_deopt_count_ GUARDED_BY(deoptimization_status_lock_);
    167 
    168   // Number of users of deoptimization there currently are.
    169   uint32_t deopter_count_ GUARDED_BY(deoptimization_status_lock_);
    170 
    171   // A mutex that just protects the breakpoint-status map. This mutex should always be at the
    172   // bottom of the lock hierarchy. Nothing more should be locked if we hold this.
    173   art::Mutex breakpoint_status_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_);
    174   // A map from methods to the number of breakpoints in them from all envs.
    175   std::unordered_map<art::ArtMethod*, uint32_t> breakpoint_status_
    176       GUARDED_BY(breakpoint_status_lock_);
    177 
    178   // The MethodInspectionCallback we use to tell the runtime if we care about particular methods.
    179   JvmtiMethodInspectionCallback inspection_callback_;
    180 
    181   // Set to true if anything calls SetLocalVariables on any thread since we need to be careful about
    182   // OSR after this.
    183   std::atomic<bool> set_local_variable_called_;
    184 
    185   // Helper for setting up/tearing-down for deoptimization.
    186   friend class ScopedDeoptimizationContext;
    187 };
    188 
    189 }  // namespace openjdkjvmti
    190 #endif  // ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
    191