• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
JvmtiMethodInspectionCallbackJvmtiMethodInspectionCallback58   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 
HaveLocalsChanged()114   bool HaveLocalsChanged() const {
115     return set_local_variable_called_.load();
116   }
117 
SetLocalsUpdated()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