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
|