1 /* 2 * Copyright (c) 1998, 2025, 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 #include "compiler/compileBroker.hpp" 26 #include "gc/shared/collectedHeap.hpp" 27 #include "gc/shared/vmThreadCpuTimeScope.inline.hpp" 28 #include "jfr/jfrEvents.hpp" 29 #include "jfr/support/jfrThreadId.hpp" 30 #include "logging/log.hpp" 31 #include "logging/logConfiguration.hpp" 32 #include "logging/logStream.hpp" 33 #include "memory/resourceArea.hpp" 34 #include "memory/universe.hpp" 35 #include "oops/oop.inline.hpp" 36 #include "oops/verifyOopClosure.hpp" 37 #include "runtime/atomic.hpp" 38 #include "runtime/cpuTimeCounters.hpp" 39 #include "runtime/handles.inline.hpp" 40 #include "runtime/interfaceSupport.inline.hpp" 41 #include "runtime/java.hpp" 42 #include "runtime/javaThread.inline.hpp" 43 #include "runtime/jniHandles.hpp" 44 #include "runtime/mutexLocker.hpp" 45 #include "runtime/os.hpp" 46 #include "runtime/perfData.inline.hpp" 47 #include "runtime/safepoint.hpp" 48 #include "runtime/synchronizer.hpp" 49 #include "runtime/timerTrace.hpp" 50 #include "runtime/vmOperation.hpp" 51 #include "runtime/vmOperations.hpp" 52 #include "runtime/vmThread.hpp" 53 #include "services/management.hpp" 54 #include "utilities/dtrace.hpp" 55 #include "utilities/events.hpp" 56 #include "utilities/vmError.hpp" 57 58 59 //------------------------------------------------------------------------------------------------------------------ 60 // Timeout machinery 61 62 void VMOperationTimeoutTask::task() { 63 assert(AbortVMOnVMOperationTimeout, "only if enabled"); 64 if (is_armed()) { 65 jlong delay = nanos_to_millis(os::javaTimeNanos() - _arm_time); 66 if (delay > AbortVMOnVMOperationTimeoutDelay) { 67 fatal("%s VM operation took too long: " JLONG_FORMAT " ms elapsed since VM-op start (timeout: %zd ms)", 68 _vm_op_name, delay, AbortVMOnVMOperationTimeoutDelay); 69 } 70 } 71 } 72 73 bool VMOperationTimeoutTask::is_armed() { 74 return Atomic::load_acquire(&_armed) != 0; 75 } 76 77 void VMOperationTimeoutTask::arm(const char* vm_op_name) { 78 _vm_op_name = vm_op_name; 79 _arm_time = os::javaTimeNanos(); 80 Atomic::release_store_fence(&_armed, 1); 81 } 82 83 void VMOperationTimeoutTask::disarm() { 84 Atomic::release_store_fence(&_armed, 0); 85 86 // The two stores to `_armed` are counted in VM-op, but they should be 87 // insignificant compared to the actual VM-op duration. 88 jlong vm_op_duration = nanos_to_millis(os::javaTimeNanos() - _arm_time); 89 90 // Repeat the timeout-check logic on the VM thread, because 91 // VMOperationTimeoutTask might miss the arm-disarm window depending on 92 // the scheduling. 93 if (vm_op_duration > AbortVMOnVMOperationTimeoutDelay) { 94 fatal("%s VM operation took too long: completed in " JLONG_FORMAT " ms (timeout: %zd ms)", 95 _vm_op_name, vm_op_duration, AbortVMOnVMOperationTimeoutDelay); 96 } 97 _vm_op_name = nullptr; 98 } 99 100 //------------------------------------------------------------------------------------------------------------------ 101 // Implementation of VMThread stuff 102 103 static VM_SafepointALot safepointALot_op; 104 static VM_ForceSafepoint no_op; 105 106 bool VMThread::_should_terminate = false; 107 bool VMThread::_terminated = false; 108 Monitor* VMThread::_terminate_lock = nullptr; 109 VMThread* VMThread::_vm_thread = nullptr; 110 VM_Operation* VMThread::_cur_vm_operation = nullptr; 111 VM_Operation* VMThread::_next_vm_operation = &no_op; // Prevent any thread from setting an operation until VM thread is ready. 112 PerfCounter* VMThread::_perf_accumulated_vm_operation_time = nullptr; 113 VMOperationTimeoutTask* VMThread::_timeout_task = nullptr; 114 115 116 void VMThread::create() { 117 assert(vm_thread() == nullptr, "we can only allocate one VMThread"); 118 _vm_thread = new VMThread(); 119 120 if (AbortVMOnVMOperationTimeout) { 121 // Make sure we call the timeout task frequently enough, but not too frequent. 122 // Try to make the interval 10% of the timeout delay, so that we miss the timeout 123 // by those 10% at max. Periodic task also expects it to fit min/max intervals. 124 size_t interval = (size_t)AbortVMOnVMOperationTimeoutDelay / 10; 125 interval = interval / PeriodicTask::interval_gran * PeriodicTask::interval_gran; 126 interval = MAX2<size_t>(interval, PeriodicTask::min_interval); 127 interval = MIN2<size_t>(interval, PeriodicTask::max_interval); 128 129 _timeout_task = new VMOperationTimeoutTask(interval); 130 _timeout_task->enroll(); 131 } else { 132 assert(_timeout_task == nullptr, "sanity"); 133 } 134 135 _terminate_lock = new Monitor(Mutex::nosafepoint, "VMThreadTerminate_lock"); 136 137 if (UsePerfData) { 138 // jvmstat performance counters 139 JavaThread* THREAD = JavaThread::current(); // For exception macros. 140 _perf_accumulated_vm_operation_time = 141 PerfDataManager::create_counter(SUN_THREADS, "vmOperationTime", 142 PerfData::U_Ticks, CHECK); 143 CPUTimeCounters::create_counter(CPUTimeGroups::CPUTimeType::vm); 144 } 145 } 146 147 VMThread::VMThread() : NamedThread(), _is_running(false) { 148 set_name("VM Thread"); 149 } 150 151 void VMThread::destroy() { 152 _vm_thread = nullptr; // VM thread is gone 153 } 154 155 static VM_Halt halt_op; 156 157 void VMThread::run() { 158 assert(this == vm_thread(), "check"); 159 160 // Notify_lock wait checks on is_running() to rewait in 161 // case of spurious wakeup, it should wait on the last 162 // value set prior to the notify 163 Atomic::store(&_is_running, true); 164 165 { 166 MutexLocker ml(Notify_lock); 167 Notify_lock->notify(); 168 } 169 // Notify_lock is destroyed by Threads::create_vm() 170 171 int prio = (VMThreadPriority == -1) 172 ? os::java_to_os_priority[NearMaxPriority] 173 : VMThreadPriority; 174 // Note that I cannot call os::set_priority because it expects Java 175 // priorities and I am *explicitly* using OS priorities so that it's 176 // possible to set the VM thread priority higher than any Java thread. 177 os::set_native_priority( this, prio ); 178 179 // Wait for VM_Operations until termination 180 this->loop(); 181 182 // Note the intention to exit before safepointing. 183 // 6295565 This has the effect of waiting for any large tty 184 // outputs to finish. 185 if (xtty != nullptr) { 186 ttyLocker ttyl; 187 xtty->begin_elem("destroy_vm"); 188 xtty->stamp(); 189 xtty->end_elem(); 190 assert(should_terminate(), "termination flag must be set"); 191 } 192 193 // 4526887 let VM thread exit at Safepoint 194 _cur_vm_operation = &halt_op; 195 SafepointSynchronize::begin(); 196 197 if (VerifyBeforeExit) { 198 HandleMark hm(VMThread::vm_thread()); 199 // Among other things, this ensures that Eden top is correct. 200 Universe::heap()->prepare_for_verify(); 201 // Silent verification so as not to pollute normal output, 202 // unless we really asked for it. 203 Universe::verify(); 204 } 205 206 CompileBroker::set_should_block(); 207 208 // wait for threads (compiler threads or daemon threads) in the 209 // _thread_in_native state to block. 210 VM_Exit::wait_for_threads_in_native_to_block(); 211 212 // The ObjectMonitor subsystem uses perf counters so do this before 213 // we signal that the VM thread is gone. We don't want to run afoul 214 // of perfMemory_exit() in exit_globals(). 215 ObjectSynchronizer::do_final_audit_and_print_stats(); 216 217 // signal other threads that VM process is gone 218 { 219 // Note: we must have the _no_safepoint_check_flag. Mutex::lock() allows 220 // VM thread to enter any lock at Safepoint as long as its _owner is null. 221 // If that happens after _terminate_lock->wait() has unset _owner 222 // but before it actually drops the lock and waits, the notification below 223 // may get lost and we will have a hang. To avoid this, we need to use 224 // Mutex::lock_without_safepoint_check(). 225 MonitorLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag); 226 _terminated = true; 227 ml.notify(); 228 } 229 230 // We are now racing with the VM termination being carried out in 231 // another thread, so we don't "delete this". Numerous threads don't 232 // get deleted when the VM terminates 233 234 } 235 236 237 // Notify the VMThread that the last non-daemon JavaThread has terminated, 238 // and wait until operation is performed. 239 void VMThread::wait_for_vm_thread_exit() { 240 assert(JavaThread::current()->is_terminated(), "Should be terminated"); 241 { 242 MonitorLocker mu(VMOperation_lock); 243 _should_terminate = true; 244 mu.notify_all(); 245 } 246 247 // Note: VM thread leaves at Safepoint. We are not stopped by Safepoint 248 // because this thread has been removed from the threads list. But anything 249 // that could get blocked by Safepoint should not be used after this point, 250 // otherwise we will hang, since there is no one can end the safepoint. 251 252 // Wait until VM thread is terminated 253 // Note: it should be OK to use Terminator_lock here. But this is called 254 // at a very delicate time (VM shutdown) and we are operating in non- VM 255 // thread at Safepoint. It's safer to not share lock with other threads. 256 { 257 MonitorLocker ml(_terminate_lock, Mutex::_no_safepoint_check_flag); 258 while (!VMThread::is_terminated()) { 259 ml.wait(); 260 } 261 } 262 } 263 264 static void post_vm_operation_event(EventExecuteVMOperation* event, VM_Operation* op) { 265 assert(event != nullptr, "invariant"); 266 assert(op != nullptr, "invariant"); 267 const bool evaluate_at_safepoint = op->evaluate_at_safepoint(); 268 event->set_operation(op->type()); 269 event->set_safepoint(evaluate_at_safepoint); 270 event->set_blocking(true); 271 event->set_caller(JFR_THREAD_ID(op->calling_thread())); 272 event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_id() : 0); 273 event->commit(); 274 } 275 276 void VMThread::evaluate_operation(VM_Operation* op) { 277 ResourceMark rm; 278 279 { 280 PerfTraceElapsedTime vm_op_timer(perf_accumulated_vm_operation_time()); 281 HOTSPOT_VMOPS_BEGIN( 282 (char*) op->name(), strlen(op->name()), 283 op->evaluate_at_safepoint() ? 0 : 1); 284 285 EventExecuteVMOperation event; 286 VMThreadCPUTimeScope CPUTimeScope(this, op->is_gc_operation()); 287 op->evaluate(); 288 if (event.should_commit()) { 289 post_vm_operation_event(&event, op); 290 } 291 292 HOTSPOT_VMOPS_END( 293 (char*) op->name(), strlen(op->name()), 294 op->evaluate_at_safepoint() ? 0 : 1); 295 } 296 } 297 298 class ALotOfHandshakeClosure : public HandshakeClosure { 299 public: 300 ALotOfHandshakeClosure() : HandshakeClosure("ALotOfHandshakeClosure") {} 301 void do_thread(Thread* thread) { 302 #ifdef ASSERT 303 JavaThread::cast(thread)->verify_states_for_handshake(); 304 #endif 305 } 306 }; 307 308 bool VMThread::handshake_or_safepoint_alot() { 309 assert(_cur_vm_operation == nullptr, "should not have an op yet"); 310 assert(_next_vm_operation == nullptr, "should not have an op yet"); 311 if (!HandshakeALot && !SafepointALot) { 312 return false; 313 } 314 static jlong last_alot_ms = 0; 315 jlong now_ms = nanos_to_millis(os::javaTimeNanos()); 316 // If HandshakeALot or SafepointALot are set, but GuaranteedSafepointInterval is explicitly 317 // set to 0 on the command line, we emit the operation if it's been more than a second 318 // since the last one. 319 jlong interval = GuaranteedSafepointInterval != 0 ? GuaranteedSafepointInterval : 1000; 320 jlong deadline_ms = interval + last_alot_ms; 321 if (now_ms > deadline_ms) { 322 last_alot_ms = now_ms; 323 return true; 324 } 325 return false; 326 } 327 328 bool VMThread::set_next_operation(VM_Operation *op) { 329 if (_next_vm_operation != nullptr) { 330 return false; 331 } 332 log_debug(vmthread)("Adding VM operation: %s", op->name()); 333 334 _next_vm_operation = op; 335 336 HOTSPOT_VMOPS_REQUEST( 337 (char *) op->name(), strlen(op->name()), 338 op->evaluate_at_safepoint() ? 0 : 1); 339 return true; 340 } 341 342 void VMThread::wait_until_executed(VM_Operation* op) { 343 MonitorLocker ml(VMOperation_lock, 344 Thread::current()->is_Java_thread() ? 345 Mutex::_safepoint_check_flag : 346 Mutex::_no_safepoint_check_flag); 347 { 348 TraceTime timer("Installing VM operation", TRACETIME_LOG(Trace, vmthread)); 349 while (true) { 350 if (VMThread::vm_thread()->set_next_operation(op)) { 351 ml.notify_all(); 352 break; 353 } 354 // Wait to install this operation as the next operation in the VM Thread 355 log_trace(vmthread)("A VM operation already set, waiting"); 356 ml.wait(); 357 } 358 } 359 { 360 // Wait until the operation has been processed 361 TraceTime timer("Waiting for VM operation to be completed", TRACETIME_LOG(Trace, vmthread)); 362 // _next_vm_operation is cleared holding VMOperation_lock after it has been 363 // executed. We wait until _next_vm_operation is not our op. 364 while (_next_vm_operation == op) { 365 // VM Thread can process it once we unlock the mutex on wait. 366 ml.wait(); 367 } 368 } 369 } 370 371 static void self_destruct_if_needed() { 372 // Support for self destruction 373 if ((SelfDestructTimer != 0.0) && !VMError::is_error_reported() && 374 (os::elapsedTime() > SelfDestructTimer * 60.0)) { 375 tty->print_cr("VM self-destructed"); 376 os::exit(-1); 377 } 378 } 379 380 void VMThread::inner_execute(VM_Operation* op) { 381 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); 382 383 VM_Operation* prev_vm_operation = nullptr; 384 if (_cur_vm_operation != nullptr) { 385 // Check that the VM operation allows nested VM operation. 386 // This is normally not the case, e.g., the compiler 387 // does not allow nested scavenges or compiles. 388 if (!_cur_vm_operation->allow_nested_vm_operations()) { 389 fatal("Unexpected nested VM operation %s requested by operation %s", 390 op->name(), _cur_vm_operation->name()); 391 } 392 op->set_calling_thread(_cur_vm_operation->calling_thread()); 393 prev_vm_operation = _cur_vm_operation; 394 } 395 396 _cur_vm_operation = op; 397 398 HandleMark hm(VMThread::vm_thread()); 399 400 const char* const cause = op->cause(); 401 stringStream ss; 402 ss.print("Executing%s%s VM operation: %s", 403 prev_vm_operation != nullptr ? " nested" : "", 404 op->evaluate_at_safepoint() ? " safepoint" : " non-safepoint", 405 op->name()); 406 if (cause != nullptr) { 407 ss.print(" (%s)", cause); 408 } 409 410 EventMarkVMOperation em("%s", ss.freeze()); 411 log_debug(vmthread)("%s", ss.freeze()); 412 413 bool end_safepoint = false; 414 bool has_timeout_task = (_timeout_task != nullptr); 415 if (_cur_vm_operation->evaluate_at_safepoint() && 416 !SafepointSynchronize::is_at_safepoint()) { 417 SafepointSynchronize::begin(); 418 if (has_timeout_task) { 419 _timeout_task->arm(_cur_vm_operation->name()); 420 } 421 end_safepoint = true; 422 } 423 424 evaluate_operation(_cur_vm_operation); 425 426 if (end_safepoint) { 427 if (has_timeout_task) { 428 _timeout_task->disarm(); 429 } 430 SafepointSynchronize::end(); 431 } 432 433 _cur_vm_operation = prev_vm_operation; 434 } 435 436 void VMThread::wait_for_operation() { 437 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); 438 MonitorLocker ml_op_lock(VMOperation_lock, Mutex::_no_safepoint_check_flag); 439 440 // Clear previous operation. 441 // On first call this clears a dummy place-holder. 442 _next_vm_operation = nullptr; 443 // Notify operation is done and notify a next operation can be installed. 444 ml_op_lock.notify_all(); 445 446 while (!should_terminate()) { 447 self_destruct_if_needed(); 448 if (_next_vm_operation != nullptr) { 449 return; 450 } 451 if (handshake_or_safepoint_alot()) { 452 if (HandshakeALot) { 453 MutexUnlocker mul(VMOperation_lock); 454 ALotOfHandshakeClosure aohc; 455 Handshake::execute(&aohc); 456 } 457 // When we unlocked above someone might have setup a new op. 458 if (_next_vm_operation != nullptr) { 459 return; 460 } 461 if (SafepointALot) { 462 _next_vm_operation = &safepointALot_op; 463 return; 464 } 465 } 466 assert(_next_vm_operation == nullptr, "Must be"); 467 assert(_cur_vm_operation == nullptr, "Must be"); 468 469 // We didn't find anything to execute, notify any waiter so they can install an op. 470 ml_op_lock.notify_all(); 471 ml_op_lock.wait(GuaranteedSafepointInterval); 472 } 473 } 474 475 void VMThread::loop() { 476 assert(_cur_vm_operation == nullptr, "no current one should be executing"); 477 478 SafepointSynchronize::init(_vm_thread); 479 480 // Need to set a calling thread for ops not passed 481 // via the normal way. 482 no_op.set_calling_thread(_vm_thread); 483 safepointALot_op.set_calling_thread(_vm_thread); 484 485 while (true) { 486 if (should_terminate()) break; 487 wait_for_operation(); 488 if (should_terminate()) break; 489 assert(_next_vm_operation != nullptr, "Must have one"); 490 inner_execute(_next_vm_operation); 491 } 492 } 493 494 // A SkipGCALot object is used to elide the usual effect of gc-a-lot 495 // over a section of execution by a thread. Currently, it's used only to 496 // prevent re-entrant calls to GC. 497 class SkipGCALot : public StackObj { 498 private: 499 bool _saved; 500 Thread* _t; 501 502 public: 503 #ifdef ASSERT 504 SkipGCALot(Thread* t) : _t(t) { 505 _saved = _t->skip_gcalot(); 506 _t->set_skip_gcalot(true); 507 } 508 509 ~SkipGCALot() { 510 assert(_t->skip_gcalot(), "Save-restore protocol invariant"); 511 _t->set_skip_gcalot(_saved); 512 } 513 #else 514 SkipGCALot(Thread* t) { } 515 ~SkipGCALot() { } 516 #endif 517 }; 518 519 void VMThread::execute(VM_Operation* op) { 520 Thread* t = Thread::current(); 521 522 PerfTraceTimedEvent p(VMThread::get_perf_timer_for(op), VMThread::get_perf_counter_for(op), \ 523 Thread::current()->profile_vm_ops()); \ 524 525 if (t->is_VM_thread()) { 526 op->set_calling_thread(t); 527 ((VMThread*)t)->inner_execute(op); 528 return; 529 } 530 531 // The current thread must not belong to the SuspendibleThreadSet, because an 532 // on-the-fly safepoint can be waiting for the current thread, and the 533 // current thread will be blocked in wait_until_executed, resulting in 534 // deadlock. 535 assert(!t->is_suspendible_thread(), "precondition"); 536 assert(!t->is_indirectly_suspendible_thread(), "precondition"); 537 538 // Avoid re-entrant attempts to gc-a-lot 539 SkipGCALot sgcalot(t); 540 541 // JavaThread or WatcherThread 542 if (t->is_Java_thread()) { 543 JavaThread::cast(t)->check_for_valid_safepoint_state(); 544 } 545 546 // New request from Java thread, evaluate prologue 547 if (!op->doit_prologue()) { 548 return; // op was cancelled 549 } 550 551 op->set_calling_thread(t); 552 553 wait_until_executed(op); 554 555 op->doit_epilogue(); 556 } 557 558 void VMThread::verify() { 559 oops_do(&VerifyOopClosure::verify_oop, nullptr); 560 } 561 562 #define DECLARE_COUNTER(name) \ 563 PerfTickCounters* _perf_##name##_timer = nullptr; \ 564 PerfCounter* _perf_##name##_count = nullptr; 565 566 VM_OPS_DO(DECLARE_COUNTER) 567 568 #undef DECLARE_COUNTER 569 570 #define SWITCH_TIMER(name) \ 571 case VM_Operation::VMOp_##name: return _perf_##name##_timer; 572 573 PerfTickCounters* VMThread::get_perf_timer_for(VM_Operation *op) { 574 switch(op->type()) { 575 VM_OPS_DO(SWITCH_TIMER) 576 default: ShouldNotReachHere(); 577 } 578 } 579 580 #undef SWITCH_TIMER 581 582 #define SWITCH_COUNT(name) \ 583 case VM_Operation::VMOp_##name: return _perf_##name##_count; 584 585 PerfCounter* VMThread::get_perf_counter_for(VM_Operation *op) { 586 switch(op->type()) { 587 VM_OPS_DO(SWITCH_COUNT) 588 default: ShouldNotReachHere(); 589 } 590 } 591 592 #undef SWITCH_COUNT 593 594 #define INIT_COUNTER(name) \ 595 NEWPERFTICKCOUNTERS(_perf_##name##_timer, SUN_RT, #name "_time"); \ 596 NEWPERFEVENTCOUNTER(_perf_##name##_count, SUN_RT, #name "_count"); \ 597 598 void VMThread::init_counters() { 599 if (ProfileVMOps && UsePerfData) { 600 EXCEPTION_MARK; 601 602 VM_OPS_DO(INIT_COUNTER) 603 604 if (HAS_PENDING_EXCEPTION) { 605 vm_exit_during_initialization("jvm_perf_init failed unexpectedly"); 606 } 607 } 608 } 609 610 #undef INIT_COUNTER 611 612 static jlong total_count() { 613 jlong total = 0; 614 #define ACC_COUNT(name) total += _perf_##name##_count->get_value(); 615 VM_OPS_DO(ACC_COUNT) 616 #undef ACC_COUNT 617 return total; 618 } 619 620 static jlong total_elapsed_time_in_ms() { 621 jlong total_elapsed_ticks = 0; 622 #define ACC_COUNT(name) total_elapsed_ticks += _perf_##name##_timer->elapsed_counter_value(); 623 VM_OPS_DO(ACC_COUNT) 624 #undef ACC_COUNT 625 return Management::ticks_to_ms(total_elapsed_ticks); 626 } 627 628 #define PRINT_COUNTER(name) {\ 629 jlong count = _perf_##name##_count->get_value(); \ 630 if (count > 0) { \ 631 st->print_cr(" %-40s = " JLONG_FORMAT_W(6) "us (" JLONG_FORMAT_W(5) " events)", #name, _perf_##name##_timer->elapsed_counter_value_us(), count); \ 632 }} 633 634 void VMThread::print_counters_on(outputStream* st) { 635 if (ProfileVMOps && UsePerfData) { 636 st->print_cr("VMOperation: Total: " JLONG_FORMAT " events (elapsed " JLONG_FORMAT "ms) for thread \"main\":", 637 total_count(), total_elapsed_time_in_ms()); 638 VM_OPS_DO(PRINT_COUNTER) 639 } else { 640 st->print_cr(" VMOperations: no info (%s is disabled)", (UsePerfData ? "ProfileVMCalls" : "UsePerfData")); 641 } 642 } 643 644 #undef PRINT_COUNTER