src/share/vm/runtime/vm_operations.hpp

changeset 435
a61af66fc99e
child 574
c0492d52d55b
     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 +};

mercurial