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