1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/runtime/vm_operations.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,366 @@ 1.4 +/* 1.5 + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +// The following classes are used for operations 1.29 +// initiated by a Java thread but that must 1.30 +// take place in the VMThread. 1.31 + 1.32 +#define VM_OP_ENUM(type) VMOp_##type, 1.33 + 1.34 +// Note: When new VM_XXX comes up, add 'XXX' to the template table. 1.35 +#define VM_OPS_DO(template) \ 1.36 + template(Dummy) \ 1.37 + template(ThreadStop) \ 1.38 + template(ThreadDump) \ 1.39 + template(PrintThreads) \ 1.40 + template(FindDeadlocks) \ 1.41 + template(ForceSafepoint) \ 1.42 + template(ForceAsyncSafepoint) \ 1.43 + template(Deoptimize) \ 1.44 + template(DeoptimizeFrame) \ 1.45 + template(DeoptimizeAll) \ 1.46 + template(ZombieAll) \ 1.47 + template(Verify) \ 1.48 + template(PrintJNI) \ 1.49 + template(HeapDumper) \ 1.50 + template(DeoptimizeTheWorld) \ 1.51 + template(GC_HeapInspection) \ 1.52 + template(GenCollectFull) \ 1.53 + template(GenCollectFullConcurrent) \ 1.54 + template(GenCollectForAllocation) \ 1.55 + template(ParallelGCFailedAllocation) \ 1.56 + template(ParallelGCFailedPermanentAllocation) \ 1.57 + template(ParallelGCSystemGC) \ 1.58 + template(CMS_Initial_Mark) \ 1.59 + template(CMS_Final_Remark) \ 1.60 + template(EnableBiasedLocking) \ 1.61 + template(RevokeBias) \ 1.62 + template(BulkRevokeBias) \ 1.63 + template(PopulateDumpSharedSpace) \ 1.64 + template(JNIFunctionTableCopier) \ 1.65 + template(RedefineClasses) \ 1.66 + template(GetOwnedMonitorInfo) \ 1.67 + template(GetObjectMonitorUsage) \ 1.68 + template(GetCurrentContendedMonitor) \ 1.69 + template(GetStackTrace) \ 1.70 + template(GetMultipleStackTraces) \ 1.71 + template(GetAllStackTraces) \ 1.72 + template(GetThreadListStackTraces) \ 1.73 + template(GetFrameCount) \ 1.74 + template(GetFrameLocation) \ 1.75 + template(ChangeBreakpoints) \ 1.76 + template(GetOrSetLocal) \ 1.77 + template(GetCurrentLocation) \ 1.78 + template(EnterInterpOnlyMode) \ 1.79 + template(ChangeSingleStep) \ 1.80 + template(HeapWalkOperation) \ 1.81 + template(HeapIterateOperation) \ 1.82 + template(ReportJavaOutOfMemory) \ 1.83 + template(Exit) \ 1.84 + 1.85 +class VM_Operation: public CHeapObj { 1.86 + public: 1.87 + enum Mode { 1.88 + _safepoint, // blocking, safepoint, vm_op C-heap allocated 1.89 + _no_safepoint, // blocking, no safepoint, vm_op C-Heap allocated 1.90 + _concurrent, // non-blocking, no safepoint, vm_op C-Heap allocated 1.91 + _async_safepoint // non-blocking, safepoint, vm_op C-Heap allocated 1.92 + }; 1.93 + 1.94 + enum VMOp_Type { 1.95 + VM_OPS_DO(VM_OP_ENUM) 1.96 + VMOp_Terminating 1.97 + }; 1.98 + 1.99 + private: 1.100 + Thread* _calling_thread; 1.101 + ThreadPriority _priority; 1.102 + long _timestamp; 1.103 + VM_Operation* _next; 1.104 + VM_Operation* _prev; 1.105 + 1.106 + // The VM operation name array 1.107 + static const char* _names[]; 1.108 + 1.109 + public: 1.110 + VM_Operation() { _calling_thread = NULL; _next = NULL; _prev = NULL; } 1.111 + virtual ~VM_Operation() {} 1.112 + 1.113 + // VM operation support (used by VM thread) 1.114 + Thread* calling_thread() const { return _calling_thread; } 1.115 + ThreadPriority priority() { return _priority; } 1.116 + void set_calling_thread(Thread* thread, ThreadPriority priority); 1.117 + 1.118 + long timestamp() const { return _timestamp; } 1.119 + void set_timestamp(long timestamp) { _timestamp = timestamp; } 1.120 + 1.121 + // Called by VM thread - does in turn invoke doit(). Do not override this 1.122 + void evaluate(); 1.123 + 1.124 + // evaluate() is called by the VMThread and in turn calls doit(). 1.125 + // If the thread invoking VMThread::execute((VM_Operation*) is a JavaThread, 1.126 + // doit_prologue() is called in that thread before transferring control to 1.127 + // the VMThread. 1.128 + // If doit_prologue() returns true the VM operation will proceed, and 1.129 + // doit_epilogue() will be called by the JavaThread once the VM operation 1.130 + // completes. If doit_prologue() returns false the VM operation is cancelled. 1.131 + virtual void doit() = 0; 1.132 + virtual bool doit_prologue() { return true; }; 1.133 + virtual void doit_epilogue() {}; // Note: Not called if mode is: _concurrent 1.134 + 1.135 + // Type test 1.136 + virtual bool is_methodCompiler() const { return false; } 1.137 + 1.138 + // Linking 1.139 + VM_Operation *next() const { return _next; } 1.140 + VM_Operation *prev() const { return _prev; } 1.141 + void set_next(VM_Operation *next) { _next = next; } 1.142 + void set_prev(VM_Operation *prev) { _prev = prev; } 1.143 + 1.144 + // Configuration. Override these appropriatly in subclasses. 1.145 + virtual VMOp_Type type() const = 0; 1.146 + virtual Mode evaluation_mode() const { return _safepoint; } 1.147 + virtual bool allow_nested_vm_operations() const { return false; } 1.148 + virtual bool is_cheap_allocated() const { return false; } 1.149 + virtual void oops_do(OopClosure* f) { /* do nothing */ }; 1.150 + 1.151 + // CAUTION: <don't hang yourself with following rope> 1.152 + // If you override these methods, make sure that the evaluation 1.153 + // of these methods is race-free and non-blocking, since these 1.154 + // methods may be evaluated either by the mutators or by the 1.155 + // vm thread, either concurrently with mutators or with the mutators 1.156 + // stopped. In other words, taking locks is verboten, and if there 1.157 + // are any races in evaluating the conditions, they'd better be benign. 1.158 + virtual bool evaluate_at_safepoint() const { 1.159 + return evaluation_mode() == _safepoint || 1.160 + evaluation_mode() == _async_safepoint; 1.161 + } 1.162 + virtual bool evaluate_concurrently() const { 1.163 + return evaluation_mode() == _concurrent || 1.164 + evaluation_mode() == _async_safepoint; 1.165 + } 1.166 + 1.167 + // Debugging 1.168 + void print_on_error(outputStream* st) const; 1.169 + const char* name() const { return _names[type()]; } 1.170 + static const char* name(int type) { 1.171 + assert(type >= 0 && type < VMOp_Terminating, "invalid VM operation type"); 1.172 + return _names[type]; 1.173 + } 1.174 +#ifndef PRODUCT 1.175 + void print_on(outputStream* st) const { print_on_error(st); } 1.176 +#endif 1.177 +}; 1.178 + 1.179 +class VM_ThreadStop: public VM_Operation { 1.180 + private: 1.181 + oop _thread; // The Thread that the Throwable is thrown against 1.182 + oop _throwable; // The Throwable thrown at the target Thread 1.183 + public: 1.184 + // All oops are passed as JNI handles, since there is no guarantee that a GC might happen before the 1.185 + // VM operation is executed. 1.186 + VM_ThreadStop(oop thread, oop throwable) { 1.187 + _thread = thread; 1.188 + _throwable = throwable; 1.189 + } 1.190 + VMOp_Type type() const { return VMOp_ThreadStop; } 1.191 + oop target_thread() const { return _thread; } 1.192 + oop throwable() const { return _throwable;} 1.193 + void doit(); 1.194 + // We deoptimize if top-most frame is compiled - this might require a C2I adapter to be generated 1.195 + bool allow_nested_vm_operations() const { return true; } 1.196 + Mode evaluation_mode() const { return _async_safepoint; } 1.197 + bool is_cheap_allocated() const { return true; } 1.198 + 1.199 + // GC support 1.200 + void oops_do(OopClosure* f) { 1.201 + f->do_oop(&_thread); f->do_oop(&_throwable); 1.202 + } 1.203 +}; 1.204 + 1.205 +// dummy vm op, evaluated just to force a safepoint 1.206 +class VM_ForceSafepoint: public VM_Operation { 1.207 + public: 1.208 + VM_ForceSafepoint() {} 1.209 + void doit() {} 1.210 + VMOp_Type type() const { return VMOp_ForceSafepoint; } 1.211 +}; 1.212 + 1.213 +// dummy vm op, evaluated just to force a safepoint 1.214 +class VM_ForceAsyncSafepoint: public VM_Operation { 1.215 + public: 1.216 + VM_ForceAsyncSafepoint() {} 1.217 + void doit() {} 1.218 + VMOp_Type type() const { return VMOp_ForceAsyncSafepoint; } 1.219 + Mode evaluation_mode() const { return _async_safepoint; } 1.220 + bool is_cheap_allocated() const { return true; } 1.221 +}; 1.222 + 1.223 +class VM_Deoptimize: public VM_Operation { 1.224 + public: 1.225 + VM_Deoptimize() {} 1.226 + VMOp_Type type() const { return VMOp_Deoptimize; } 1.227 + void doit(); 1.228 + bool allow_nested_vm_operations() const { return true; } 1.229 +}; 1.230 + 1.231 +class VM_DeoptimizeFrame: public VM_Operation { 1.232 + private: 1.233 + JavaThread* _thread; 1.234 + intptr_t* _id; 1.235 + public: 1.236 + VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id); 1.237 + VMOp_Type type() const { return VMOp_DeoptimizeFrame; } 1.238 + void doit(); 1.239 + bool allow_nested_vm_operations() const { return true; } 1.240 +}; 1.241 + 1.242 +#ifndef PRODUCT 1.243 +class VM_DeoptimizeAll: public VM_Operation { 1.244 + private: 1.245 + KlassHandle _dependee; 1.246 + public: 1.247 + VM_DeoptimizeAll() {} 1.248 + VMOp_Type type() const { return VMOp_DeoptimizeAll; } 1.249 + void doit(); 1.250 + bool allow_nested_vm_operations() const { return true; } 1.251 +}; 1.252 + 1.253 + 1.254 +class VM_ZombieAll: public VM_Operation { 1.255 + public: 1.256 + VM_ZombieAll() {} 1.257 + VMOp_Type type() const { return VMOp_ZombieAll; } 1.258 + void doit(); 1.259 + bool allow_nested_vm_operations() const { return true; } 1.260 +}; 1.261 +#endif // PRODUCT 1.262 + 1.263 +class VM_Verify: public VM_Operation { 1.264 + private: 1.265 + KlassHandle _dependee; 1.266 + public: 1.267 + VM_Verify() {} 1.268 + VMOp_Type type() const { return VMOp_Verify; } 1.269 + void doit(); 1.270 +}; 1.271 + 1.272 + 1.273 +class VM_PrintThreads: public VM_Operation { 1.274 + private: 1.275 + outputStream* _out; 1.276 + bool _print_concurrent_locks; 1.277 + public: 1.278 + VM_PrintThreads() { _out = tty; _print_concurrent_locks = PrintConcurrentLocks; } 1.279 + VM_PrintThreads(outputStream* out, bool print_concurrent_locks) { _out = out; _print_concurrent_locks = print_concurrent_locks; } 1.280 + VMOp_Type type() const { return VMOp_PrintThreads; } 1.281 + void doit(); 1.282 + bool doit_prologue(); 1.283 + void doit_epilogue(); 1.284 +}; 1.285 + 1.286 +class VM_PrintJNI: public VM_Operation { 1.287 + private: 1.288 + outputStream* _out; 1.289 + public: 1.290 + VM_PrintJNI() { _out = tty; } 1.291 + VM_PrintJNI(outputStream* out) { _out = out; } 1.292 + VMOp_Type type() const { return VMOp_PrintJNI; } 1.293 + void doit(); 1.294 +}; 1.295 + 1.296 +class DeadlockCycle; 1.297 +class VM_FindDeadlocks: public VM_Operation { 1.298 + private: 1.299 + bool _concurrent_locks; 1.300 + DeadlockCycle* _deadlocks; 1.301 + outputStream* _out; 1.302 + 1.303 + public: 1.304 + VM_FindDeadlocks(bool concurrent_locks) : _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL) {}; 1.305 + VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _out(st), _deadlocks(NULL) {}; 1.306 + ~VM_FindDeadlocks(); 1.307 + 1.308 + DeadlockCycle* result() { return _deadlocks; }; 1.309 + VMOp_Type type() const { return VMOp_FindDeadlocks; } 1.310 + void doit(); 1.311 + bool doit_prologue(); 1.312 +}; 1.313 + 1.314 +class ThreadDumpResult; 1.315 +class ThreadSnapshot; 1.316 +class ThreadConcurrentLocks; 1.317 + 1.318 +class VM_ThreadDump : public VM_Operation { 1.319 + private: 1.320 + ThreadDumpResult* _result; 1.321 + int _num_threads; 1.322 + GrowableArray<instanceHandle>* _threads; 1.323 + int _max_depth; 1.324 + bool _with_locked_monitors; 1.325 + bool _with_locked_synchronizers; 1.326 + 1.327 + ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl); 1.328 + 1.329 + public: 1.330 + VM_ThreadDump(ThreadDumpResult* result, 1.331 + int max_depth, // -1 indicates entire stack 1.332 + bool with_locked_monitors, 1.333 + bool with_locked_synchronizers); 1.334 + 1.335 + VM_ThreadDump(ThreadDumpResult* result, 1.336 + GrowableArray<instanceHandle>* threads, 1.337 + int num_threads, // -1 indicates entire stack 1.338 + int max_depth, 1.339 + bool with_locked_monitors, 1.340 + bool with_locked_synchronizers); 1.341 + 1.342 + VMOp_Type type() const { return VMOp_ThreadDump; } 1.343 + void doit(); 1.344 + bool doit_prologue(); 1.345 + void doit_epilogue(); 1.346 +}; 1.347 + 1.348 + 1.349 +class VM_Exit: public VM_Operation { 1.350 + private: 1.351 + int _exit_code; 1.352 + static volatile bool _vm_exited; 1.353 + static Thread * _shutdown_thread; 1.354 + static void wait_if_vm_exited(); 1.355 + public: 1.356 + VM_Exit(int exit_code) { 1.357 + _exit_code = exit_code; 1.358 + } 1.359 + static int wait_for_threads_in_native_to_block(); 1.360 + static int set_vm_exited(); 1.361 + static bool vm_exited() { return _vm_exited; } 1.362 + static void block_if_vm_exited() { 1.363 + if (_vm_exited) { 1.364 + wait_if_vm_exited(); 1.365 + } 1.366 + } 1.367 + VMOp_Type type() const { return VMOp_Exit; } 1.368 + void doit(); 1.369 +};