< prev index next >

src/share/vm/gc/g1/g1CollectedHeap.cpp

Print this page
rev 12504 : 8171238: Unify cleanup code used in G1 Remark and Full GC marking
Reviewed-by:


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 };


< prev index next >