< prev index next >

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

Print this page




   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/metadataOnStackMark.hpp"
  27 #include "classfile/stringTable.hpp"
  28 #include "classfile/symbolTable.hpp"
  29 #include "code/codeCache.hpp"
  30 #include "code/icBuffer.hpp"
  31 #include "gc/g1/g1Allocator.inline.hpp"
  32 #include "gc/g1/g1BarrierSet.hpp"
  33 #include "gc/g1/g1CollectedHeap.inline.hpp"
  34 #include "gc/g1/g1CollectionSet.hpp"
  35 #include "gc/g1/g1CollectorPolicy.hpp"
  36 #include "gc/g1/g1CollectorState.hpp"
  37 #include "gc/g1/g1ConcurrentRefine.hpp"
  38 #include "gc/g1/g1ConcurrentRefineThread.hpp"
  39 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
  40 #include "gc/g1/g1EvacStats.inline.hpp"
  41 #include "gc/g1/g1FullCollector.hpp"
  42 #include "gc/g1/g1GCPhaseTimes.hpp"
  43 #include "gc/g1/g1HeapSizingPolicy.hpp"
  44 #include "gc/g1/g1HeapTransition.hpp"
  45 #include "gc/g1/g1HeapVerifier.hpp"
  46 #include "gc/g1/g1HotCardCache.hpp"
  47 #include "gc/g1/g1MemoryPool.hpp"
  48 #include "gc/g1/g1OopClosures.inline.hpp"


3239 }
3240 
3241 void G1CollectedHeap::print_termination_stats(uint worker_id,
3242                                               double elapsed_ms,
3243                                               double strong_roots_ms,
3244                                               double term_ms,
3245                                               size_t term_attempts,
3246                                               size_t alloc_buffer_waste,
3247                                               size_t undo_waste) const {
3248   log_debug(gc, task, stats)
3249               ("%3d %9.2f %9.2f %6.2f "
3250                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
3251                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
3252                worker_id, elapsed_ms, strong_roots_ms, strong_roots_ms * 100 / elapsed_ms,
3253                term_ms, term_ms * 100 / elapsed_ms, term_attempts,
3254                (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
3255                alloc_buffer_waste * HeapWordSize / K,
3256                undo_waste * HeapWordSize / K);
3257 }
3258 
3259 class G1StringAndSymbolCleaningTask : public AbstractGangTask {
3260 private:
3261   BoolObjectClosure* _is_alive;
3262   G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
3263   OopStorage::ParState<false /* concurrent */, false /* const */> _par_state_string;
3264 
3265   int _initial_string_table_size;
3266   int _initial_symbol_table_size;
3267 
3268   bool  _process_strings;
3269   int _strings_processed;
3270   int _strings_removed;
3271 
3272   bool  _process_symbols;
3273   int _symbols_processed;
3274   int _symbols_removed;
3275 
3276   bool _process_string_dedup;
3277 
3278 public:
3279   G1StringAndSymbolCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, bool process_string_dedup) :
3280     AbstractGangTask("String/Symbol Unlinking"),
3281     _is_alive(is_alive),
3282     _dedup_closure(is_alive, NULL, false),
3283     _par_state_string(StringTable::weak_storage()),
3284     _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
3285     _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0),
3286     _process_string_dedup(process_string_dedup) {
3287 
3288     _initial_string_table_size = (int) StringTable::the_table()->table_size();
3289     _initial_symbol_table_size = SymbolTable::the_table()->table_size();
3290     if (process_symbols) {
3291       SymbolTable::clear_parallel_claimed_index();
3292     }
3293     if (process_strings) {
3294       StringTable::reset_dead_counter();
3295     }
3296   }
3297 
3298   ~G1StringAndSymbolCleaningTask() {
3299     guarantee(!_process_symbols || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
3300               "claim value %d after unlink less than initial symbol table size %d",
3301               SymbolTable::parallel_claimed_index(), _initial_symbol_table_size);
3302 
3303     log_info(gc, stringtable)(
3304         "Cleaned string and symbol table, "
3305         "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, "
3306         "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
3307         strings_processed(), strings_removed(),
3308         symbols_processed(), symbols_removed());
3309     if (_process_strings) {
3310       StringTable::finish_dead_counter();
3311     }
3312   }
3313 
3314   void work(uint worker_id) {
3315     int strings_processed = 0;
3316     int strings_removed = 0;
3317     int symbols_processed = 0;
3318     int symbols_removed = 0;
3319     if (_process_strings) {
3320       StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed);
3321       Atomic::add(strings_processed, &_strings_processed);
3322       Atomic::add(strings_removed, &_strings_removed);
3323     }
3324     if (_process_symbols) {
3325       SymbolTable::possibly_parallel_unlink(&symbols_processed, &symbols_removed);
3326       Atomic::add(symbols_processed, &_symbols_processed);
3327       Atomic::add(symbols_removed, &_symbols_removed);
3328     }
3329     if (_process_string_dedup) {
3330       G1StringDedup::parallel_unlink(&_dedup_closure, worker_id);
3331     }
3332   }
3333 
3334   size_t strings_processed() const { return (size_t)_strings_processed; }
3335   size_t strings_removed()   const { return (size_t)_strings_removed; }
3336 
3337   size_t symbols_processed() const { return (size_t)_symbols_processed; }
3338   size_t symbols_removed()   const { return (size_t)_symbols_removed; }
3339 };
3340 
3341 class G1CodeCacheUnloadingTask {
3342 private:
3343   static Monitor* _lock;
3344 
3345   BoolObjectClosure* const _is_alive;
3346   const bool               _unloading_occurred;
3347   const uint               _num_workers;
3348 
3349   // Variables used to claim nmethods.
3350   CompiledMethod* _first_nmethod;
3351   CompiledMethod* volatile _claimed_nmethod;
3352 
3353   // The list of nmethods that need to be processed by the second pass.
3354   CompiledMethod* volatile _postponed_list;
3355   volatile uint            _num_entered_barrier;
3356 
3357  public:
3358   G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :


3568   bool claim_resolved_method_task() {
3569     if (_resolved_method_task_claimed) {
3570       return false;
3571     }
3572     return Atomic::cmpxchg(1, &_resolved_method_task_claimed, 0) == 0;
3573   }
3574 
3575   // These aren't big, one thread can do it all.
3576   void work() {
3577     if (claim_resolved_method_task()) {
3578       ResolvedMethodTable::unlink();
3579     }
3580   }
3581 };
3582 
3583 
3584 // To minimize the remark pause times, the tasks below are done in parallel.
3585 class G1ParallelCleaningTask : public AbstractGangTask {
3586 private:
3587   bool                          _unloading_occurred;
3588   G1StringAndSymbolCleaningTask _string_symbol_task;
3589   G1CodeCacheUnloadingTask      _code_cache_task;
3590   G1KlassCleaningTask           _klass_cleaning_task;
3591   G1ResolvedMethodCleaningTask  _resolved_method_cleaning_task;
3592 
3593 public:
3594   // The constructor is run in the VMThread.
3595   G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
3596       AbstractGangTask("Parallel Cleaning"),
3597       _unloading_occurred(unloading_occurred),
3598       _string_symbol_task(is_alive, true, true, G1StringDedup::is_enabled()),
3599       _code_cache_task(num_workers, is_alive, unloading_occurred),
3600       _klass_cleaning_task(),
3601       _resolved_method_cleaning_task() {
3602   }
3603 
3604   // The parallel work done by all worker threads.
3605   void work(uint worker_id) {
3606     // Do first pass of code cache cleaning.
3607     _code_cache_task.work_first_pass(worker_id);
3608 
3609     // Let the threads mark that the first pass is done.
3610     _code_cache_task.barrier_mark(worker_id);
3611 
3612     // Clean the Strings and Symbols.
3613     _string_symbol_task.work(worker_id);
3614 
3615     // Clean unreferenced things in the ResolvedMethodTable
3616     _resolved_method_cleaning_task.work();
3617 
3618     // Wait for all workers to finish the first code cache cleaning pass.
3619     _code_cache_task.barrier_wait(worker_id);
3620 
3621     // Do the second code cache cleaning work, which realize on
3622     // the liveness information gathered during the first pass.
3623     _code_cache_task.work_second_pass(worker_id);
3624 
3625     // Clean all klasses that were not unloaded.
3626     // The weak metadata in klass doesn't need to be
3627     // processed if there was no unloading.
3628     if (_unloading_occurred) {
3629       _klass_cleaning_task.work();
3630     }
3631   }
3632 };
3633 
3634 
3635 void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
3636                                         bool class_unloading_occurred) {
3637   uint n_workers = workers()->active_workers();
3638 
3639   G1ParallelCleaningTask g1_unlink_task(is_alive, n_workers, class_unloading_occurred);
3640   workers()->run_task(&g1_unlink_task);
3641 }
3642 
3643 void G1CollectedHeap::partial_cleaning(BoolObjectClosure* is_alive,
3644                                        bool process_strings,
3645                                        bool process_symbols,
3646                                        bool process_string_dedup) {
3647   if (!process_strings && !process_symbols && !process_string_dedup) {
3648     // Nothing to clean.
3649     return;
3650   }
3651 
3652   G1StringAndSymbolCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols, process_string_dedup);
3653   workers()->run_task(&g1_unlink_task);
3654 
3655 }
3656 
3657 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
3658  private:
3659   DirtyCardQueueSet* _queue;
3660   G1CollectedHeap* _g1h;
3661  public:
3662   G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
3663     _queue(queue), _g1h(g1h) { }
3664 
3665   virtual void work(uint worker_id) {
3666     G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
3667     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
3668 
3669     RedirtyLoggedCardTableEntryClosure cl(_g1h);
3670     _queue->par_apply_closure_to_all_completed_buffers(&cl);
3671 
3672     phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
3673   }
3674 };


4028   phase_times->record_par_time(par_time_ms);
4029 
4030   double code_root_fixup_time_ms =
4031         (os::elapsedTime() - end_par_time_sec) * 1000.0;
4032   phase_times->record_code_root_fixup_time(code_root_fixup_time_ms);
4033 }
4034 
4035 void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
4036   // Also cleans the card table from temporary duplicate detection information used
4037   // during UpdateRS/ScanRS.
4038   g1_rem_set()->cleanup_after_oops_into_collection_set_do();
4039 
4040   // Process any discovered reference objects - we have
4041   // to do this _before_ we retire the GC alloc regions
4042   // as we may have to copy some 'reachable' referent
4043   // objects (and their reachable sub-graphs) that were
4044   // not copied during the pause.
4045   process_discovered_references(per_thread_states);
4046 
4047   // FIXME
4048   // CM's reference processing also cleans up the string and symbol tables.
4049   // Should we do that here also? We could, but it is a serial operation
4050   // and could significantly increase the pause time.
4051 
4052   G1STWIsAliveClosure is_alive(this);
4053   G1KeepAliveClosure keep_alive(this);
4054 
4055   {
4056     double start = os::elapsedTime();
4057 
4058     WeakProcessor::weak_oops_do(&is_alive, &keep_alive);
4059 
4060     double time_ms = (os::elapsedTime() - start) * 1000.0;
4061     g1_policy()->phase_times()->record_weak_ref_proc_time(time_ms);
4062   }
4063 
4064   if (G1StringDedup::is_enabled()) {
4065     double fixup_start = os::elapsedTime();
4066 
4067     G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive, true, g1_policy()->phase_times());
4068 




   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/metadataOnStackMark.hpp"
  27 #include "classfile/stringTable.hpp"

  28 #include "code/codeCache.hpp"
  29 #include "code/icBuffer.hpp"
  30 #include "gc/g1/g1Allocator.inline.hpp"
  31 #include "gc/g1/g1BarrierSet.hpp"
  32 #include "gc/g1/g1CollectedHeap.inline.hpp"
  33 #include "gc/g1/g1CollectionSet.hpp"
  34 #include "gc/g1/g1CollectorPolicy.hpp"
  35 #include "gc/g1/g1CollectorState.hpp"
  36 #include "gc/g1/g1ConcurrentRefine.hpp"
  37 #include "gc/g1/g1ConcurrentRefineThread.hpp"
  38 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
  39 #include "gc/g1/g1EvacStats.inline.hpp"
  40 #include "gc/g1/g1FullCollector.hpp"
  41 #include "gc/g1/g1GCPhaseTimes.hpp"
  42 #include "gc/g1/g1HeapSizingPolicy.hpp"
  43 #include "gc/g1/g1HeapTransition.hpp"
  44 #include "gc/g1/g1HeapVerifier.hpp"
  45 #include "gc/g1/g1HotCardCache.hpp"
  46 #include "gc/g1/g1MemoryPool.hpp"
  47 #include "gc/g1/g1OopClosures.inline.hpp"


3238 }
3239 
3240 void G1CollectedHeap::print_termination_stats(uint worker_id,
3241                                               double elapsed_ms,
3242                                               double strong_roots_ms,
3243                                               double term_ms,
3244                                               size_t term_attempts,
3245                                               size_t alloc_buffer_waste,
3246                                               size_t undo_waste) const {
3247   log_debug(gc, task, stats)
3248               ("%3d %9.2f %9.2f %6.2f "
3249                "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
3250                SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
3251                worker_id, elapsed_ms, strong_roots_ms, strong_roots_ms * 100 / elapsed_ms,
3252                term_ms, term_ms * 100 / elapsed_ms, term_attempts,
3253                (alloc_buffer_waste + undo_waste) * HeapWordSize / K,
3254                alloc_buffer_waste * HeapWordSize / K,
3255                undo_waste * HeapWordSize / K);
3256 }
3257 
3258 class G1StringCleaningTask : public AbstractGangTask {
3259 private:
3260   BoolObjectClosure* _is_alive;
3261   G1StringDedupUnlinkOrOopsDoClosure _dedup_closure;
3262   OopStorage::ParState<false /* concurrent */, false /* const */> _par_state_string;
3263 
3264   int _initial_string_table_size;

3265 
3266   bool  _process_strings;
3267   int _strings_processed;
3268   int _strings_removed;
3269 




3270   bool _process_string_dedup;
3271 
3272 public:
3273   G1StringCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_string_dedup) :
3274     AbstractGangTask("String Unlinking"),
3275     _is_alive(is_alive),
3276     _dedup_closure(is_alive, NULL, false),
3277     _par_state_string(StringTable::weak_storage()),
3278     _process_strings(process_strings), _strings_processed(0), _strings_removed(0),

3279     _process_string_dedup(process_string_dedup) {
3280 
3281     _initial_string_table_size = (int) StringTable::the_table()->table_size();




3282     if (process_strings) {
3283       StringTable::reset_dead_counter();
3284     }
3285   }
3286 
3287   ~G1StringCleaningTask() {




3288     log_info(gc, stringtable)(
3289         "Cleaned string table, "
3290         "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
3291         strings_processed(), strings_removed());


3292     if (_process_strings) {
3293       StringTable::finish_dead_counter();
3294     }
3295   }
3296 
3297   void work(uint worker_id) {
3298     int strings_processed = 0;
3299     int strings_removed = 0;


3300     if (_process_strings) {
3301       StringTable::possibly_parallel_unlink(&_par_state_string, _is_alive, &strings_processed, &strings_removed);
3302       Atomic::add(strings_processed, &_strings_processed);
3303       Atomic::add(strings_removed, &_strings_removed);
3304     }





3305     if (_process_string_dedup) {
3306       G1StringDedup::parallel_unlink(&_dedup_closure, worker_id);
3307     }
3308   }
3309 
3310   size_t strings_processed() const { return (size_t)_strings_processed; }
3311   size_t strings_removed()   const { return (size_t)_strings_removed; }



3312 };
3313 
3314 class G1CodeCacheUnloadingTask {
3315 private:
3316   static Monitor* _lock;
3317 
3318   BoolObjectClosure* const _is_alive;
3319   const bool               _unloading_occurred;
3320   const uint               _num_workers;
3321 
3322   // Variables used to claim nmethods.
3323   CompiledMethod* _first_nmethod;
3324   CompiledMethod* volatile _claimed_nmethod;
3325 
3326   // The list of nmethods that need to be processed by the second pass.
3327   CompiledMethod* volatile _postponed_list;
3328   volatile uint            _num_entered_barrier;
3329 
3330  public:
3331   G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :


3541   bool claim_resolved_method_task() {
3542     if (_resolved_method_task_claimed) {
3543       return false;
3544     }
3545     return Atomic::cmpxchg(1, &_resolved_method_task_claimed, 0) == 0;
3546   }
3547 
3548   // These aren't big, one thread can do it all.
3549   void work() {
3550     if (claim_resolved_method_task()) {
3551       ResolvedMethodTable::unlink();
3552     }
3553   }
3554 };
3555 
3556 
3557 // To minimize the remark pause times, the tasks below are done in parallel.
3558 class G1ParallelCleaningTask : public AbstractGangTask {
3559 private:
3560   bool                          _unloading_occurred;
3561   G1StringCleaningTask          _string_task;
3562   G1CodeCacheUnloadingTask      _code_cache_task;
3563   G1KlassCleaningTask           _klass_cleaning_task;
3564   G1ResolvedMethodCleaningTask  _resolved_method_cleaning_task;
3565 
3566 public:
3567   // The constructor is run in the VMThread.
3568   G1ParallelCleaningTask(BoolObjectClosure* is_alive, uint num_workers, bool unloading_occurred) :
3569       AbstractGangTask("Parallel Cleaning"),
3570       _unloading_occurred(unloading_occurred),
3571       _string_task(is_alive, true, G1StringDedup::is_enabled()),
3572       _code_cache_task(num_workers, is_alive, unloading_occurred),
3573       _klass_cleaning_task(),
3574       _resolved_method_cleaning_task() {
3575   }
3576 
3577   // The parallel work done by all worker threads.
3578   void work(uint worker_id) {
3579     // Do first pass of code cache cleaning.
3580     _code_cache_task.work_first_pass(worker_id);
3581 
3582     // Let the threads mark that the first pass is done.
3583     _code_cache_task.barrier_mark(worker_id);
3584 
3585     // Clean the Strings.
3586     _string_task.work(worker_id);
3587 
3588     // Clean unreferenced things in the ResolvedMethodTable
3589     _resolved_method_cleaning_task.work();
3590 
3591     // Wait for all workers to finish the first code cache cleaning pass.
3592     _code_cache_task.barrier_wait(worker_id);
3593 
3594     // Do the second code cache cleaning work, which realize on
3595     // the liveness information gathered during the first pass.
3596     _code_cache_task.work_second_pass(worker_id);
3597 
3598     // Clean all klasses that were not unloaded.
3599     // The weak metadata in klass doesn't need to be
3600     // processed if there was no unloading.
3601     if (_unloading_occurred) {
3602       _klass_cleaning_task.work();
3603     }
3604   }
3605 };
3606 
3607 
3608 void G1CollectedHeap::complete_cleaning(BoolObjectClosure* is_alive,
3609                                         bool class_unloading_occurred) {
3610   uint n_workers = workers()->active_workers();
3611 
3612   G1ParallelCleaningTask g1_unlink_task(is_alive, n_workers, class_unloading_occurred);
3613   workers()->run_task(&g1_unlink_task);
3614 }
3615 
3616 void G1CollectedHeap::partial_cleaning(BoolObjectClosure* is_alive,
3617                                        bool process_strings,

3618                                        bool process_string_dedup) {
3619   if (!process_strings && !process_string_dedup) {
3620     // Nothing to clean.
3621     return;
3622   }
3623 
3624   G1StringCleaningTask g1_unlink_task(is_alive, process_strings, process_string_dedup);
3625   workers()->run_task(&g1_unlink_task);

3626 }
3627 
3628 class G1RedirtyLoggedCardsTask : public AbstractGangTask {
3629  private:
3630   DirtyCardQueueSet* _queue;
3631   G1CollectedHeap* _g1h;
3632  public:
3633   G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue, G1CollectedHeap* g1h) : AbstractGangTask("Redirty Cards"),
3634     _queue(queue), _g1h(g1h) { }
3635 
3636   virtual void work(uint worker_id) {
3637     G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
3638     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::RedirtyCards, worker_id);
3639 
3640     RedirtyLoggedCardTableEntryClosure cl(_g1h);
3641     _queue->par_apply_closure_to_all_completed_buffers(&cl);
3642 
3643     phase_times->record_thread_work_item(G1GCPhaseTimes::RedirtyCards, worker_id, cl.num_dirtied());
3644   }
3645 };


3999   phase_times->record_par_time(par_time_ms);
4000 
4001   double code_root_fixup_time_ms =
4002         (os::elapsedTime() - end_par_time_sec) * 1000.0;
4003   phase_times->record_code_root_fixup_time(code_root_fixup_time_ms);
4004 }
4005 
4006 void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
4007   // Also cleans the card table from temporary duplicate detection information used
4008   // during UpdateRS/ScanRS.
4009   g1_rem_set()->cleanup_after_oops_into_collection_set_do();
4010 
4011   // Process any discovered reference objects - we have
4012   // to do this _before_ we retire the GC alloc regions
4013   // as we may have to copy some 'reachable' referent
4014   // objects (and their reachable sub-graphs) that were
4015   // not copied during the pause.
4016   process_discovered_references(per_thread_states);
4017 
4018   // FIXME
4019   // CM's reference processing also cleans up the string table.
4020   // Should we do that here also? We could, but it is a serial operation
4021   // and could significantly increase the pause time.
4022 
4023   G1STWIsAliveClosure is_alive(this);
4024   G1KeepAliveClosure keep_alive(this);
4025 
4026   {
4027     double start = os::elapsedTime();
4028 
4029     WeakProcessor::weak_oops_do(&is_alive, &keep_alive);
4030 
4031     double time_ms = (os::elapsedTime() - start) * 1000.0;
4032     g1_policy()->phase_times()->record_weak_ref_proc_time(time_ms);
4033   }
4034 
4035   if (G1StringDedup::is_enabled()) {
4036     double fixup_start = os::elapsedTime();
4037 
4038     G1StringDedup::unlink_or_oops_do(&is_alive, &keep_alive, true, g1_policy()->phase_times());
4039 


< prev index next >