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 class VM_ClearICs: public VM_Operation { 64 private: 65 bool _preserve_static_stubs; 66 public: 67 VM_ClearICs(bool preserve_static_stubs) { _preserve_static_stubs = preserve_static_stubs; } 68 void doit(); 69 VMOp_Type type() const { return VMOp_ClearICs; } 70 }; 71 72 // Base class for invoking parts of a gtest in a safepoint. 73 // Derived classes provide the doit method. 74 // Typically also need to transition the gtest thread from native to VM. 75 class VM_GTestExecuteAtSafepoint: public VM_Operation { 76 public: 77 VMOp_Type type() const { return VMOp_GTestExecuteAtSafepoint; } 78 79 protected: 80 VM_GTestExecuteAtSafepoint() {} 81 }; 82 83 class VM_CleanClassLoaderDataMetaspaces : public VM_Operation { 84 public: 85 VM_CleanClassLoaderDataMetaspaces() {} 86 VMOp_Type type() const { return VMOp_CleanClassLoaderDataMetaspaces; } 87 void doit(); 88 }; 89 90 class VM_RehashStringTable : public VM_Operation { 91 public: 92 VM_RehashStringTable() {} 93 VMOp_Type type() const { return VMOp_RehashStringTable; } 94 void doit(); 95 }; 96 97 class VM_RehashSymbolTable : public VM_Operation { 98 public: 99 VM_RehashSymbolTable() {} 100 VMOp_Type type() const { return VMOp_RehashSymbolTable; } 101 void doit(); 102 }; 103 104 // Deopt helper that can deoptimize frames in threads other than the 105 // current thread. Only used through Deoptimization::deoptimize_frame. 106 class VM_DeoptimizeFrame: public VM_Operation { 107 friend class Deoptimization; 108 109 private: 110 JavaThread* _thread; 111 intptr_t* _id; 112 int _reason; 113 VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason); 114 115 public: 116 VMOp_Type type() const { return VMOp_DeoptimizeFrame; } 117 void doit(); 118 bool allow_nested_vm_operations() const { return true; } 119 }; 120 121 #ifndef PRODUCT 122 class VM_DeoptimizeAll: public VM_Operation { 123 public: 124 VM_DeoptimizeAll() {} 125 VMOp_Type type() const { return VMOp_DeoptimizeAll; } 126 void doit(); 127 bool allow_nested_vm_operations() const { return true; } 128 }; 129 130 131 class VM_ZombieAll: public VM_Operation { 132 public: 133 VM_ZombieAll() {} 134 VMOp_Type type() const { return VMOp_ZombieAll; } 135 void doit(); 136 bool allow_nested_vm_operations() const { return true; } 137 }; 138 #endif // PRODUCT 139 140 class VM_PrintThreads: public VM_Operation { 141 private: 142 outputStream* _out; 143 bool _print_concurrent_locks; 144 bool _print_extended_info; 145 bool _print_jni_handle_info; 146 public: 147 VM_PrintThreads() 148 : _out(tty), _print_concurrent_locks(PrintConcurrentLocks), _print_extended_info(false), _print_jni_handle_info(false) 149 {} 150 VM_PrintThreads(outputStream* out, bool print_concurrent_locks, bool print_extended_info, bool print_jni_handle_info) 151 : _out(out), _print_concurrent_locks(print_concurrent_locks), _print_extended_info(print_extended_info), 152 _print_jni_handle_info(print_jni_handle_info) 153 {} 154 VMOp_Type type() const { 155 return VMOp_PrintThreads; 156 } 157 void doit(); 158 bool doit_prologue(); 159 void doit_epilogue(); 160 }; 161 162 class VM_PrintMetadata : public VM_Operation { 163 private: 164 outputStream* const _out; 165 const size_t _scale; 166 const int _flags; 167 168 public: 169 VM_PrintMetadata(outputStream* out, size_t scale, int flags) 170 : _out(out), _scale(scale), _flags(flags) 171 {}; 172 173 VMOp_Type type() const { return VMOp_PrintMetadata; } 174 void doit(); 175 }; 176 177 class DeadlockCycle; 178 class VM_FindDeadlocks: public VM_Operation { 179 private: 180 bool _concurrent_locks; 181 DeadlockCycle* _deadlocks; 182 outputStream* _out; 183 ThreadsListSetter _setter; // Helper to set hazard ptr in the originating thread 184 // which protects the JavaThreads in _deadlocks. 185 186 public: 187 VM_FindDeadlocks(bool concurrent_locks) : _concurrent_locks(concurrent_locks), _deadlocks(nullptr), _out(nullptr), _setter() {}; 188 VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _deadlocks(nullptr), _out(st) {}; 189 ~VM_FindDeadlocks(); 190 191 DeadlockCycle* result() { return _deadlocks; }; 192 VMOp_Type type() const { return VMOp_FindDeadlocks; } 193 void doit(); 194 }; 195 196 class ThreadDumpResult; 197 class ThreadSnapshot; 198 class ThreadConcurrentLocks; 199 200 class VM_ThreadDump : public VM_Operation { 201 private: 202 ThreadDumpResult* _result; 203 int _num_threads; 204 GrowableArray<instanceHandle>* _threads; 205 int _max_depth; 206 bool _with_locked_monitors; 207 bool _with_locked_synchronizers; 208 209 void snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl, 210 ObjectMonitorsView* monitors); 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 class VM_PrintClassLayout: public VM_Operation { 266 private: 267 outputStream* _out; 268 char* _class_name; 269 public: 270 VM_PrintClassLayout(outputStream* st, char* class_name): _out(st), _class_name(class_name) {} 271 VMOp_Type type() const { return VMOp_PrintClassHierarchy; } 272 void doit(); 273 }; 274 275 #if INCLUDE_SERVICES 276 class VM_PrintClassHierarchy: public VM_Operation { 277 private: 278 outputStream* _out; 279 bool _print_interfaces; 280 bool _print_subclasses; 281 char* _classname; 282 283 public: 284 VM_PrintClassHierarchy(outputStream* st, bool print_interfaces, bool print_subclasses, char* classname) : 285 _out(st), _print_interfaces(print_interfaces), _print_subclasses(print_subclasses), 286 _classname(classname) {} 287 VMOp_Type type() const { return VMOp_PrintClassHierarchy; } 288 void doit(); 289 }; 290 #endif // INCLUDE_SERVICES 291 292 #endif // SHARE_RUNTIME_VMOPERATIONS_HPP