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 <iosfwd>
37 #include <unordered_map>
38 
39 #include "base/mutex.h"
40 #include "runtime_callbacks.h"
41 
42 #include <jvmti.h>
43 
44 namespace art {
45 class ArtMethod;
46 class ScopedObjectAccessUnchecked;
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:
JvmtiMethodInspectionCallbackJvmtiMethodInspectionCallback58   explicit JvmtiMethodInspectionCallback(DeoptManager* manager) : manager_(manager) {}
59 
60   bool HaveLocalsChanged() override REQUIRES_SHARED(art::Locks::mutator_lock_);
61 
62  private:
63   DeoptManager* manager_;
64 };
65 
66 class ScopedDeoptimizationContext;
67 
68 class DeoptManager {
69  public:
70   DeoptManager();
71 
72   void Setup();
73   void Shutdown();
74 
75   void DumpDeoptInfo(art::Thread* self, std::ostream& stream);
76 
77   void RemoveDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
78                                                 !art::Roles::uninterruptible_);
79   void AddDeoptimizationRequester() REQUIRES(!deoptimization_status_lock_,
80                                              !art::Roles::uninterruptible_);
81   bool MethodHasBreakpoints(art::ArtMethod* method)
82       REQUIRES(!deoptimization_status_lock_);
83 
84   void RemoveMethodBreakpoint(art::ArtMethod* method)
85       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
86       REQUIRES_SHARED(art::Locks::mutator_lock_);
87 
88   void AddMethodBreakpoint(art::ArtMethod* method)
89       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
90       REQUIRES_SHARED(art::Locks::mutator_lock_);
91 
92   void AddDeoptimizeAllMethods()
93       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
94       REQUIRES_SHARED(art::Locks::mutator_lock_);
95 
96   void RemoveDeoptimizeAllMethods()
97       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
98       REQUIRES_SHARED(art::Locks::mutator_lock_);
99 
100   jvmtiError AddDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
101       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
102       REQUIRES_SHARED(art::Locks::mutator_lock_);
103 
104   jvmtiError RemoveDeoptimizeThreadMethods(art::ScopedObjectAccessUnchecked& soa, jthread thread)
105       REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_)
106       REQUIRES_SHARED(art::Locks::mutator_lock_);
107 
108   void DeoptimizeThread(art::Thread* target)
109       REQUIRES(!art::Locks::thread_list_lock_)
110       REQUIRES_SHARED(art::Locks::mutator_lock_);
111   void DeoptimizeAllThreads() REQUIRES_SHARED(art::Locks::mutator_lock_);
112 
113   void FinishSetup() REQUIRES(!deoptimization_status_lock_, !art::Roles::uninterruptible_);
114 
115   static DeoptManager* Get();
116 
HaveLocalsChanged()117   bool HaveLocalsChanged() const {
118     return set_local_variable_called_.load();
119   }
120 
SetLocalsUpdated()121   void SetLocalsUpdated() {
122     set_local_variable_called_.store(true);
123   }
124 
125  private:
126   bool MethodHasBreakpointsLocked(art::ArtMethod* method)
127       REQUIRES(breakpoint_status_lock_);
128 
129   // Wait until nothing is currently in the middle of deoptimizing/undeoptimizing something. This is
130   // needed to ensure that everything is synchronized since threads need to drop the
131   // deoptimization_status_lock_ while deoptimizing methods.
132   void WaitForDeoptimizationToFinish(art::Thread* self)
133       RELEASE(deoptimization_status_lock_) REQUIRES(!art::Locks::mutator_lock_);
134 
135   void WaitForDeoptimizationToFinishLocked(art::Thread* self)
136       REQUIRES(deoptimization_status_lock_, !art::Locks::mutator_lock_);
137 
138   void AddDeoptimizeAllMethodsLocked(art::Thread* self)
139       RELEASE(deoptimization_status_lock_)
140       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
141 
142   void RemoveDeoptimizeAllMethodsLocked(art::Thread* self)
143       RELEASE(deoptimization_status_lock_)
144       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
145 
146   void PerformGlobalDeoptimization(art::Thread* self)
147       RELEASE(deoptimization_status_lock_)
148       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
149 
150   void PerformGlobalUndeoptimization(art::Thread* self)
151       RELEASE(deoptimization_status_lock_)
152       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
153 
154   void PerformLimitedDeoptimization(art::Thread* self, art::ArtMethod* method)
155       RELEASE(deoptimization_status_lock_)
156       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
157 
158   void PerformLimitedUndeoptimization(art::Thread* self, art::ArtMethod* method)
159       RELEASE(deoptimization_status_lock_)
160       REQUIRES(!art::Roles::uninterruptible_, !art::Locks::mutator_lock_);
161 
162   static constexpr const char* kDeoptManagerInstrumentationKey = "JVMTI_DeoptManager";
163 
164   art::Mutex deoptimization_status_lock_ ACQUIRED_BEFORE(art::Locks::classlinker_classes_lock_);
165   art::ConditionVariable deoptimization_condition_ GUARDED_BY(deoptimization_status_lock_);
166   bool performing_deoptimization_ GUARDED_BY(deoptimization_status_lock_);
167 
168   // Number of times we have gotten requests to deopt everything.
169   uint32_t global_deopt_count_ GUARDED_BY(deoptimization_status_lock_);
170 
171   // Number of users of deoptimization there currently are.
172   uint32_t deopter_count_ GUARDED_BY(deoptimization_status_lock_);
173 
174   // A mutex that just protects the breakpoint-status map. This mutex should always be at the
175   // bottom of the lock hierarchy. Nothing more should be locked if we hold this.
176   art::Mutex breakpoint_status_lock_ ACQUIRED_BEFORE(art::Locks::abort_lock_);
177   // A map from methods to the number of breakpoints in them from all envs.
178   std::unordered_map<art::ArtMethod*, uint32_t> breakpoint_status_
179       GUARDED_BY(breakpoint_status_lock_);
180 
181   // The MethodInspectionCallback we use to tell the runtime if we care about particular methods.
182   JvmtiMethodInspectionCallback inspection_callback_;
183 
184   // Set to true if anything calls SetLocalVariables on any thread since we need to be careful about
185   // OSR after this.
186   std::atomic<bool> set_local_variable_called_;
187 
188   // Helper for setting up/tearing-down for deoptimization.
189   friend class ScopedDeoptimizationContext;
190 };
191 
192 }  // namespace openjdkjvmti
193 #endif  // ART_OPENJDKJVMTI_DEOPT_MANAGER_H_
194