vm_operations.hpp 14.8 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31 32 33
#ifndef SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
#define SHARE_VM_RUNTIME_VM_OPERATIONS_HPP

#include "classfile/javaClasses.hpp"
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
#include "runtime/thread.hpp"
#include "utilities/top.hpp"

D
duke 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// The following classes are used for operations
// initiated by a Java thread but that must
// take place in the VMThread.

#define VM_OP_ENUM(type)   VMOp_##type,

// Note: When new VM_XXX comes up, add 'XXX' to the template table.
#define VM_OPS_DO(template)                       \
  template(Dummy)                                 \
  template(ThreadStop)                            \
  template(ThreadDump)                            \
  template(PrintThreads)                          \
  template(FindDeadlocks)                         \
  template(ForceSafepoint)                        \
  template(ForceAsyncSafepoint)                   \
  template(Deoptimize)                            \
  template(DeoptimizeFrame)                       \
  template(DeoptimizeAll)                         \
  template(ZombieAll)                             \
53
  template(UnlinkSymbols)                         \
54
  template(HandleFullCodeCache)                   \
D
duke 已提交
55 56 57 58 59 60 61 62
  template(Verify)                                \
  template(PrintJNI)                              \
  template(HeapDumper)                            \
  template(DeoptimizeTheWorld)                    \
  template(GC_HeapInspection)                     \
  template(GenCollectFull)                        \
  template(GenCollectFullConcurrent)              \
  template(GenCollectForAllocation)               \
63
  template(GenCollectForPermanentAllocation)      \
D
duke 已提交
64 65 66
  template(ParallelGCFailedAllocation)            \
  template(ParallelGCFailedPermanentAllocation)   \
  template(ParallelGCSystemGC)                    \
67
  template(CGC_Operation)                         \
D
duke 已提交
68 69
  template(CMS_Initial_Mark)                      \
  template(CMS_Final_Remark)                      \
70 71 72
  template(G1CollectFull)                         \
  template(G1CollectForAllocation)                \
  template(G1IncCollectionPause)                  \
D
duke 已提交
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  template(EnableBiasedLocking)                   \
  template(RevokeBias)                            \
  template(BulkRevokeBias)                        \
  template(PopulateDumpSharedSpace)               \
  template(JNIFunctionTableCopier)                \
  template(RedefineClasses)                       \
  template(GetOwnedMonitorInfo)                   \
  template(GetObjectMonitorUsage)                 \
  template(GetCurrentContendedMonitor)            \
  template(GetStackTrace)                         \
  template(GetMultipleStackTraces)                \
  template(GetAllStackTraces)                     \
  template(GetThreadListStackTraces)              \
  template(GetFrameCount)                         \
  template(GetFrameLocation)                      \
  template(ChangeBreakpoints)                     \
  template(GetOrSetLocal)                         \
  template(GetCurrentLocation)                    \
  template(EnterInterpOnlyMode)                   \
  template(ChangeSingleStep)                      \
  template(HeapWalkOperation)                     \
  template(HeapIterateOperation)                  \
  template(ReportJavaOutOfMemory)                 \
96
  template(JFRCheckpoint)                         \
D
duke 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
  template(Exit)                                  \

class VM_Operation: public CHeapObj {
 public:
  enum Mode {
    _safepoint,       // blocking,        safepoint, vm_op C-heap allocated
    _no_safepoint,    // blocking,     no safepoint, vm_op C-Heap allocated
    _concurrent,      // non-blocking, no safepoint, vm_op C-Heap allocated
    _async_safepoint  // non-blocking,    safepoint, vm_op C-Heap allocated
  };

  enum VMOp_Type {
    VM_OPS_DO(VM_OP_ENUM)
    VMOp_Terminating
  };

 private:
  Thread*         _calling_thread;
  ThreadPriority  _priority;
  long            _timestamp;
  VM_Operation*   _next;
  VM_Operation*   _prev;

  // The VM operation name array
  static const char* _names[];

 public:
  VM_Operation()  { _calling_thread = NULL; _next = NULL; _prev = NULL; }
  virtual ~VM_Operation() {}

  // VM operation support (used by VM thread)
  Thread* calling_thread() const                 { return _calling_thread; }
  ThreadPriority priority()                      { return _priority; }
  void set_calling_thread(Thread* thread, ThreadPriority priority);

  long timestamp() const              { return _timestamp; }
  void set_timestamp(long timestamp)  { _timestamp = timestamp; }

  // Called by VM thread - does in turn invoke doit(). Do not override this
  void evaluate();

  // evaluate() is called by the VMThread and in turn calls doit().
  // If the thread invoking VMThread::execute((VM_Operation*) is a JavaThread,
  // doit_prologue() is called in that thread before transferring control to
  // the VMThread.
  // If doit_prologue() returns true the VM operation will proceed, and
  // doit_epilogue() will be called by the JavaThread once the VM operation
  // completes. If doit_prologue() returns false the VM operation is cancelled.
  virtual void doit()                            = 0;
  virtual bool doit_prologue()                   { return true; };
  virtual void doit_epilogue()                   {}; // Note: Not called if mode is: _concurrent

  // Type test
  virtual bool is_methodCompiler() const         { return false; }

  // Linking
  VM_Operation *next() const                     { return _next; }
  VM_Operation *prev() const                     { return _prev; }
  void set_next(VM_Operation *next)              { _next = next; }
  void set_prev(VM_Operation *prev)              { _prev = prev; }

  // Configuration. Override these appropriatly in subclasses.
  virtual VMOp_Type type() const = 0;
  virtual Mode evaluation_mode() const            { return _safepoint; }
  virtual bool allow_nested_vm_operations() const { return false; }
  virtual bool is_cheap_allocated() const         { return false; }
  virtual void oops_do(OopClosure* f)              { /* do nothing */ };

  // CAUTION: <don't hang yourself with following rope>
  // If you override these methods, make sure that the evaluation
  // of these methods is race-free and non-blocking, since these
  // methods may be evaluated either by the mutators or by the
  // vm thread, either concurrently with mutators or with the mutators
  // stopped. In other words, taking locks is verboten, and if there
  // are any races in evaluating the conditions, they'd better be benign.
  virtual bool evaluate_at_safepoint() const {
    return evaluation_mode() == _safepoint  ||
           evaluation_mode() == _async_safepoint;
  }
  virtual bool evaluate_concurrently() const {
    return evaluation_mode() == _concurrent ||
           evaluation_mode() == _async_safepoint;
  }

  // Debugging
  void print_on_error(outputStream* st) const;
  const char* name() const { return _names[type()]; }
  static const char* name(int type) {
    assert(type >= 0 && type < VMOp_Terminating, "invalid VM operation type");
    return _names[type];
  }
#ifndef PRODUCT
  void print_on(outputStream* st) const { print_on_error(st); }
#endif
};

class VM_ThreadStop: public VM_Operation {
 private:
  oop     _thread;        // The Thread that the Throwable is thrown against
  oop     _throwable;     // The Throwable thrown at the target Thread
 public:
  // All oops are passed as JNI handles, since there is no guarantee that a GC might happen before the
  // VM operation is executed.
  VM_ThreadStop(oop thread, oop throwable) {
    _thread    = thread;
    _throwable = throwable;
  }
  VMOp_Type type() const                         { return VMOp_ThreadStop; }
  oop target_thread() const                      { return _thread; }
  oop throwable() const                          { return _throwable;}
  void doit();
  // We deoptimize if top-most frame is compiled - this might require a C2I adapter to be generated
  bool allow_nested_vm_operations() const        { return true; }
  Mode evaluation_mode() const                   { return _async_safepoint; }
  bool is_cheap_allocated() const                { return true; }

  // GC support
  void oops_do(OopClosure* f) {
    f->do_oop(&_thread); f->do_oop(&_throwable);
  }
};

// dummy vm op, evaluated just to force a safepoint
class VM_ForceSafepoint: public VM_Operation {
 public:
  VM_ForceSafepoint() {}
  void doit()         {}
  VMOp_Type type() const { return VMOp_ForceSafepoint; }
};

// dummy vm op, evaluated just to force a safepoint
class VM_ForceAsyncSafepoint: public VM_Operation {
 public:
  VM_ForceAsyncSafepoint() {}
  void doit()              {}
  VMOp_Type type() const                         { return VMOp_ForceAsyncSafepoint; }
  Mode evaluation_mode() const                   { return _async_safepoint; }
  bool is_cheap_allocated() const                { return true; }
};

class VM_Deoptimize: public VM_Operation {
 public:
  VM_Deoptimize() {}
  VMOp_Type type() const                        { return VMOp_Deoptimize; }
  void doit();
  bool allow_nested_vm_operations() const        { return true; }
};

245 246 247

// Deopt helper that can deoptimize frames in threads other than the
// current thread.  Only used through Deoptimization::deoptimize_frame.
D
duke 已提交
248
class VM_DeoptimizeFrame: public VM_Operation {
249 250
  friend class Deoptimization;

D
duke 已提交
251 252 253 254
 private:
  JavaThread* _thread;
  intptr_t*   _id;
  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
255 256

 public:
D
duke 已提交
257 258 259 260 261
  VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
  void doit();
  bool allow_nested_vm_operations() const        { return true;  }
};

262 263 264 265 266 267 268 269 270 271
class VM_HandleFullCodeCache: public VM_Operation {
 private:
  bool  _is_full;
 public:
  VM_HandleFullCodeCache(bool is_full)           { _is_full = is_full; }
  VMOp_Type type() const                         { return VMOp_HandleFullCodeCache; }
  void doit();
  bool allow_nested_vm_operations() const        { return true; }
};

D
duke 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
#ifndef PRODUCT
class VM_DeoptimizeAll: public VM_Operation {
 private:
  KlassHandle _dependee;
 public:
  VM_DeoptimizeAll() {}
  VMOp_Type type() const                         { return VMOp_DeoptimizeAll; }
  void doit();
  bool allow_nested_vm_operations() const        { return true; }
};


class VM_ZombieAll: public VM_Operation {
 public:
  VM_ZombieAll() {}
  VMOp_Type type() const                         { return VMOp_ZombieAll; }
  void doit();
  bool allow_nested_vm_operations() const        { return true; }
};
#endif // PRODUCT

293 294 295 296 297 298 299 300
class VM_UnlinkSymbols: public VM_Operation {
 public:
  VM_UnlinkSymbols() {}
  VMOp_Type type() const                         { return VMOp_UnlinkSymbols; }
  void doit();
  bool allow_nested_vm_operations() const        { return true; }
};

D
duke 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
class VM_Verify: public VM_Operation {
 private:
  KlassHandle _dependee;
 public:
  VM_Verify() {}
  VMOp_Type type() const { return VMOp_Verify; }
  void doit();
};


class VM_PrintThreads: public VM_Operation {
 private:
  outputStream* _out;
  bool _print_concurrent_locks;
 public:
  VM_PrintThreads()                                                { _out = tty; _print_concurrent_locks = PrintConcurrentLocks; }
  VM_PrintThreads(outputStream* out, bool print_concurrent_locks)  { _out = out; _print_concurrent_locks = print_concurrent_locks; }
  VMOp_Type type() const                                           {  return VMOp_PrintThreads; }
  void doit();
  bool doit_prologue();
  void doit_epilogue();
};

class VM_PrintJNI: public VM_Operation {
 private:
  outputStream* _out;
 public:
  VM_PrintJNI()                         { _out = tty; }
  VM_PrintJNI(outputStream* out)        { _out = out; }
  VMOp_Type type() const                { return VMOp_PrintJNI; }
  void doit();
};

class DeadlockCycle;
class VM_FindDeadlocks: public VM_Operation {
 private:
  bool           _concurrent_locks;
  DeadlockCycle* _deadlocks;
  outputStream*  _out;

 public:
  VM_FindDeadlocks(bool concurrent_locks) :  _concurrent_locks(concurrent_locks), _out(NULL), _deadlocks(NULL) {};
  VM_FindDeadlocks(outputStream* st) : _concurrent_locks(true), _out(st), _deadlocks(NULL) {};
  ~VM_FindDeadlocks();

  DeadlockCycle* result()      { return _deadlocks; };
  VMOp_Type type() const       { return VMOp_FindDeadlocks; }
  void doit();
  bool doit_prologue();
};

class ThreadDumpResult;
class ThreadSnapshot;
class ThreadConcurrentLocks;

class VM_ThreadDump : public VM_Operation {
 private:
  ThreadDumpResult*              _result;
  int                            _num_threads;
  GrowableArray<instanceHandle>* _threads;
  int                            _max_depth;
  bool                           _with_locked_monitors;
  bool                           _with_locked_synchronizers;

  ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);

 public:
  VM_ThreadDump(ThreadDumpResult* result,
                int max_depth,  // -1 indicates entire stack
                bool with_locked_monitors,
                bool with_locked_synchronizers);

  VM_ThreadDump(ThreadDumpResult* result,
                GrowableArray<instanceHandle>* threads,
                int num_threads, // -1 indicates entire stack
                int max_depth,
                bool with_locked_monitors,
                bool with_locked_synchronizers);

  VMOp_Type type() const { return VMOp_ThreadDump; }
  void doit();
  bool doit_prologue();
  void doit_epilogue();
};


class VM_Exit: public VM_Operation {
 private:
  int  _exit_code;
  static volatile bool _vm_exited;
  static Thread * _shutdown_thread;
  static void wait_if_vm_exited();
 public:
  VM_Exit(int exit_code) {
    _exit_code = exit_code;
  }
  static int wait_for_threads_in_native_to_block();
  static int set_vm_exited();
  static bool vm_exited()                      { return _vm_exited; }
  static void block_if_vm_exited() {
    if (_vm_exited) {
      wait_if_vm_exited();
    }
  }
  VMOp_Type type() const { return VMOp_Exit; }
  void doit();
};
408 409

#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP