3511 }
3512
3513 void G1CollectedHeap::print_termination_stats(uint worker_id,
3514 double elapsed_ms,
3515 double strong_roots_ms,
3516 double term_ms,
3517 size_t term_attempts,
3518 size_t alloc_buffer_waste,
3519 size_t undo_waste) const {
3520 log_debug(gc, task, stats)
3521 ("%3d %9.2f %9.2f %6.2f "
3522 "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
3523 SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
3524 worker_id, elapsed_ms, strong_roots_ms, strong_roots_ms * 100 / elapsed_ms,
3525 term_ms, term_ms * 100 / elapsed_ms, term_attempts,
3526 (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
3527 alloc_buffer_waste * HeapWordSize / K,
3528 undo_waste * HeapWordSize / K);
3529 }
3530
3531 class G1StringSymbolTableUnlinkTask : public AbstractGangTask {
3532 private:
3533 BoolObjectClosure* _is_alive;
3534 G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
3535
3536 int _initial_string_table_size;
3537 int _initial_symbol_table_size;
3538
3539 bool _process_strings;
3540 int _strings_processed;
3541 int _strings_removed;
3542
3543 bool _process_symbols;
3544 int _symbols_processed;
3545 int _symbols_removed;
3546
3547 bool _process_string_dedup;
3548
3549 public:
3550 G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, bool process_string_dedup) :
3551 AbstractGangTask("String/Symbol Unlinking"),
3552 _is_alive(is_alive),
3553 _dedup_closure(is_alive, NULL, false),
3554 _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
3555 _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0),
3556 _process_string_dedup(process_string_dedup) {
3557
3558 _initial_string_table_size = StringTable::the_table()->table_size();
3559 _initial_symbol_table_size = SymbolTable::the_table()->table_size();
3560 if (process_strings) {
3561 StringTable::clear_parallel_claimed_index();
3562 }
3563 if (process_symbols) {
3564 SymbolTable::clear_parallel_claimed_index();
3565 }
3566 }
3567
3568 ~G1StringSymbolTableUnlinkTask() {
3569 guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size,
3570 "claim value %d after unlink less than initial string table size %d",
3571 StringTable::parallel_claimed_index(), _initial_string_table_size);
3572 guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
3573 "claim value %d after unlink less than initial symbol table size %d",
3574 SymbolTable::parallel_claimed_index(), _initial_symbol_table_size);
3575
3576 log_info(gc, stringtable)(
3577 "Cleaned string and symbol table, "
3578 "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, "
3579 "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
3580 strings_processed(), strings_removed(),
3581 symbols_processed(), symbols_removed());
3582 }
3583
3584 void work(uint worker_id) {
3585 int strings_processed = 0;
3586 int strings_removed = 0;
3587 int symbols_processed = 0;
3588 int symbols_removed = 0;
3817
3818 void work() {
3819 ResourceMark rm;
3820
3821 // One worker will clean the subklass/sibling klass tree.
3822 if (claim_clean_klass_tree_task()) {
3823 Klass::clean_subklass_tree(_is_alive);
3824 }
3825
3826 // All workers will help cleaning the classes,
3827 InstanceKlass* klass;
3828 while ((klass = claim_next_klass()) != NULL) {
3829 clean_klass(klass);
3830 }
3831 }
3832 };
3833
3834 // To minimize the remark pause times, the tasks below are done in parallel.
3835 class G1ParallelCleaningTask : public AbstractGangTask {
3836 private:
3837 G1StringSymbolTableUnlinkTask _string_symbol_task;
3838 G1CodeCacheUnloadingTask _code_cache_task;
3839 G1KlassCleaningTask _klass_cleaning_task;
3840
3841 public:
3842 // The constructor is run in the VMThread.
3843 G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
3844 AbstractGangTask("Parallel Cleaning"),
3845 _string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
3846 _code_cache_task(num_workers, is_alive, unloading_occurred),
3847 _klass_cleaning_task(is_alive) {
3848 }
3849
3850 // The parallel work done by all worker threads.
3851 void work(uint worker_id) {
3852 // Do first pass of code cache cleaning.
3853 _code_cache_task.work_first_pass(worker_id);
3854
3855 // Let the threads mark that the first pass is done.
3856 _code_cache_task.barrier_mark(worker_id);
3857
3858 // Clean the Strings and Symbols.
3859 _string_symbol_task.work(worker_id);
3860
3861 // Wait for all workers to finish the first code cache cleaning pass.
3862 _code_cache_task.barrier_wait(worker_id);
3863
3864 // Do the second code cache cleaning work, which realize on
3865 // the liveness information gathered during the first pass.
3866 _code_cache_task.work_second_pass(worker_id);
3867
3868 // Clean all klasses that were not unloaded.
3869 _klass_cleaning_task.work();
3870 }
3871 };
3872
3873
3874 void G1CollectedHeap::full_cleaning(BoolObjectClosure* is_alive,
3875 bool class_unloading_occurred) {
3876 uint n_workers = workers()->active_workers();
3877
3878 G1ParallelCleaningTask g1_unlink_task(is_alive, n_workers, class_unloading_occurred);
3879 workers()->run_task(&g1_unlink_task);
3880 }
3881
3882 void G1CollectedHeap::partial_cleaning(BoolObjectClosure* is_alive,
3883 bool process_strings,
3884 bool process_symbols,
3885 bool process_string_dedup) {
3886 if (!process_strings && !process_symbols && !process_string_dedup) {
3887 // Nothing to clean.
3888 return;
3889 }
3890
3891 G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols, process_string_dedup);
3892 workers()->run_task(&g1_unlink_task);
3893
3894 }
3895
3896 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
3897 private:
3898 DirtyCardQueueSet* _queue;
3899 G1CollectedHeap* _g1h;
3900 public:
3901 G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
3902 _queue(queue), _g1h(g1h) { }
3903
3904 virtual void work(uint worker_id) {
3905 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
3906 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
3907
3908 RedirtyLoggedCardTableEntryClosure cl(_g1h);
3909 _queue->par_apply_closure_to_all_completed_buffers(&cl);
3910
3911 phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
|
3511 }
3512
3513 void G1CollectedHeap::print_termination_stats(uint worker_id,
3514 double elapsed_ms,
3515 double strong_roots_ms,
3516 double term_ms,
3517 size_t term_attempts,
3518 size_t alloc_buffer_waste,
3519 size_t undo_waste) const {
3520 log_debug(gc, task, stats)
3521 ("%3d %9.2f %9.2f %6.2f "
3522 "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
3523 SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
3524 worker_id, elapsed_ms, strong_roots_ms, strong_roots_ms * 100 / elapsed_ms,
3525 term_ms, term_ms * 100 / elapsed_ms, term_attempts,
3526 (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
3527 alloc_buffer_waste * HeapWordSize / K,
3528 undo_waste * HeapWordSize / K);
3529 }
3530
3531 class G1StringAndSymbolCleaningTask : public AbstractGangTask {
3532 private:
3533 BoolObjectClosure* _is_alive;
3534 G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
3535
3536 int _initial_string_table_size;
3537 int _initial_symbol_table_size;
3538
3539 bool _process_strings;
3540 int _strings_processed;
3541 int _strings_removed;
3542
3543 bool _process_symbols;
3544 int _symbols_processed;
3545 int _symbols_removed;
3546
3547 bool _process_string_dedup;
3548
3549 public:
3550 G1StringAndSymbolCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, bool process_string_dedup) :
3551 AbstractGangTask("String/Symbol Unlinking"),
3552 _is_alive(is_alive),
3553 _dedup_closure(is_alive, NULL, false),
3554 _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
3555 _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0),
3556 _process_string_dedup(process_string_dedup) {
3557
3558 _initial_string_table_size = StringTable::the_table()->table_size();
3559 _initial_symbol_table_size = SymbolTable::the_table()->table_size();
3560 if (process_strings) {
3561 StringTable::clear_parallel_claimed_index();
3562 }
3563 if (process_symbols) {
3564 SymbolTable::clear_parallel_claimed_index();
3565 }
3566 }
3567
3568 ~G1StringAndSymbolCleaningTask() {
3569 guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size,
3570 "claim value %d after unlink less than initial string table size %d",
3571 StringTable::parallel_claimed_index(), _initial_string_table_size);
3572 guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
3573 "claim value %d after unlink less than initial symbol table size %d",
3574 SymbolTable::parallel_claimed_index(), _initial_symbol_table_size);
3575
3576 log_info(gc, stringtable)(
3577 "Cleaned string and symbol table, "
3578 "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, "
3579 "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
3580 strings_processed(), strings_removed(),
3581 symbols_processed(), symbols_removed());
3582 }
3583
3584 void work(uint worker_id) {
3585 int strings_processed = 0;
3586 int strings_removed = 0;
3587 int symbols_processed = 0;
3588 int symbols_removed = 0;
3817
3818 void work() {
3819 ResourceMark rm;
3820
3821 // One worker will clean the subklass/sibling klass tree.
3822 if (claim_clean_klass_tree_task()) {
3823 Klass::clean_subklass_tree(_is_alive);
3824 }
3825
3826 // All workers will help cleaning the classes,
3827 InstanceKlass* klass;
3828 while ((klass = claim_next_klass()) != NULL) {
3829 clean_klass(klass);
3830 }
3831 }
3832 };
3833
3834 // To minimize the remark pause times, the tasks below are done in parallel.
3835 class G1ParallelCleaningTask : public AbstractGangTask {
3836 private:
3837 G1StringAndSymbolCleaningTask _string_symbol_task;
3838 G1CodeCacheUnloadingTask _code_cache_task;
3839 G1KlassCleaningTask _klass_cleaning_task;
3840
3841 public:
3842 // The constructor is run in the VMThread.
3843 G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
3844 AbstractGangTask("Parallel Cleaning"),
3845 _string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
3846 _code_cache_task(num_workers, is_alive, unloading_occurred),
3847 _klass_cleaning_task(is_alive) {
3848 }
3849
3850 // The parallel work done by all worker threads.
3851 void work(uint worker_id) {
3852 // Do first pass of code cache cleaning.
3853 _code_cache_task.work_first_pass(worker_id);
3854
3855 // Let the threads mark that the first pass is done.
3856 _code_cache_task.barrier_mark(worker_id);
3857
3858 // Clean the Strings and Symbols.
3859 _string_symbol_task.work(worker_id);
3860
3861 // Wait for all workers to finish the first code cache cleaning pass.
3862 _code_cache_task.barrier_wait(worker_id);
3863
3864 // Do the second code cache cleaning work, which realize on
3865 // the liveness information gathered during the first pass.
3866 _code_cache_task.work_second_pass(worker_id);
3867
3868 // Clean all klasses that were not unloaded.
3869 _klass_cleaning_task.work();
3870 }
3871 };
3872
3873
3874 void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
3875 bool class_unloading_occurred) {
3876 uint n_workers = workers()->active_workers();
3877
3878 G1ParallelCleaningTask g1_unlink_task(is_alive, n_workers, class_unloading_occurred);
3879 workers()->run_task(&g1_unlink_task);
3880 }
3881
3882 void G1CollectedHeap::partial_cleaning(BoolObjectClosure* is_alive,
3883 bool process_strings,
3884 bool process_symbols,
3885 bool process_string_dedup) {
3886 if (!process_strings && !process_symbols && !process_string_dedup) {
3887 // Nothing to clean.
3888 return;
3889 }
3890
3891 G1StringAndSymbolCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols, process_string_dedup);
3892 workers()->run_task(&g1_unlink_task);
3893
3894 }
3895
3896 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
3897 private:
3898 DirtyCardQueueSet* _queue;
3899 G1CollectedHeap* _g1h;
3900 public:
3901 G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
3902 _queue(queue), _g1h(g1h) { }
3903
3904 virtual void work(uint worker_id) {
3905 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
3906 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
3907
3908 RedirtyLoggedCardTableEntryClosure cl(_g1h);
3909 _queue->par_apply_closure_to_all_completed_buffers(&cl);
3910
3911 phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
|