comparison src/share/vm/runtime/sweeper.cpp @ 10405:f2110083203d

8005849: JEP 167: Event-Based JVM Tracing Reviewed-by: acorn, coleenp, sla Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>
author sla
date Mon, 10 Jun 2013 11:30:51 +0200
parents 0cfa93c2fcc4
children 836a62f43af9 ab274453d37f
comparison
equal deleted inserted replaced
10404:d0add7016434 10405:f2110083203d
1 /* 1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
34 #include "runtime/compilationPolicy.hpp" 34 #include "runtime/compilationPolicy.hpp"
35 #include "runtime/mutexLocker.hpp" 35 #include "runtime/mutexLocker.hpp"
36 #include "runtime/os.hpp" 36 #include "runtime/os.hpp"
37 #include "runtime/sweeper.hpp" 37 #include "runtime/sweeper.hpp"
38 #include "runtime/vm_operations.hpp" 38 #include "runtime/vm_operations.hpp"
39 #include "trace/tracing.hpp"
39 #include "utilities/events.hpp" 40 #include "utilities/events.hpp"
40 #include "utilities/xmlstream.hpp" 41 #include "utilities/xmlstream.hpp"
41 42
42 #ifdef ASSERT 43 #ifdef ASSERT
43 44
128 129
129 130
130 long NMethodSweeper::_traversals = 0; // No. of stack traversals performed 131 long NMethodSweeper::_traversals = 0; // No. of stack traversals performed
131 nmethod* NMethodSweeper::_current = NULL; // Current nmethod 132 nmethod* NMethodSweeper::_current = NULL; // Current nmethod
132 int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache 133 int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache
134 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep
135 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep
136 int NMethodSweeper::_marked_count = 0; // Nof. nmethods marked for reclaim in current sweep
133 137
134 volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass 138 volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass
135 volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress. 139 volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress.
136 140
137 jint NMethodSweeper::_locked_seen = 0; 141 jint NMethodSweeper::_locked_seen = 0;
141 jlong NMethodSweeper::_last_full_flush_time = 0; 145 jlong NMethodSweeper::_last_full_flush_time = 0;
142 int NMethodSweeper::_highest_marked = 0; 146 int NMethodSweeper::_highest_marked = 0;
143 int NMethodSweeper::_dead_compile_ids = 0; 147 int NMethodSweeper::_dead_compile_ids = 0;
144 long NMethodSweeper::_last_flush_traversal_id = 0; 148 long NMethodSweeper::_last_flush_traversal_id = 0;
145 149
150 int NMethodSweeper::_number_of_flushes = 0; // Total of full traversals caused by full cache
151 int NMethodSweeper::_total_nof_methods_reclaimed = 0;
152 jlong NMethodSweeper::_total_time_sweeping = 0;
153 jlong NMethodSweeper::_total_time_this_sweep = 0;
154 jlong NMethodSweeper::_peak_sweep_time = 0;
155 jlong NMethodSweeper::_peak_sweep_fraction_time = 0;
156 jlong NMethodSweeper::_total_disconnect_time = 0;
157 jlong NMethodSweeper::_peak_disconnect_time = 0;
158
146 class MarkActivationClosure: public CodeBlobClosure { 159 class MarkActivationClosure: public CodeBlobClosure {
147 public: 160 public:
148 virtual void do_code_blob(CodeBlob* cb) { 161 virtual void do_code_blob(CodeBlob* cb) {
149 // If we see an activation belonging to a non_entrant nmethod, we mark it. 162 // If we see an activation belonging to a non_entrant nmethod, we mark it.
150 if (cb->is_nmethod() && ((nmethod*)cb)->is_not_entrant()) { 163 if (cb->is_nmethod() && ((nmethod*)cb)->is_not_entrant()) {
174 if (!sweep_in_progress() && _resweep) { 187 if (!sweep_in_progress() && _resweep) {
175 _seen = 0; 188 _seen = 0;
176 _invocations = NmethodSweepFraction; 189 _invocations = NmethodSweepFraction;
177 _current = CodeCache::first_nmethod(); 190 _current = CodeCache::first_nmethod();
178 _traversals += 1; 191 _traversals += 1;
192 _total_time_this_sweep = 0;
193
179 if (PrintMethodFlushing) { 194 if (PrintMethodFlushing) {
180 tty->print_cr("### Sweep: stack traversal %d", _traversals); 195 tty->print_cr("### Sweep: stack traversal %d", _traversals);
181 } 196 }
182 Threads::nmethods_do(&mark_activation_closure); 197 Threads::nmethods_do(&mark_activation_closure);
183 198
227 _sweep_started = 0; 242 _sweep_started = 0;
228 } 243 }
229 } 244 }
230 245
231 void NMethodSweeper::sweep_code_cache() { 246 void NMethodSweeper::sweep_code_cache() {
232 #ifdef ASSERT 247
233 jlong sweep_start; 248 jlong sweep_start_counter = os::elapsed_counter();
234 if (PrintMethodFlushing) { 249
235 sweep_start = os::javaTimeMillis(); 250 _flushed_count = 0;
236 } 251 _zombified_count = 0;
237 #endif 252 _marked_count = 0;
253
238 if (PrintMethodFlushing && Verbose) { 254 if (PrintMethodFlushing && Verbose) {
239 tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations); 255 tty->print_cr("### Sweep at %d out of %d. Invocations left: %d", _seen, CodeCache::nof_nmethods(), _invocations);
240 } 256 }
241 257
242 if (!CompileBroker::should_compile_new_jobs()) { 258 if (!CompileBroker::should_compile_new_jobs()) {
300 if (PrintMethodFlushing) { 316 if (PrintMethodFlushing) {
301 tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep"); 317 tty->print_cr("### Couldn't make progress on some nmethods so stopping sweep");
302 } 318 }
303 } 319 }
304 320
321 jlong sweep_end_counter = os::elapsed_counter();
322 jlong sweep_time = sweep_end_counter - sweep_start_counter;
323 _total_time_sweeping += sweep_time;
324 _total_time_this_sweep += sweep_time;
325 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time);
326 _total_nof_methods_reclaimed += _flushed_count;
327
328 EventSweepCodeCache event(UNTIMED);
329 if (event.should_commit()) {
330 event.set_starttime(sweep_start_counter);
331 event.set_endtime(sweep_end_counter);
332 event.set_sweepIndex(_traversals);
333 event.set_sweepFractionIndex(NmethodSweepFraction - _invocations + 1);
334 event.set_sweptCount(todo);
335 event.set_flushedCount(_flushed_count);
336 event.set_markedCount(_marked_count);
337 event.set_zombifiedCount(_zombified_count);
338 event.commit();
339 }
340
305 #ifdef ASSERT 341 #ifdef ASSERT
306 if(PrintMethodFlushing) { 342 if(PrintMethodFlushing) {
307 jlong sweep_end = os::javaTimeMillis(); 343 tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, (jlong)sweep_time);
308 tty->print_cr("### sweeper: sweep time(%d): " INT64_FORMAT, _invocations, sweep_end - sweep_start);
309 } 344 }
310 #endif 345 #endif
311 346
312 if (_invocations == 1) { 347 if (_invocations == 1) {
348 _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep);
313 log_sweep("finished"); 349 log_sweep("finished");
314 } 350 }
315 351
316 // Sweeper is the only case where memory is released, 352 // Sweeper is the only case where memory is released,
317 // check here if it is time to restart the compiler. 353 // check here if it is time to restart the compiler.
386 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); 422 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods");
387 if (PrintMethodFlushing && Verbose) { 423 if (PrintMethodFlushing && Verbose) {
388 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); 424 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm);
389 } 425 }
390 release_nmethod(nm); 426 release_nmethod(nm);
427 _flushed_count++;
391 } else { 428 } else {
392 if (PrintMethodFlushing && Verbose) { 429 if (PrintMethodFlushing && Verbose) {
393 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); 430 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm);
394 } 431 }
395 nm->mark_for_reclamation(); 432 nm->mark_for_reclamation();
396 _resweep = true; 433 _resweep = true;
434 _marked_count++;
397 SWEEP(nm); 435 SWEEP(nm);
398 } 436 }
399 } else if (nm->is_not_entrant()) { 437 } else if (nm->is_not_entrant()) {
400 // If there is no current activations of this method on the 438 // If there is no current activations of this method on the
401 // stack we can safely convert it to a zombie method 439 // stack we can safely convert it to a zombie method
403 if (PrintMethodFlushing && Verbose) { 441 if (PrintMethodFlushing && Verbose) {
404 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); 442 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
405 } 443 }
406 nm->make_zombie(); 444 nm->make_zombie();
407 _resweep = true; 445 _resweep = true;
446 _zombified_count++;
408 SWEEP(nm); 447 SWEEP(nm);
409 } else { 448 } else {
410 // Still alive, clean up its inline caches 449 // Still alive, clean up its inline caches
411 MutexLocker cl(CompiledIC_lock); 450 MutexLocker cl(CompiledIC_lock);
412 nm->cleanup_inline_caches(); 451 nm->cleanup_inline_caches();
418 } 457 }
419 } else if (nm->is_unloaded()) { 458 } else if (nm->is_unloaded()) {
420 // Unloaded code, just make it a zombie 459 // Unloaded code, just make it a zombie
421 if (PrintMethodFlushing && Verbose) 460 if (PrintMethodFlushing && Verbose)
422 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); 461 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
462
423 if (nm->is_osr_method()) { 463 if (nm->is_osr_method()) {
424 SWEEP(nm); 464 SWEEP(nm);
425 // No inline caches will ever point to osr methods, so we can just remove it 465 // No inline caches will ever point to osr methods, so we can just remove it
426 release_nmethod(nm); 466 release_nmethod(nm);
467 _flushed_count++;
427 } else { 468 } else {
428 nm->make_zombie(); 469 nm->make_zombie();
429 _resweep = true; 470 _resweep = true;
471 _zombified_count++;
430 SWEEP(nm); 472 SWEEP(nm);
431 } 473 }
432 } else { 474 } else {
433 assert(nm->is_alive(), "should be alive"); 475 assert(nm->is_alive(), "should be alive");
434 476
482 524
483 void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) { 525 void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) {
484 // If there was a race in detecting full code cache, only run 526 // If there was a race in detecting full code cache, only run
485 // one vm op for it or keep the compiler shut off 527 // one vm op for it or keep the compiler shut off
486 528
487 debug_only(jlong start = os::javaTimeMillis();) 529 jlong disconnect_start_counter = os::elapsed_counter();
488 530
489 // Traverse the code cache trying to dump the oldest nmethods 531 // Traverse the code cache trying to dump the oldest nmethods
490 int curr_max_comp_id = CompileBroker::get_compilation_id(); 532 int curr_max_comp_id = CompileBroker::get_compilation_id();
491 int flush_target = ((curr_max_comp_id - _dead_compile_ids) / CodeCacheFlushingFraction) + _dead_compile_ids; 533 int flush_target = ((curr_max_comp_id - _dead_compile_ids) / CodeCacheFlushingFraction) + _dead_compile_ids;
492 534
539 // traversal cycle and turn it back on if it clears enough space. 581 // traversal cycle and turn it back on if it clears enough space.
540 if (is_full) { 582 if (is_full) {
541 _last_full_flush_time = os::javaTimeMillis(); 583 _last_full_flush_time = os::javaTimeMillis();
542 } 584 }
543 585
586 jlong disconnect_end_counter = os::elapsed_counter();
587 jlong disconnect_time = disconnect_end_counter - disconnect_start_counter;
588 _total_disconnect_time += disconnect_time;
589 _peak_disconnect_time = MAX2(disconnect_time, _peak_disconnect_time);
590
591 EventCleanCodeCache event(UNTIMED);
592 if (event.should_commit()) {
593 event.set_starttime(disconnect_start_counter);
594 event.set_endtime(disconnect_end_counter);
595 event.set_disconnectedCount(disconnected);
596 event.set_madeNonEntrantCount(made_not_entrant);
597 event.commit();
598 }
599 _number_of_flushes++;
600
544 // After two more traversals the sweeper will get rid of unrestored nmethods 601 // After two more traversals the sweeper will get rid of unrestored nmethods
545 _last_flush_traversal_id = _traversals; 602 _last_flush_traversal_id = _traversals;
546 _resweep = true; 603 _resweep = true;
547 #ifdef ASSERT 604 #ifdef ASSERT
548 jlong end = os::javaTimeMillis(); 605
549 if(PrintMethodFlushing && Verbose) { 606 if(PrintMethodFlushing && Verbose) {
550 tty->print_cr("### sweeper: unload time: " INT64_FORMAT, end-start); 607 tty->print_cr("### sweeper: unload time: " INT64_FORMAT, (jlong)disconnect_time);
551 } 608 }
552 #endif 609 #endif
553 } 610 }
554 611
555 612