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:
VM_None(const char * reason)38   VM_None(const char* reason) : _reason(reason) {}
name() const39   const char* name() const { return _reason; }
type() const40   VMOp_Type type() const { return VMOp_None; }
doit()41   void doit() {};
42 };
43 
44 class VM_Cleanup: public VM_Operation {
45  public:
type() const46   VMOp_Type type() const { return VMOp_Cleanup; }
doit()47   void doit() {};
48 };
49 
50 class VM_ClearICs: public VM_Operation {
51  private:
52   bool _preserve_static_stubs;
53  public:
VM_ClearICs(bool preserve_static_stubs)54   VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; }
55   void doit();
type() const56   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:
doit()62   void doit()         {}
type() const63   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:
type() const69   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:
type() const75   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:
type() const81   VMOp_Type type() const { return VMOp_ICBufferFull; }
skip_thread_oop_barriers() const82   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:
type() const90   VMOp_Type type() const                         { return VMOp_GTestExecuteAtSafepoint; }
91 
92  protected:
VM_GTestExecuteAtSafepoint()93   VM_GTestExecuteAtSafepoint() {}
94 };
95 
96 class VM_CleanClassLoaderDataMetaspaces : public VM_Operation {
97  public:
VM_CleanClassLoaderDataMetaspaces()98   VM_CleanClassLoaderDataMetaspaces() {}
type() const99   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:
type() const115   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
116   void doit();
allow_nested_vm_operations() const117   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:
VM_DeoptimizeAll()125   VM_DeoptimizeAll() {}
type() const126   VMOp_Type type() const                         { return VMOp_DeoptimizeAll; }
127   void doit();
allow_nested_vm_operations() const128   bool allow_nested_vm_operations() const        { return true; }
129 };
130 
131 
132 class VM_ZombieAll: public VM_Operation {
133  public:
VM_ZombieAll()134   VM_ZombieAll() {}
type() const135   VMOp_Type type() const                         { return VMOp_ZombieAll; }
136   void doit();
allow_nested_vm_operations() const137   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  public:
VM_PrintThreads()147   VM_PrintThreads()
148     : _out(tty), _print_concurrent_locks(PrintConcurrentLocks), _print_extended_info(false)
149   {}
VM_PrintThreads(outputStream * out,bool print_concurrent_locks,bool print_extended_info)150   VM_PrintThreads(outputStream* out, bool print_concurrent_locks, bool print_extended_info)
151     : _out(out), _print_concurrent_locks(print_concurrent_locks), _print_extended_info(print_extended_info)
152   {}
type() const153   VMOp_Type type() const {
154     return VMOp_PrintThreads;
155   }
156   void doit();
157   bool doit_prologue();
158   void doit_epilogue();
159 };
160 
161 class VM_PrintJNI: public VM_Operation {
162  private:
163   outputStream* _out;
164  public:
VM_PrintJNI()165   VM_PrintJNI()                         { _out = tty; }
VM_PrintJNI(outputStream * out)166   VM_PrintJNI(outputStream* out)        { _out = out; }
type() const167   VMOp_Type type() const                { return VMOp_PrintJNI; }
168   void doit();
169 };
170 
171 class VM_PrintMetadata : public VM_Operation {
172  private:
173   outputStream* const _out;
174   const size_t        _scale;
175   const int           _flags;
176 
177  public:
VM_PrintMetadata(outputStream * out,size_t scale,int flags)178   VM_PrintMetadata(outputStream* out, size_t scale, int flags)
179     : _out(out), _scale(scale), _flags(flags)
180   {};
181 
type() const182   VMOp_Type type() const  { return VMOp_PrintMetadata; }
183   void doit();
184 };
185 
186 class DeadlockCycle;
187 class VM_FindDeadlocks: public VM_Operation {
188  private:
189   bool              _concurrent_locks;
190   DeadlockCycle*    _deadlocks;
191   outputStream*     _out;
192   ThreadsListSetter _setter;  // Helper to set hazard ptr in the originating thread
193                               // which protects the JavaThreads in _deadlocks.
194 
195  public:
VM_FindDeadlocks(bool concurrent_locks)196   VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _deadlocks(NULL), _out(NULL), _setter() {};
VM_FindDeadlocks(outputStream * st)197   VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _deadlocks(NULL), _out(st) {};
198   ~VM_FindDeadlocks();
199 
result()200   DeadlockCycle* result()      { return _deadlocks; };
type() const201   VMOp_Type type() const       { return VMOp_FindDeadlocks; }
202   void doit();
203 };
204 
205 class ThreadDumpResult;
206 class ThreadSnapshot;
207 class ThreadConcurrentLocks;
208 
209 class VM_ThreadDump : public VM_Operation {
210  private:
211   ThreadDumpResult*              _result;
212   int                            _num_threads;
213   GrowableArray<instanceHandle>* _threads;
214   int                            _max_depth;
215   bool                           _with_locked_monitors;
216   bool                           _with_locked_synchronizers;
217 
218   void snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
219 
220  public:
221   VM_ThreadDump(ThreadDumpResult* result,
222                 int max_depth,  // -1 indicates entire stack
223                 bool with_locked_monitors,
224                 bool with_locked_synchronizers);
225 
226   VM_ThreadDump(ThreadDumpResult* result,
227                 GrowableArray<instanceHandle>* threads,
228                 int num_threads, // -1 indicates entire stack
229                 int max_depth,
230                 bool with_locked_monitors,
231                 bool with_locked_synchronizers);
232 
type() const233   VMOp_Type type() const { return VMOp_ThreadDump; }
234   void doit();
235   bool doit_prologue();
236   void doit_epilogue();
237 };
238 
239 
240 class VM_Exit: public VM_Operation {
241  private:
242   int  _exit_code;
243   static volatile bool _vm_exited;
244   static Thread * volatile _shutdown_thread;
245   static void wait_if_vm_exited();
246  public:
VM_Exit(int exit_code)247   VM_Exit(int exit_code) {
248     _exit_code = exit_code;
249   }
250   static int wait_for_threads_in_native_to_block();
251   static int set_vm_exited();
vm_exited()252   static bool vm_exited()                      { return _vm_exited; }
shutdown_thread()253   static Thread * shutdown_thread()            { return _shutdown_thread; }
block_if_vm_exited()254   static void block_if_vm_exited() {
255     if (_vm_exited) {
256       wait_if_vm_exited();
257     }
258   }
type() const259   VMOp_Type type() const { return VMOp_Exit; }
260   void doit();
261 };
262 
263 class VM_PrintCompileQueue: public VM_Operation {
264  private:
265   outputStream* _out;
266 
267  public:
VM_PrintCompileQueue(outputStream * st)268   VM_PrintCompileQueue(outputStream* st) : _out(st) {}
type() const269   VMOp_Type type() const { return VMOp_PrintCompileQueue; }
270   void doit();
271 };
272 
273 #if INCLUDE_SERVICES
274 class VM_PrintClassHierarchy: public VM_Operation {
275  private:
276   outputStream* _out;
277   bool _print_interfaces;
278   bool _print_subclasses;
279   char* _classname;
280 
281  public:
VM_PrintClassHierarchy(outputStream * st,bool print_interfaces,bool print_subclasses,char * classname)282   VM_PrintClassHierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) :
283     _out(st), _print_interfaces(print_interfaces), _print_subclasses(print_subclasses),
284     _classname(classname) {}
type() const285   VMOp_Type type() const { return VMOp_PrintClassHierarchy; }
286   void doit();
287 };
288 #endif // INCLUDE_SERVICES
289 
290 #endif // SHARE_RUNTIME_VMOPERATIONS_HPP
291