1 /*
  2  * Copyright (c) 1997, 2021, 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/vmOperation.hpp"
 30 #include "runtime/thread.hpp"
 31 #include "runtime/threadSMR.hpp"
 32 
 33 // A hodge podge of commonly used VM Operations
 34 
 35 class VM_None: public VM_Operation {
 36   const char* _reason;
 37  public:
 38   VM_None(const char* reason) : _reason(reason) {}
 39   const char* name() const { return _reason; }
 40   VMOp_Type type() const { return VMOp_None; }
 41   void doit() {};
 42 };
 43 
 44 class VM_Cleanup: public VM_Operation {
 45  public:
 46   VMOp_Type type() const { return VMOp_Cleanup; }
 47   void doit() {};
 48 };
 49 
 50 class VM_ClearICs: public VM_Operation {
 51  private:
 52   bool _preserve_static_stubs;
 53  public:
 54   VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; }
 55   void doit();
 56   VMOp_Type type() const { return VMOp_ClearICs; }
 57 };
 58 
 59 // empty vm op, evaluated just to force a safepoint
 60 class VM_ForceSafepoint: public VM_Operation {
 61  public:
 62   void doit()         {}
 63   VMOp_Type type() const { return VMOp_ForceSafepoint; }
 64 };
 65 
 66 // empty vm op, when forcing a safepoint to suspend a thread
 67 class VM_ThreadSuspend: public VM_ForceSafepoint {
 68  public:
 69   VMOp_Type type() const { return VMOp_ThreadSuspend; }
 70 };
 71 
 72 // empty vm op, when forcing a safepoint to suspend threads from jvmti
 73 class VM_ThreadsSuspendJVMTI: public VM_ForceSafepoint {
 74  public:
 75   VMOp_Type type() const { return VMOp_ThreadsSuspendJVMTI; }
 76 };
 77 
 78 // empty vm op, when forcing a safepoint due to inline cache buffers being full
 79 class VM_ICBufferFull: public VM_ForceSafepoint {
 80  public:
 81   VMOp_Type type() const { return VMOp_ICBufferFull; }
 82   virtual bool skip_thread_oop_barriers() const { return true; }
 83 };
 84 
 85 // Base class for invoking parts of a gtest in a safepoint.
 86 // Derived classes provide the doit method.
 87 // Typically also need to transition the gtest thread from native to VM.
 88 class VM_GTestExecuteAtSafepoint: public VM_Operation {
 89  public:
 90   VMOp_Type type() const                         { return VMOp_GTestExecuteAtSafepoint; }
 91 
 92  protected:
 93   VM_GTestExecuteAtSafepoint() {}
 94 };
 95 
 96 class VM_CleanClassLoaderDataMetaspaces : public VM_Operation {
 97  public:
 98   VM_CleanClassLoaderDataMetaspaces() {}
 99   VMOp_Type type() const                         { return VMOp_CleanClassLoaderDataMetaspaces; }
100   void doit();
101 };
102 
103 // Deopt helper that can deoptimize frames in threads other than the
104 // current thread.  Only used through Deoptimization::deoptimize_frame.
105 class VM_DeoptimizeFrame: public VM_Operation {
106   friend class Deoptimization;
107 
108  private:
109   JavaThread* _thread;
110   intptr_t*   _id;
111   int _reason;
112   VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
113 
114  public:
115   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
116   void doit();
117   bool allow_nested_vm_operations() const        { return true;  }
118 };
119 
120 #ifndef PRODUCT
121 class VM_DeoptimizeAll: public VM_Operation {
122  private:
123   Klass* _dependee;
124  public:
125   VM_DeoptimizeAll() {}
126   VMOp_Type type() const                         { return VMOp_DeoptimizeAll; }
127   void doit();
128   bool allow_nested_vm_operations() const        { return true; }
129 };
130 
131 
132 class VM_ZombieAll: public VM_Operation {
133  public:
134   VM_ZombieAll() {}
135   VMOp_Type type() const                         { return VMOp_ZombieAll; }
136   void doit();
137   bool allow_nested_vm_operations() const        { return true; }
138 };
139 #endif // PRODUCT
140 
141 class VM_PrintThreads: public VM_Operation {
142  private:
143   outputStream* _out;
144   bool _print_concurrent_locks;
145   bool _print_extended_info;
146   bool _print_jni_handle_info;
147  public:
148   VM_PrintThreads()
149     : _out(tty), _print_concurrent_locks(PrintConcurrentLocks), _print_extended_info(false), _print_jni_handle_info(false)
150   {}
151   VM_PrintThreads(outputStream* out, bool print_concurrent_locks, bool print_extended_info, bool print_jni_handle_info)
152     : _out(out), _print_concurrent_locks(print_concurrent_locks), _print_extended_info(print_extended_info),
153       _print_jni_handle_info(print_jni_handle_info)
154   {}
155   VMOp_Type type() const {
156     return VMOp_PrintThreads;
157   }
158   void doit();
159   bool doit_prologue();
160   void doit_epilogue();
161 };
162 
163 class VM_PrintMetadata : public VM_Operation {
164  private:
165   outputStream* const _out;
166   const size_t        _scale;
167   const int           _flags;
168 
169  public:
170   VM_PrintMetadata(outputStream* out, size_t scale, int flags)
171     : _out(out), _scale(scale), _flags(flags)
172   {};
173 
174   VMOp_Type type() const  { return VMOp_PrintMetadata; }
175   void doit();
176 };
177 
178 class DeadlockCycle;
179 class VM_FindDeadlocks: public VM_Operation {
180  private:
181   bool              _concurrent_locks;
182   DeadlockCycle*    _deadlocks;
183   outputStream*     _out;
184   ThreadsListSetter _setter;  // Helper to set hazard ptr in the originating thread
185                               // which protects the JavaThreads in _deadlocks.
186 
187  public:
188   VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _deadlocks(NULL), _out(NULL), _setter() {};
189   VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _deadlocks(NULL), _out(st) {};
190   ~VM_FindDeadlocks();
191 
192   DeadlockCycle* result()      { return _deadlocks; };
193   VMOp_Type type() const       { return VMOp_FindDeadlocks; }
194   void doit();
195 };
196 
197 class ThreadDumpResult;
198 class ThreadSnapshot;
199 class ThreadConcurrentLocks;
200 
201 class VM_ThreadDump : public VM_Operation {
202  private:
203   ThreadDumpResult*              _result;
204   int                            _num_threads;
205   GrowableArray<instanceHandle>* _threads;
206   int                            _max_depth;
207   bool                           _with_locked_monitors;
208   bool                           _with_locked_synchronizers;
209 
210   void snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
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 #if INCLUDE_SERVICES
266 class VM_PrintClassHierarchy: public VM_Operation {
267  private:
268   outputStream* _out;
269   bool _print_interfaces;
270   bool _print_subclasses;
271   char* _classname;
272 
273  public:
274   VM_PrintClassHierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) :
275     _out(st), _print_interfaces(print_interfaces), _print_subclasses(print_subclasses),
276     _classname(classname) {}
277   VMOp_Type type() const { return VMOp_PrintClassHierarchy; }
278   void doit();
279 };
280 #endif // INCLUDE_SERVICES
281 
282 #endif // SHARE_RUNTIME_VMOPERATIONS_HPP