Mercurial > hg > graal-compiler
comparison src/share/vm/runtime/sweeper.cpp @ 14518:d8041d695d19
Merged with jdk9/dev/hotspot changeset 3812c088b945
author | twisti |
---|---|
date | Tue, 11 Mar 2014 18:45:59 -0700 |
parents | 2d4a8d3d286b abec000618bf |
children | 4ca6dc0799b6 |
comparison
equal
deleted
inserted
replaced
14141:f97c5ec83832 | 14518:d8041d695d19 |
---|---|
127 #define SWEEP(nm) | 127 #define SWEEP(nm) |
128 #endif | 128 #endif |
129 | 129 |
130 nmethod* NMethodSweeper::_current = NULL; // Current nmethod | 130 nmethod* NMethodSweeper::_current = NULL; // Current nmethod |
131 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. | 131 long NMethodSweeper::_traversals = 0; // Stack scan count, also sweep ID. |
132 long NMethodSweeper::_total_nof_code_cache_sweeps = 0; // Total number of full sweeps of the code cache | |
132 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper | 133 long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper |
133 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened | 134 long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened |
134 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache | 135 int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache |
135 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep | 136 int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep |
136 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep | 137 int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep |
141 volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper | 142 volatile int NMethodSweeper::_sweep_started = 0; // Flag to control conc sweeper |
142 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: | 143 volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: |
143 // 1) alive -> not_entrant | 144 // 1) alive -> not_entrant |
144 // 2) not_entrant -> zombie | 145 // 2) not_entrant -> zombie |
145 // 3) zombie -> marked_for_reclamation | 146 // 3) zombie -> marked_for_reclamation |
146 | 147 int NMethodSweeper::_hotness_counter_reset_val = 0; |
147 int NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed | 148 |
148 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping | 149 long NMethodSweeper::_total_nof_methods_reclaimed = 0; // Accumulated nof methods flushed |
149 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep | 150 long NMethodSweeper::_total_nof_c2_methods_reclaimed = 0; // Accumulated nof methods flushed |
150 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep | 151 size_t NMethodSweeper::_total_flushed_size = 0; // Total number of bytes flushed from the code cache |
151 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction | 152 Tickspan NMethodSweeper::_total_time_sweeping; // Accumulated time sweeping |
152 int NMethodSweeper::_hotness_counter_reset_val = 0; | 153 Tickspan NMethodSweeper::_total_time_this_sweep; // Total time this sweep |
154 Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep | |
155 Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction | |
156 | |
153 | 157 |
154 | 158 |
155 class MarkActivationClosure: public CodeBlobClosure { | 159 class MarkActivationClosure: public CodeBlobClosure { |
156 public: | 160 public: |
157 virtual void do_code_blob(CodeBlob* cb) { | 161 virtual void do_code_blob(CodeBlob* cb) { |
255 // As a result, we invoke the sweeper after | 259 // As a result, we invoke the sweeper after |
256 // 15 invocations of 'mark_active_nmethods. | 260 // 15 invocations of 'mark_active_nmethods. |
257 // Large ReservedCodeCacheSize: (e.g., 256M + code Cache is 90% full). The formula | 261 // Large ReservedCodeCacheSize: (e.g., 256M + code Cache is 90% full). The formula |
258 // computes: (256 / 16) - 10 = 6. | 262 // computes: (256 / 16) - 10 = 6. |
259 if (!_should_sweep) { | 263 if (!_should_sweep) { |
260 int time_since_last_sweep = _time_counter - _last_sweep; | 264 const int time_since_last_sweep = _time_counter - _last_sweep; |
261 double wait_until_next_sweep = (ReservedCodeCacheSize / (16 * M)) - time_since_last_sweep - | 265 // ReservedCodeCacheSize has an 'unsigned' type. We need a 'signed' type for max_wait_time, |
262 CodeCache::reverse_free_ratio(); | 266 // since 'time_since_last_sweep' can be larger than 'max_wait_time'. If that happens using |
267 // an unsigned type would cause an underflow (wait_until_next_sweep becomes a large positive | |
268 // value) that disables the intended periodic sweeps. | |
269 const int max_wait_time = ReservedCodeCacheSize / (16 * M); | |
270 double wait_until_next_sweep = max_wait_time - time_since_last_sweep - CodeCache::reverse_free_ratio(); | |
271 assert(wait_until_next_sweep <= (double)max_wait_time, "Calculation of code cache sweeper interval is incorrect"); | |
263 | 272 |
264 if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) { | 273 if ((wait_until_next_sweep <= 0.0) || !CompileBroker::should_compile_new_jobs()) { |
265 _should_sweep = true; | 274 _should_sweep = true; |
266 } | 275 } |
267 } | 276 } |
285 _sweep_fractions_left--; | 294 _sweep_fractions_left--; |
286 } | 295 } |
287 | 296 |
288 // We are done with sweeping the code cache once. | 297 // We are done with sweeping the code cache once. |
289 if (_sweep_fractions_left == 0) { | 298 if (_sweep_fractions_left == 0) { |
299 _total_nof_code_cache_sweeps++; | |
290 _last_sweep = _time_counter; | 300 _last_sweep = _time_counter; |
291 // Reset flag; temporarily disables sweeper | 301 // Reset flag; temporarily disables sweeper |
292 _should_sweep = false; | 302 _should_sweep = false; |
293 // If there was enough state change, 'possibly_enable_sweeper()' | 303 // If there was enough state change, 'possibly_enable_sweeper()' |
294 // sets '_should_sweep' to true | 304 // sets '_should_sweep' to true |
297 // can further increase by calls to 'report_state_change'. | 307 // can further increase by calls to 'report_state_change'. |
298 if (_should_sweep) { | 308 if (_should_sweep) { |
299 _bytes_changed = 0; | 309 _bytes_changed = 0; |
300 } | 310 } |
301 } | 311 } |
302 _sweep_started = 0; | 312 // Release work, because another compiler thread could continue. |
313 OrderAccess::release_store((int*)&_sweep_started, 0); | |
303 } | 314 } |
304 } | 315 } |
305 | 316 |
306 void NMethodSweeper::sweep_code_cache() { | 317 void NMethodSweeper::sweep_code_cache() { |
307 Ticks sweep_start_counter = Ticks::now(); | 318 Ticks sweep_start_counter = Ticks::now(); |
371 const Ticks sweep_end_counter = Ticks::now(); | 382 const Ticks sweep_end_counter = Ticks::now(); |
372 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; | 383 const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; |
373 _total_time_sweeping += sweep_time; | 384 _total_time_sweeping += sweep_time; |
374 _total_time_this_sweep += sweep_time; | 385 _total_time_this_sweep += sweep_time; |
375 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); | 386 _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); |
387 _total_flushed_size += freed_memory; | |
376 _total_nof_methods_reclaimed += _flushed_count; | 388 _total_nof_methods_reclaimed += _flushed_count; |
377 | 389 |
378 EventSweepCodeCache event(UNTIMED); | 390 EventSweepCodeCache event(UNTIMED); |
379 if (event.should_commit()) { | 391 if (event.should_commit()) { |
380 event.set_starttime(sweep_start_counter); | 392 event.set_starttime(sweep_start_counter); |
510 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); | 522 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); |
511 if (PrintMethodFlushing && Verbose) { | 523 if (PrintMethodFlushing && Verbose) { |
512 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); | 524 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); |
513 } | 525 } |
514 freed_memory = nm->total_size(); | 526 freed_memory = nm->total_size(); |
527 if (nm->is_compiled_by_c2()) { | |
528 _total_nof_c2_methods_reclaimed++; | |
529 } | |
515 release_nmethod(nm); | 530 release_nmethod(nm); |
516 _flushed_count++; | 531 _flushed_count++; |
517 } else { | 532 } else { |
518 if (PrintMethodFlushing && Verbose) { | 533 if (PrintMethodFlushing && Verbose) { |
519 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); | 534 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); |
548 } | 563 } |
549 if (nm->is_osr_method()) { | 564 if (nm->is_osr_method()) { |
550 SWEEP(nm); | 565 SWEEP(nm); |
551 // No inline caches will ever point to osr methods, so we can just remove it | 566 // No inline caches will ever point to osr methods, so we can just remove it |
552 freed_memory = nm->total_size(); | 567 freed_memory = nm->total_size(); |
568 if (nm->is_compiled_by_c2()) { | |
569 _total_nof_c2_methods_reclaimed++; | |
570 } | |
553 release_nmethod(nm); | 571 release_nmethod(nm); |
554 _flushed_count++; | 572 _flushed_count++; |
555 } else { | 573 } else { |
556 // Code cache state change is tracked in make_zombie() | 574 // Code cache state change is tracked in make_zombie() |
557 nm->make_zombie(); | 575 nm->make_zombie(); |
635 xtty->print(s.as_string()); | 653 xtty->print(s.as_string()); |
636 xtty->stamp(); | 654 xtty->stamp(); |
637 xtty->end_elem(); | 655 xtty->end_elem(); |
638 } | 656 } |
639 } | 657 } |
658 | |
659 void NMethodSweeper::print() { | |
660 ttyLocker ttyl; | |
661 tty->print_cr("Code cache sweeper statistics:"); | |
662 tty->print_cr(" Total sweep time: %1.0lfms", (double)_total_time_sweeping.value()/1000000); | |
663 tty->print_cr(" Total number of full sweeps: %ld", _total_nof_code_cache_sweeps); | |
664 tty->print_cr(" Total number of flushed methods: %ld(%ld C2 methods)", _total_nof_methods_reclaimed, | |
665 _total_nof_c2_methods_reclaimed); | |
666 tty->print_cr(" Total size of flushed methods: " SIZE_FORMAT "kB", _total_flushed_size/K); | |
667 } |