src/share/vm/runtime/sweeper.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hs-comp-code-aging Sdiff src/share/vm/runtime

src/share/vm/runtime/sweeper.cpp

Print this page




 552     // Unloaded code, just make it a zombie
 553     if (PrintMethodFlushing && Verbose) {
 554       tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
 555     }
 556     if (nm->is_osr_method()) {
 557       SWEEP(nm);
 558       // No inline caches will ever point to osr methods, so we can just remove it
 559       freed_memory = nm->total_size();
 560       if (nm->is_compiled_by_c2()) {
 561         _total_nof_c2_methods_reclaimed++;
 562       }
 563       release_nmethod(nm);
 564       _flushed_count++;
 565     } else {
 566       // Code cache state change is tracked in make_zombie()
 567       nm->make_zombie();
 568       _zombified_count++;
 569       SWEEP(nm);
 570     }
 571   } else {











 572     if (UseCodeCacheFlushing) {
 573       if (!nm->is_locked_by_vm() && !nm->is_osr_method() && !nm->is_native_method()) {


 574         // Do not make native methods and OSR-methods not-entrant
 575         nm->dec_hotness_counter();
 576         // Get the initial value of the hotness counter. This value depends on the
 577         // ReservedCodeCacheSize
 578         int reset_val = hotness_counter_reset_val();
 579         int time_since_reset = reset_val - nm->hotness_counter();
 580         double threshold = -reset_val + (CodeCache::reverse_free_ratio() * NmethodSweepActivity);
 581         // The less free space in the code cache we have - the bigger reverse_free_ratio() is.
 582         // I.e., 'threshold' increases with lower available space in the code cache and a higher
 583         // NmethodSweepActivity. If the current hotness counter - which decreases from its initial
 584         // value until it is reset by stack walking - is smaller than the computed threshold, the
 585         // corresponding nmethod is considered for removal.
 586         if ((NmethodSweepActivity > 0) && (nm->hotness_counter() < threshold) && (time_since_reset > 10)) {
 587           // A method is marked as not-entrant if the method is
 588           // 1) 'old enough': nm->hotness_counter() < threshold
 589           // 2) The method was in_use for a minimum amount of time: (time_since_reset > 10)
 590           //    The second condition is necessary if we are dealing with very small code cache
 591           //    sizes (e.g., <10m) and the code cache size is too small to hold all hot methods.
 592           //    The second condition ensures that methods are not immediately made not-entrant
 593           //    after compilation.










































 594           nm->make_not_entrant();

 595           // Code cache state change is tracked in make_not_entrant()
 596           if (PrintMethodFlushing && Verbose) {
 597             tty->print_cr("### Nmethod %d/" PTR_FORMAT "made not-entrant: hotness counter %d/%d threshold %f",
 598                           nm->compile_id(), nm, nm->hotness_counter(), reset_val, threshold);
 599           }
 600         }
 601       }
 602     }
 603     // Clean-up all inline caches that point to zombie/non-reentrant methods
 604     MutexLocker cl(CompiledIC_lock);
 605     nm->cleanup_inline_caches();
 606     SWEEP(nm);
 607   }
 608   return freed_memory;
 609 }
 610 
 611 // Print out some state information about the current sweep and the
 612 // state of the code cache if it's requested.
 613 void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
 614   if (PrintMethodFlushing) {
 615     stringStream s;
 616     // Dump code cache state into a buffer before locking the tty,
 617     // because log_state() will use locks causing lock conflicts.
 618     CodeCache::log_state(&s);
 619 
 620     ttyLocker ttyl;
 621     tty->print("### sweeper: %s ", msg);
 622     if (format != NULL) {
 623       va_list ap;
 624       va_start(ap, format);
 625       tty->vprint(format, ap);
 626       va_end(ap);
 627     }
 628     tty->print_cr(s.as_string());




 552     // Unloaded code, just make it a zombie
 553     if (PrintMethodFlushing && Verbose) {
 554       tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm);
 555     }
 556     if (nm->is_osr_method()) {
 557       SWEEP(nm);
 558       // No inline caches will ever point to osr methods, so we can just remove it
 559       freed_memory = nm->total_size();
 560       if (nm->is_compiled_by_c2()) {
 561         _total_nof_c2_methods_reclaimed++;
 562       }
 563       release_nmethod(nm);
 564       _flushed_count++;
 565     } else {
 566       // Code cache state change is tracked in make_zombie()
 567       nm->make_zombie();
 568       _zombified_count++;
 569       SWEEP(nm);
 570     }
 571   } else {
 572     possibly_flush(nm);
 573     // Clean-up all inline caches that point to zombie/non-reentrant methods
 574     MutexLocker cl(CompiledIC_lock);
 575     nm->cleanup_inline_caches();
 576     SWEEP(nm);
 577   }
 578   return freed_memory;
 579 }
 580 
 581 
 582 void NMethodSweeper::possibly_flush(nmethod* nm) {
 583   if (UseCodeCacheFlushing) {
 584     if (!nm->is_locked_by_vm() && !nm->is_osr_method() && !nm->is_native_method()) {
 585       bool make_not_entrant = false;
 586 
 587       // Do not make native methods and OSR-methods not-entrant
 588       nm->dec_hotness_counter();
 589       // Get the initial value of the hotness counter. This value depends on the
 590       // ReservedCodeCacheSize
 591       int reset_val = hotness_counter_reset_val();
 592       int time_since_reset = reset_val - nm->hotness_counter();
 593       double threshold = -reset_val + (CodeCache::reverse_free_ratio() * NmethodSweepActivity);
 594       // The less free space in the code cache we have - the bigger reverse_free_ratio() is.
 595       // I.e., 'threshold' increases with lower available space in the code cache and a higher
 596       // NmethodSweepActivity. If the current hotness counter - which decreases from its initial
 597       // value until it is reset by stack walking - is smaller than the computed threshold, the
 598       // corresponding nmethod is considered for removal.
 599       if ((NmethodSweepActivity > 0) && (nm->hotness_counter() < threshold) && (time_since_reset > MinPassesBeforeFlush)) {
 600         // A method is marked as not-entrant if the method is
 601         // 1) 'old enough': nm->hotness_counter() < threshold
 602         // 2) The method was in_use for a minimum amount of time: (time_since_reset > MinPassesBeforeFlush)
 603         //    The second condition is necessary if we are dealing with very small code cache
 604         //    sizes (e.g., <10m) and the code cache size is too small to hold all hot methods.
 605         //    The second condition ensures that methods are not immediately made not-entrant
 606         //    after compilation.
 607         make_not_entrant = true;
 608       }
 609 
 610       // The stack-scanning low-cost detection didn't see the method used (which can happen for
 611       // flat profiles). Check the age counter for possible data.
 612       if (UseCodeAging && make_not_entrant && (nm->is_compiled_by_c2() || nm->is_compiled_by_c1())) {
 613         MethodCounters* mc = nm->method()->method_counters();
 614         if (mc != NULL) {
 615           // Snapshot the value as it's changed concurrently
 616           int age = mc->nmethod_age();
 617           if (MethodCounters::is_nmethod_hot(age)) {
 618             // The method has gone through flushing, and it became relatively hot that it deopted
 619             // before we could take a look at it.
 620             if (time_since_reset > MinPassesBeforeFlush * 2) {
 621               // It's been long enough, we still haven't seen it on stack.
 622               // Try to flush it, but enable counters the next time.
 623               mc->reset_nmethod_age();
 624             } else {
 625               make_not_entrant = false;
 626             }
 627           } else if (MethodCounters::is_nmethod_warm(age)) {
 628             // Method has counters enabled, and the method was used within
 629             // previous 10 sweeps. Reset the counter. Stay in the existing
 630             // compiled state.
 631             mc->reset_nmethod_age();
 632             // delay the next check
 633             nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val());
 634             make_not_entrant = false;
 635           } else if (MethodCounters::is_nmethod_age_unset(age)) {
 636             // No counters were used before. Set the counters to the detection
 637             // limit value. If the method is going to be used again it will be compiled
 638             // with counters that we're going to use for analysis the the next time.
 639             mc->reset_nmethod_age();
 640           } else {
 641             // Method was totally idle for 10 sweeps
 642             // The counter already has the initial value, flush it and may be recompile
 643             // later with counters
 644           }
 645         }
 646       }
 647 
 648       if (make_not_entrant) {
 649         nm->make_not_entrant();
 650 
 651         // Code cache state change is tracked in make_not_entrant()
 652         if (PrintMethodFlushing && Verbose) {
 653           tty->print_cr("### Nmethod %d/" PTR_FORMAT "made not-entrant: hotness counter %d/%d threshold %f",
 654               nm->compile_id(), nm, nm->hotness_counter(), reset_val, threshold);
 655         }
 656       }
 657     }
 658   }






 659 }
 660 
 661 // Print out some state information about the current sweep and the
 662 // state of the code cache if it's requested.
 663 void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
 664   if (PrintMethodFlushing) {
 665     stringStream s;
 666     // Dump code cache state into a buffer before locking the tty,
 667     // because log_state() will use locks causing lock conflicts.
 668     CodeCache::log_state(&s);
 669 
 670     ttyLocker ttyl;
 671     tty->print("### sweeper: %s ", msg);
 672     if (format != NULL) {
 673       va_list ap;
 674       va_start(ap, format);
 675       tty->vprint(format, ap);
 676       va_end(ap);
 677     }
 678     tty->print_cr(s.as_string());


src/share/vm/runtime/sweeper.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File