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