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