1 /* 2 * Copyright (c) 1998, 2024, 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 "precompiled.hpp" 26 #include "compiler/compileBroker.hpp" 27 #include "gc/shared/collectedHeap.hpp" 28 #include "jfr/jfrEvents.hpp" 29 #include "jfr/support/jfrThreadId.hpp" 30 #include "logging/log.hpp" 31 #include "logging/logStream.hpp" 32 #include "logging/logConfiguration.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/vmThread.hpp" 51 #include "runtime/vmOperation.hpp" 52 #include "runtime/vmOperations.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: " INTX_FORMAT " 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: " INTX_FORMAT " 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 op->evaluate(); 287 if (event.should_commit()) { 288 post_vm_operation_event(&event, op); 289 } 290 291 HOTSPOT_VMOPS_END( 292 (char *) op->name(), strlen(op->name()), 293 op->evaluate_at_safepoint() ? 0 : 1); 294 } 295 296 if (UsePerfData && os::is_thread_cpu_time_supported()) { 297 assert(Thread::current() == this, "Must be called from VM thread"); 298 // Update vm_thread_cpu_time after each VM operation. 299 ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::vm); 300 tttc.do_thread(this); 301 } 302 } 303 304 class HandshakeALotClosure : public HandshakeClosure { 305 public: 306 HandshakeALotClosure() : HandshakeClosure("HandshakeALot") {} 307 void do_thread(Thread* thread) { 308 #ifdef ASSERT 309 JavaThread::cast(thread)->verify_states_for_handshake(); 310 #endif 311 } 312 }; 313 314 bool VMThread::handshake_or_safepoint_alot() { 315 assert(_cur_vm_operation == nullptr, "should not have an op yet"); 316 assert(_next_vm_operation == nullptr, "should not have an op yet"); 317 if (!HandshakeALot && !SafepointALot) { 318 return false; 319 } 320 static jlong last_alot_ms = 0; 321 jlong now_ms = nanos_to_millis(os::javaTimeNanos()); 322 // If HandshakeALot or SafepointALot are set, but GuaranteedSafepointInterval is explicitly 323 // set to 0 on the command line, we emit the operation if it's been more than a second 324 // since the last one. 325 jlong interval = GuaranteedSafepointInterval != 0 ? GuaranteedSafepointInterval : 1000; 326 jlong deadline_ms = interval + last_alot_ms; 327 if (now_ms > deadline_ms) { 328 last_alot_ms = now_ms; 329 return true; 330 } 331 return false; 332 } 333 334 bool VMThread::set_next_operation(VM_Operation *op) { 335 if (_next_vm_operation != nullptr) { 336 return false; 337 } 338 log_debug(vmthread)("Adding VM operation: %s", op->name()); 339 340 _next_vm_operation = op; 341 342 HOTSPOT_VMOPS_REQUEST( 343 (char *) op->name(), strlen(op->name()), 344 op->evaluate_at_safepoint() ? 0 : 1); 345 return true; 346 } 347 348 void VMThread::wait_until_executed(VM_Operation* op) { 349 MonitorLocker ml(VMOperation_lock, 350 Thread::current()->is_Java_thread() ? 351 Mutex::_safepoint_check_flag : 352 Mutex::_no_safepoint_check_flag); 353 { 354 TraceTime timer("Installing VM operation", TRACETIME_LOG(Trace, vmthread)); 355 while (true) { 356 if (VMThread::vm_thread()->set_next_operation(op)) { 357 ml.notify_all(); 358 break; 359 } 360 // Wait to install this operation as the next operation in the VM Thread 361 log_trace(vmthread)("A VM operation already set, waiting"); 362 ml.wait(); 363 } 364 } 365 { 366 // Wait until the operation has been processed 367 TraceTime timer("Waiting for VM operation to be completed", TRACETIME_LOG(Trace, vmthread)); 368 // _next_vm_operation is cleared holding VMOperation_lock after it has been 369 // executed. We wait until _next_vm_operation is not our op. 370 while (_next_vm_operation == op) { 371 // VM Thread can process it once we unlock the mutex on wait. 372 ml.wait(); 373 } 374 } 375 } 376 377 static void self_destruct_if_needed() { 378 // Support for self destruction 379 if ((SelfDestructTimer != 0.0) && !VMError::is_error_reported() && 380 (os::elapsedTime() > SelfDestructTimer * 60.0)) { 381 tty->print_cr("VM self-destructed"); 382 os::exit(-1); 383 } 384 } 385 386 void VMThread::inner_execute(VM_Operation* op) { 387 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); 388 389 VM_Operation* prev_vm_operation = nullptr; 390 if (_cur_vm_operation != nullptr) { 391 // Check that the VM operation allows nested VM operation. 392 // This is normally not the case, e.g., the compiler 393 // does not allow nested scavenges or compiles. 394 if (!_cur_vm_operation->allow_nested_vm_operations()) { 395 fatal("Unexpected nested VM operation %s requested by operation %s", 396 op->name(), _cur_vm_operation->name()); 397 } 398 op->set_calling_thread(_cur_vm_operation->calling_thread()); 399 prev_vm_operation = _cur_vm_operation; 400 } 401 402 _cur_vm_operation = op; 403 404 HandleMark hm(VMThread::vm_thread()); 405 406 const char* const cause = op->cause(); 407 EventMarkVMOperation em("Executing %sVM operation: %s%s%s%s", 408 prev_vm_operation != nullptr ? "nested " : "", 409 op->name(), 410 cause != nullptr ? " (" : "", 411 cause != nullptr ? cause : "", 412 cause != nullptr ? ")" : ""); 413 414 log_debug(vmthread)("Evaluating %s %s VM operation: %s", 415 prev_vm_operation != nullptr ? "nested" : "", 416 _cur_vm_operation->evaluate_at_safepoint() ? "safepoint" : "non-safepoint", 417 _cur_vm_operation->name()); 418 419 bool end_safepoint = false; 420 bool has_timeout_task = (_timeout_task != nullptr); 421 if (_cur_vm_operation->evaluate_at_safepoint() && 422 !SafepointSynchronize::is_at_safepoint()) { 423 SafepointSynchronize::begin(); 424 if (has_timeout_task) { 425 _timeout_task->arm(_cur_vm_operation->name()); 426 } 427 end_safepoint = true; 428 } 429 430 evaluate_operation(_cur_vm_operation); 431 432 if (end_safepoint) { 433 if (has_timeout_task) { 434 _timeout_task->disarm(); 435 } 436 SafepointSynchronize::end(); 437 } 438 439 _cur_vm_operation = prev_vm_operation; 440 } 441 442 void VMThread::wait_for_operation() { 443 assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); 444 MonitorLocker ml_op_lock(VMOperation_lock, Mutex::_no_safepoint_check_flag); 445 446 // Clear previous operation. 447 // On first call this clears a dummy place-holder. 448 _next_vm_operation = nullptr; 449 // Notify operation is done and notify a next operation can be installed. 450 ml_op_lock.notify_all(); 451 452 while (!should_terminate()) { 453 self_destruct_if_needed(); 454 if (_next_vm_operation != nullptr) { 455 return; 456 } 457 if (handshake_or_safepoint_alot()) { 458 if (HandshakeALot) { 459 MutexUnlocker mul(VMOperation_lock); 460 HandshakeALotClosure hal_cl; 461 Handshake::execute(&hal_cl); 462 } 463 // When we unlocked above someone might have setup a new op. 464 if (_next_vm_operation != nullptr) { 465 return; 466 } 467 if (SafepointALot) { 468 _next_vm_operation = &safepointALot_op; 469 return; 470 } 471 } 472 assert(_next_vm_operation == nullptr, "Must be"); 473 assert(_cur_vm_operation == nullptr, "Must be"); 474 475 // We didn't find anything to execute, notify any waiter so they can install an op. 476 ml_op_lock.notify_all(); 477 ml_op_lock.wait(GuaranteedSafepointInterval); 478 } 479 } 480 481 void VMThread::loop() { 482 assert(_cur_vm_operation == nullptr, "no current one should be executing"); 483 484 SafepointSynchronize::init(_vm_thread); 485 486 // Need to set a calling thread for ops not passed 487 // via the normal way. 488 no_op.set_calling_thread(_vm_thread); 489 safepointALot_op.set_calling_thread(_vm_thread); 490 491 while (true) { 492 if (should_terminate()) break; 493 wait_for_operation(); 494 if (should_terminate()) break; 495 assert(_next_vm_operation != nullptr, "Must have one"); 496 inner_execute(_next_vm_operation); 497 } 498 } 499 500 // A SkipGCALot object is used to elide the usual effect of gc-a-lot 501 // over a section of execution by a thread. Currently, it's used only to 502 // prevent re-entrant calls to GC. 503 class SkipGCALot : public StackObj { 504 private: 505 bool _saved; 506 Thread* _t; 507 508 public: 509 #ifdef ASSERT 510 SkipGCALot(Thread* t) : _t(t) { 511 _saved = _t->skip_gcalot(); 512 _t->set_skip_gcalot(true); 513 } 514 515 ~SkipGCALot() { 516 assert(_t->skip_gcalot(), "Save-restore protocol invariant"); 517 _t->set_skip_gcalot(_saved); 518 } 519 #else 520 SkipGCALot(Thread* t) { } 521 ~SkipGCALot() { } 522 #endif 523 }; 524 525 void VMThread::execute(VM_Operation* op) { 526 Thread* t = Thread::current(); 527 528 PerfTraceTimedEvent p(VMThread::get_perf_timer_for(op), VMThread::get_perf_counter_for(op), \ 529 Thread::current()->profile_vm_ops()); \ 530 531 if (t->is_VM_thread()) { 532 op->set_calling_thread(t); 533 ((VMThread*)t)->inner_execute(op); 534 return; 535 } 536 537 // Avoid re-entrant attempts to gc-a-lot 538 SkipGCALot sgcalot(t); 539 540 // JavaThread or WatcherThread 541 if (t->is_Java_thread()) { 542 JavaThread::cast(t)->check_for_valid_safepoint_state(); 543 } 544 545 // New request from Java thread, evaluate prologue 546 if (!op->doit_prologue()) { 547 return; // op was cancelled 548 } 549 550 op->set_calling_thread(t); 551 552 wait_until_executed(op); 553 554 op->doit_epilogue(); 555 } 556 557 void VMThread::verify() { 558 oops_do(&VerifyOopClosure::verify_oop, nullptr); 559 } 560 561 #define DECLARE_COUNTER(name) \ 562 PerfTickCounters* _perf_##name##_timer = nullptr; \ 563 PerfCounter* _perf_##name##_count = nullptr; 564 565 VM_OPS_DO(DECLARE_COUNTER) 566 567 #undef DECLARE_COUNTER 568 569 #define SWITCH_TIMER(name) \ 570 case VM_Operation::VMOp_##name: return _perf_##name##_timer; 571 572 PerfTickCounters* VMThread::get_perf_timer_for(VM_Operation *op) { 573 switch(op->type()) { 574 VM_OPS_DO(SWITCH_TIMER) 575 default: ShouldNotReachHere(); 576 } 577 } 578 579 #undef SWITCH_TIMER 580 581 #define SWITCH_COUNT(name) \ 582 case VM_Operation::VMOp_##name: return _perf_##name##_count; 583 584 PerfCounter* VMThread::get_perf_counter_for(VM_Operation *op) { 585 switch(op->type()) { 586 VM_OPS_DO(SWITCH_COUNT) 587 default: ShouldNotReachHere(); 588 } 589 } 590 591 #undef SWITCH_COUNT 592 593 #define INIT_COUNTER(name) \ 594 NEWPERFTICKCOUNTERS(_perf_##name##_timer, SUN_RT, #name "_time"); \ 595 NEWPERFEVENTCOUNTER(_perf_##name##_count, SUN_RT, #name "_count"); \ 596 597 void VMThread::init_counters() { 598 if (ProfileVMOps && UsePerfData) { 599 EXCEPTION_MARK; 600 601 VM_OPS_DO(INIT_COUNTER) 602 603 if (HAS_PENDING_EXCEPTION) { 604 vm_exit_during_initialization("jvm_perf_init failed unexpectedly"); 605 } 606 } 607 } 608 609 #undef INIT_COUNTER 610 611 static jlong total_count() { 612 jlong total = 0; 613 #define ACC_COUNT(name) total += _perf_##name##_count->get_value(); 614 VM_OPS_DO(ACC_COUNT) 615 #undef ACC_COUNT 616 return total; 617 } 618 619 static jlong total_elapsed_time_in_ms() { 620 jlong total_elapsed_ticks = 0; 621 #define ACC_COUNT(name) total_elapsed_ticks += _perf_##name##_timer->elapsed_counter_value(); 622 VM_OPS_DO(ACC_COUNT) 623 #undef ACC_COUNT 624 return Management::ticks_to_ms(total_elapsed_ticks); 625 } 626 627 #define PRINT_COUNTER(name) {\ 628 jlong count = _perf_##name##_count->get_value(); \ 629 if (count > 0) { \ 630 st->print_cr(" %-40s = " JLONG_FORMAT_W(6) "us (" JLONG_FORMAT_W(5) " events)", #name, _perf_##name##_timer->elapsed_counter_value_us(), count); \ 631 }} 632 633 void VMThread::print_counters_on(outputStream* st) { 634 if (ProfileVMOps && UsePerfData) { 635 st->print_cr("VMOperation: Total: " JLONG_FORMAT " events (elapsed " JLONG_FORMAT "ms) for thread \"main\":", 636 total_count(), total_elapsed_time_in_ms()); 637 VM_OPS_DO(PRINT_COUNTER) 638 } else { 639 st->print_cr(" VMOperations: no info (%s is disabled)", (UsePerfData ? "ProfileVMCalls" : "UsePerfData")); 640 } 641 } 642 643 #undef PRINT_COUNTER