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 class VM_ClearICs: public VM_Operation {
 64  private:
 65   bool _preserve_static_stubs;
 66  public:
 67   VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; }
 68   void doit();
 69   VMOp_Type type() const { return VMOp_ClearICs; }
 70 };
 71 
 72 // Base class for invoking parts of a gtest in a safepoint.
 73 // Derived classes provide the doit method.
 74 // Typically also need to transition the gtest thread from native to VM.
 75 class VM_GTestExecuteAtSafepoint: public VM_Operation {
 76  public:
 77   VMOp_Type type() const                         { return VMOp_GTestExecuteAtSafepoint; }
 78 
 79  protected:
 80   VM_GTestExecuteAtSafepoint() {}
 81 };
 82 
 83 class VM_CleanClassLoaderDataMetaspaces : public VM_Operation {
 84  public:
 85   VM_CleanClassLoaderDataMetaspaces() {}
 86   VMOp_Type type() const                         { return VMOp_CleanClassLoaderDataMetaspaces; }
 87   void doit();
 88 };
 89 
 90 class VM_RehashStringTable : public VM_Operation {
 91  public:
 92   VM_RehashStringTable() {}
 93   VMOp_Type type() const                         { return VMOp_RehashStringTable; }
 94   void doit();
 95 };
 96 
 97 class VM_RehashSymbolTable : public VM_Operation {
 98  public:
 99   VM_RehashSymbolTable() {}
100   VMOp_Type type() const                         { return VMOp_RehashSymbolTable; }
101   void doit();
102 };
103 
104 // Deopt helper that can deoptimize frames in threads other than the
105 // current thread.  Only used through Deoptimization::deoptimize_frame.
106 class VM_DeoptimizeFrame: public VM_Operation {
107   friend class Deoptimization;
108 
109  private:
110   JavaThread* _thread;
111   intptr_t*   _id;
112   int _reason;
113   VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
114 
115  public:
116   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
117   void doit();
118   bool allow_nested_vm_operations() const        { return true;  }
119 };
120 
121 #ifndef PRODUCT
122 class VM_DeoptimizeAll: public VM_Operation {
123  public:
124   VM_DeoptimizeAll() {}
125   VMOp_Type type() const                         { return VMOp_DeoptimizeAll; }
126   void doit();
127   bool allow_nested_vm_operations() const        { return true; }
128 };
129 
130 
131 class VM_ZombieAll: public VM_Operation {
132  public:
133   VM_ZombieAll() {}
134   VMOp_Type type() const                         { return VMOp_ZombieAll; }
135   void doit();
136   bool allow_nested_vm_operations() const        { return true; }
137 };
138 #endif // PRODUCT
139 
140 class VM_PrintThreads: public VM_Operation {
141  private:
142   outputStream* _out;
143   bool _print_concurrent_locks;
144   bool _print_extended_info;
145   bool _print_jni_handle_info;
146  public:
147   VM_PrintThreads()
148     : _out(tty), _print_concurrent_locks(PrintConcurrentLocks), _print_extended_info(false), _print_jni_handle_info(false)
149   {}
150   VM_PrintThreads(outputStream* out, bool print_concurrent_locks, bool print_extended_info, bool print_jni_handle_info)
151     : _out(out), _print_concurrent_locks(print_concurrent_locks), _print_extended_info(print_extended_info),
152       _print_jni_handle_info(print_jni_handle_info)
153   {}
154   VMOp_Type type() const {
155     return VMOp_PrintThreads;
156   }
157   void doit();
158   bool doit_prologue();
159   void doit_epilogue();
160 };
161 
162 class VM_PrintMetadata : public VM_Operation {
163  private:
164   outputStream* const _out;
165   const size_t        _scale;
166   const int           _flags;
167 
168  public:
169   VM_PrintMetadata(outputStream* out, size_t scale, int flags)
170     : _out(out), _scale(scale), _flags(flags)
171   {};
172 
173   VMOp_Type type() const  { return VMOp_PrintMetadata; }
174   void doit();
175 };
176 
177 class DeadlockCycle;
178 class VM_FindDeadlocks: public VM_Operation {
179  private:
180   bool              _concurrent_locks;
181   DeadlockCycle*    _deadlocks;
182   outputStream*     _out;
183   ThreadsListSetter _setter;  // Helper to set hazard ptr in the originating thread
184                               // which protects the JavaThreads in _deadlocks.
185 
186  public:
187   VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _deadlocks(nullptr), _out(nullptr), _setter() {};
188   VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _deadlocks(nullptr), _out(st) {};
189   ~VM_FindDeadlocks();
190 
191   DeadlockCycle* result()      { return _deadlocks; };
192   VMOp_Type type() const       { return VMOp_FindDeadlocks; }
193   void doit();
194 };
195 
196 class ThreadDumpResult;
197 class ThreadSnapshot;
198 class ThreadConcurrentLocks;
199 
200 class VM_ThreadDump : public VM_Operation {
201  private:
202   ThreadDumpResult*              _result;
203   int                            _num_threads;
204   GrowableArray<instanceHandle>* _threads;
205   int                            _max_depth;
206   bool                           _with_locked_monitors;
207   bool                           _with_locked_synchronizers;
208 
209   void snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl,
210                        ObjectMonitorsView* monitors);
211 
212  public:
213   VM_ThreadDump(ThreadDumpResult* result,
214                 int max_depth,  // -1 indicates entire stack
215                 bool with_locked_monitors,
216                 bool with_locked_synchronizers);
217 
218   VM_ThreadDump(ThreadDumpResult* result,
219                 GrowableArray<instanceHandle>* threads,
220                 int num_threads, // -1 indicates entire stack
221                 int max_depth,
222                 bool with_locked_monitors,
223                 bool with_locked_synchronizers);
224 
225   VMOp_Type type() const { return VMOp_ThreadDump; }
226   void doit();
227   bool doit_prologue();
228   void doit_epilogue();
229 };
230 
231 
232 class VM_Exit: public VM_Operation {
233  private:
234   int  _exit_code;
235   static volatile bool _vm_exited;
236   static Thread * volatile _shutdown_thread;
237   static void wait_if_vm_exited();
238  public:
239   VM_Exit(int exit_code) {
240     _exit_code = exit_code;
241   }
242   static int wait_for_threads_in_native_to_block();
243   static int set_vm_exited();
244   static bool vm_exited()                      { return _vm_exited; }
245   static Thread * shutdown_thread()            { return _shutdown_thread; }
246   static void block_if_vm_exited() {
247     if (_vm_exited) {
248       wait_if_vm_exited();
249     }
250   }
251   VMOp_Type type() const { return VMOp_Exit; }
252   void doit();
253 };
254 
255 class VM_PrintCompileQueue: public VM_Operation {
256  private:
257   outputStream* _out;
258 
259  public:
260   VM_PrintCompileQueue(outputStream* st) : _out(st) {}
261   VMOp_Type type() const { return VMOp_PrintCompileQueue; }
262   void doit();
263 };
264 
265 class VM_PrintClassLayout: public VM_Operation {
266  private:
267   outputStream* _out;
268   char* _class_name;
269  public:
270   VM_PrintClassLayout(outputStream* st, char* class_name): _out(st), _class_name(class_name) {}
271   VMOp_Type type() const { return VMOp_PrintClassHierarchy; }
272   void doit();
273 };
274 
275 #if INCLUDE_SERVICES
276 class VM_PrintClassHierarchy: public VM_Operation {
277  private:
278   outputStream* _out;
279   bool _print_interfaces;
280   bool _print_subclasses;
281   char* _classname;
282 
283  public:
284   VM_PrintClassHierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) :
285     _out(st), _print_interfaces(print_interfaces), _print_subclasses(print_subclasses),
286     _classname(classname) {}
287   VMOp_Type type() const { return VMOp_PrintClassHierarchy; }
288   void doit();
289 };
290 #endif // INCLUDE_SERVICES
291 
292 #endif // SHARE_RUNTIME_VMOPERATIONS_HPP