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