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