Mercurial > hg > graal-jvmci-8
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 |