1 /*
  2  * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_RUNTIME_VMOPERATIONS_HPP
 26 #define SHARE_RUNTIME_VMOPERATIONS_HPP
 27 
 28 #include "oops/oop.hpp"
 29 #include "runtime/javaThread.hpp"
 30 #include "runtime/vmOperation.hpp"
 31 #include "runtime/threadSMR.hpp"
 32 
 33 class ObjectMonitorsView;
 34 
 35 // A hodge podge of commonly used VM Operations
 36 
 37 class VM_EmptyOperation : public VM_Operation {
 38 public:
 39   virtual void doit() final {}
 40   virtual bool skip_thread_oop_barriers() const final {
 41     // Neither the doit function nor the safepoint
 42     // cleanup tasks read oops in the Java threads.
 43     return true;
 44   }
 45 };
 46 
 47 class VM_Halt: public VM_EmptyOperation {
 48  public:
 49   VMOp_Type type() const { return VMOp_Halt; }
 50 };
 51 
 52 class VM_SafepointALot: public VM_EmptyOperation {
 53  public:
 54   VMOp_Type type() const { return VMOp_SafepointALot; }
 55 };
 56 
 57 // empty vm op, evaluated just to force a safepoint
 58 class VM_ForceSafepoint: public VM_EmptyOperation {
 59  public:
 60   VMOp_Type type() const { return VMOp_ForceSafepoint; }
 61 };
 62 
 63 // used by whitebox API to emulate VM issues
 64 // when VM can't operate and doesn't respond to jcmd
 65 class VM_HangInSafepoint: public VM_Operation {
 66 public:
 67   VMOp_Type type() const { return VMOp_ForceSafepoint; }
 68   void doit() {
 69     while(true) {
 70       os::naked_short_sleep(10);
 71     }
 72   }
 73 };
 74 
 75 class VM_ClearICs: public VM_Operation {
 76  private:
 77   bool _preserve_static_stubs;
 78  public:
 79   VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; }
 80   void doit();
 81   VMOp_Type type() const { return VMOp_ClearICs; }
 82 };
 83 
 84 // Base class for invoking parts of a gtest in a safepoint.
 85 // Derived classes provide the doit method.
 86 // Typically also need to transition the gtest thread from native to VM.
 87 class VM_GTestExecuteAtSafepoint: public VM_Operation {
 88  public:
 89   VMOp_Type type() const                         { return VMOp_GTestExecuteAtSafepoint; }
 90 
 91  protected:
 92   VM_GTestExecuteAtSafepoint() {}
 93 };
 94 
 95 class VM_CleanClassLoaderDataMetaspaces : public VM_Operation {
 96  public:
 97   VM_CleanClassLoaderDataMetaspaces() {}
 98   VMOp_Type type() const                         { return VMOp_CleanClassLoaderDataMetaspaces; }
 99   void doit();
100 };
101 
102 class VM_RehashStringTable : public VM_Operation {
103  public:
104   VM_RehashStringTable() {}
105   VMOp_Type type() const                         { return VMOp_RehashStringTable; }
106   void doit();
107 };
108 
109 class VM_RehashSymbolTable : public VM_Operation {
110  public:
111   VM_RehashSymbolTable() {}
112   VMOp_Type type() const                         { return VMOp_RehashSymbolTable; }
113   void doit();
114 };
115 
116 // Deopt helper that can deoptimize frames in threads other than the
117 // current thread.  Only used through Deoptimization::deoptimize_frame.
118 class VM_DeoptimizeFrame: public VM_Operation {
119   friend class Deoptimization;
120 
121  private:
122   JavaThread* _thread;
123   intptr_t*   _id;
124   int _reason;
125   VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
126 
127  public:
128   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
129   void doit();
130   bool allow_nested_vm_operations() const        { return true;  }
131 };
132 
133 #ifndef PRODUCT
134 class VM_DeoptimizeAll: public VM_Operation {
135  public:
136   VM_DeoptimizeAll() {}
137   VMOp_Type type() const                         { return VMOp_DeoptimizeAll; }
138   void doit();
139   bool allow_nested_vm_operations() const        { return true; }
140 };
141 
142 
143 class VM_ZombieAll: public VM_Operation {
144  public:
145   VM_ZombieAll() {}
146   VMOp_Type type() const                         { return VMOp_ZombieAll; }
147   void doit();
148   bool allow_nested_vm_operations() const        { return true; }
149 };
150 #endif // PRODUCT
151 
152 class VM_PrintThreads: public VM_Operation {
153  private:
154   outputStream* _out;
155   bool _print_concurrent_locks;
156   bool _print_extended_info;
157   bool _print_jni_handle_info;
158  public:
159   VM_PrintThreads()
160     : _out(tty), _print_concurrent_locks(PrintConcurrentLocks), _print_extended_info(false), _print_jni_handle_info(false)
161   {}
162   VM_PrintThreads(outputStream* out, bool print_concurrent_locks, bool print_extended_info, bool print_jni_handle_info)
163     : _out(out), _print_concurrent_locks(print_concurrent_locks), _print_extended_info(print_extended_info),
164       _print_jni_handle_info(print_jni_handle_info)
165   {}
166   VMOp_Type type() const {
167     return VMOp_PrintThreads;
168   }
169   void doit();
170   bool doit_prologue();
171   void doit_epilogue();
172 };
173 
174 class VM_PrintMetadata : public VM_Operation {
175  private:
176   outputStream* const _out;
177   const size_t        _scale;
178   const int           _flags;
179 
180  public:
181   VM_PrintMetadata(outputStream* out, size_t scale, int flags)
182     : _out(out), _scale(scale), _flags(flags)
183   {};
184 
185   VMOp_Type type() const  { return VMOp_PrintMetadata; }
186   void doit();
187 };
188 
189 class DeadlockCycle;
190 class VM_FindDeadlocks: public VM_Operation {
191  private:
192   bool              _concurrent_locks;
193   DeadlockCycle*    _deadlocks;
194   outputStream*     _out;
195   ThreadsListSetter _setter;  // Helper to set hazard ptr in the originating thread
196                               // which protects the JavaThreads in _deadlocks.
197 
198  public:
199   VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _deadlocks(nullptr), _out(nullptr), _setter() {};
200   VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _deadlocks(nullptr), _out(st) {};
201   ~VM_FindDeadlocks();
202 
203   DeadlockCycle* result()      { return _deadlocks; };
204   VMOp_Type type() const       { return VMOp_FindDeadlocks; }
205   void doit();
206 };
207 
208 class ThreadDumpResult;
209 class ThreadSnapshot;
210 class ThreadConcurrentLocks;
211 
212 class VM_ThreadDump : public VM_Operation {
213  private:
214   ThreadDumpResult*              _result;
215   int                            _num_threads;
216   GrowableArray<instanceHandle>* _threads;
217   int                            _max_depth;
218   bool                           _with_locked_monitors;
219   bool                           _with_locked_synchronizers;
220 
221   void snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl,
222                        ObjectMonitorsView* monitors);
223 
224  public:
225   VM_ThreadDump(ThreadDumpResult* result,
226                 int max_depth,  // -1 indicates entire stack
227                 bool with_locked_monitors,
228                 bool with_locked_synchronizers);
229 
230   VM_ThreadDump(ThreadDumpResult* result,
231                 GrowableArray<instanceHandle>* threads,
232                 int num_threads, // -1 indicates entire stack
233                 int max_depth,
234                 bool with_locked_monitors,
235                 bool with_locked_synchronizers);
236 
237   VMOp_Type type() const { return VMOp_ThreadDump; }
238   void doit();
239   bool doit_prologue();
240   void doit_epilogue();
241 };
242 
243 
244 class VM_Exit: public VM_Operation {
245  private:
246   int  _exit_code;
247   static volatile bool _vm_exited;
248   static Thread * volatile _shutdown_thread;
249   static void wait_if_vm_exited();
250  public:
251   VM_Exit(int exit_code) {
252     _exit_code = exit_code;
253   }
254   static int wait_for_threads_in_native_to_block();
255   static int set_vm_exited();
256   static bool vm_exited()                      { return _vm_exited; }
257   static Thread * shutdown_thread()            { return _shutdown_thread; }
258   static void block_if_vm_exited() {
259     if (_vm_exited) {
260       wait_if_vm_exited();
261     }
262   }
263   VMOp_Type type() const { return VMOp_Exit; }
264   void doit();
265 };
266 
267 class VM_PrintCompileQueue: public VM_Operation {
268  private:
269   outputStream* _out;
270 
271  public:
272   VM_PrintCompileQueue(outputStream* st) : _out(st) {}
273   VMOp_Type type() const { return VMOp_PrintCompileQueue; }
274   void doit();
275 };
276 
277 #if INCLUDE_SERVICES
278 class VM_PrintClassHierarchy: public VM_Operation {
279  private:
280   outputStream* _out;
281   bool _print_interfaces;
282   bool _print_subclasses;
283   char* _classname;
284 
285  public:
286   VM_PrintClassHierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) :
287     _out(st), _print_interfaces(print_interfaces), _print_subclasses(print_subclasses),
288     _classname(classname) {}
289   VMOp_Type type() const { return VMOp_PrintClassHierarchy; }
290   void doit();
291 };
292 #endif // INCLUDE_SERVICES
293 
294 #endif // SHARE_RUNTIME_VMOPERATIONS_HPP