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