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 int _initial_string_table_size;
3535 int _initial_symbol_table_size;
3536
3537 bool _process_strings;
3538 int _strings_processed;
3539 int _strings_removed;
3540
3541 bool _process_symbols;
3542 int _symbols_processed;
3543 int _symbols_removed;
3544
3545 public:
3546 G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) :
3547 AbstractGangTask("String/Symbol Unlinking"),
3548 _is_alive(is_alive),
3549 _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
3550 _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) {
3551
3552 _initial_string_table_size = StringTable::the_table()->table_size();
3553 _initial_symbol_table_size = SymbolTable::the_table()->table_size();
3554 if (process_strings) {
3555 StringTable::clear_parallel_claimed_index();
3556 }
3557 if (process_symbols) {
3558 SymbolTable::clear_parallel_claimed_index();
3559 }
3560 }
3561
3562 ~G1StringSymbolTableUnlinkTask() {
3563 guarantee(!_process_strings || StringTable::parallel_claimed_index() >= _initial_string_table_size,
3564 "claim value %d after unlink less than initial string table size %d",
3565 StringTable::parallel_claimed_index(), _initial_string_table_size);
3566 guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
3567 "claim value %d after unlink less than initial symbol table size %d",
3568 SymbolTable::parallel_claimed_index(), _initial_symbol_table_size);
3569
3570 log_info(gc, stringtable)(
3573 "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
3574 strings_processed(), strings_removed(),
3575 symbols_processed(), symbols_removed());
3576 }
3577
3578 void work(uint worker_id) {
3579 int strings_processed = 0;
3580 int strings_removed = 0;
3581 int symbols_processed = 0;
3582 int symbols_removed = 0;
3583 if (_process_strings) {
3584 StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed);
3585 Atomic::add(strings_processed, &_strings_processed);
3586 Atomic::add(strings_removed, &_strings_removed);
3587 }
3588 if (_process_symbols) {
3589 SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed);
3590 Atomic::add(symbols_processed, &_symbols_processed);
3591 Atomic::add(symbols_removed, &_symbols_removed);
3592 }
3593 }
3594
3595 size_t strings_processed() const { return (size_t)_strings_processed; }
3596 size_t strings_removed() const { return (size_t)_strings_removed; }
3597
3598 size_t symbols_processed() const { return (size_t)_symbols_processed; }
3599 size_t symbols_removed() const { return (size_t)_symbols_removed; }
3600 };
3601
3602 class G1CodeCacheUnloadingTask VALUE_OBJ_CLASS_SPEC {
3603 private:
3604 static Monitor* _lock;
3605
3606 BoolObjectClosure* const _is_alive;
3607 const bool _unloading_occurred;
3608 const uint _num_workers;
3609
3610 // Variables used to claim nmethods.
3611 CompiledMethod* _first_nmethod;
3612 volatile CompiledMethod* _claimed_nmethod;
3814 Klass::clean_subklass_tree(_is_alive);
3815 }
3816
3817 // All workers will help cleaning the classes,
3818 InstanceKlass* klass;
3819 while ((klass = claim_next_klass()) != NULL) {
3820 clean_klass(klass);
3821 }
3822 }
3823 };
3824
3825 // To minimize the remark pause times, the tasks below are done in parallel.
3826 class G1ParallelCleaningTask : public AbstractGangTask {
3827 private:
3828 G1StringSymbolTableUnlinkTask _string_symbol_task;
3829 G1CodeCacheUnloadingTask _code_cache_task;
3830 G1KlassCleaningTask _klass_cleaning_task;
3831
3832 public:
3833 // The constructor is run in the VMThread.
3834 G1ParallelCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, uint num_workers, bool unloading_occurred) :
3835 AbstractGangTask("Parallel Cleaning"),
3836 _string_symbol_task(is_alive, process_strings, process_symbols),
3837 _code_cache_task(num_workers, is_alive, unloading_occurred),
3838 _klass_cleaning_task(is_alive) {
3839 }
3840
3841 // The parallel work done by all worker threads.
3842 void work(uint worker_id) {
3843 // Do first pass of code cache cleaning.
3844 _code_cache_task.work_first_pass(worker_id);
3845
3846 // Let the threads mark that the first pass is done.
3847 _code_cache_task.barrier_mark(worker_id);
3848
3849 // Clean the Strings and Symbols.
3850 _string_symbol_task.work(worker_id);
3851
3852 // Wait for all workers to finish the first code cache cleaning pass.
3853 _code_cache_task.barrier_wait(worker_id);
3854
3855 // Do the second code cache cleaning work, which realize on
3856 // the liveness information gathered during the first pass.
3857 _code_cache_task.work_second_pass(worker_id);
3858
3859 // Clean all klasses that were not unloaded.
3860 _klass_cleaning_task.work();
3861 }
3862 };
3863
3864
3865 void G1CollectedHeap::parallel_cleaning(BoolObjectClosure* is_alive,
3866 bool process_strings,
3867 bool process_symbols,
3868 bool class_unloading_occurred) {
3869 uint n_workers = workers()->active_workers();
3870
3871 G1ParallelCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols,
3872 n_workers, class_unloading_occurred);
3873 workers()->run_task(&g1_unlink_task);
3874 }
3875
3876 void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive,
3877 bool process_strings, bool process_symbols) {
3878 { // Timing scope
3879 G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols);
3880 workers()->run_task(&g1_unlink_task);
3881 }
3882 }
3883
3884 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
3885 private:
3886 DirtyCardQueueSet* _queue;
3887 G1CollectedHeap* _g1h;
3888 public:
3889 G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
3890 _queue(queue), _g1h(g1h) { }
3891
3892 virtual void work(uint worker_id) {
3893 G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
3894 G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
3895
3896 RedirtyLoggedCardTableEntryClosure cl(_g1h);
3897 _queue->par_apply_closure_to_all_completed_buffers(&cl);
3898
3899 phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
3900 }
3901 };
|
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)(
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;
3589 if (_process_strings) {
3590 StringTable::possibly_parallel_unlink(_is_alive, &strings_processed, &strings_removed);
3591 Atomic::add(strings_processed, &_strings_processed);
3592 Atomic::add(strings_removed, &_strings_removed);
3593 }
3594 if (_process_symbols) {
3595 SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed);
3596 Atomic::add(symbols_processed, &_symbols_processed);
3597 Atomic::add(symbols_removed, &_symbols_removed);
3598 }
3599 if (_process_string_dedup) {
3600 G1StringDedup::parallel_unlink(&_dedup_closure, worker_id);
3601 }
3602 }
3603
3604 size_t strings_processed() const { return (size_t)_strings_processed; }
3605 size_t strings_removed() const { return (size_t)_strings_removed; }
3606
3607 size_t symbols_processed() const { return (size_t)_symbols_processed; }
3608 size_t symbols_removed() const { return (size_t)_symbols_removed; }
3609 };
3610
3611 class G1CodeCacheUnloadingTask VALUE_OBJ_CLASS_SPEC {
3612 private:
3613 static Monitor* _lock;
3614
3615 BoolObjectClosure* const _is_alive;
3616 const bool _unloading_occurred;
3617 const uint _num_workers;
3618
3619 // Variables used to claim nmethods.
3620 CompiledMethod* _first_nmethod;
3621 volatile CompiledMethod* _claimed_nmethod;
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());
3912 }
3913 };
|