< prev index next >

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

Print this page
rev 13070 : imported patch 8177544-full-gc-scope
rev 13071 : [mq]: 8177544-full-gc-scope-tschatzl-rev1

*** 36,58 **** #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacStats.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1HotCardCache.hpp" - #include "gc/g1/g1MarkSweep.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RegionToSpaceMapper.hpp" #include "gc/g1/g1RemSet.inline.hpp" #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RootProcessor.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/g1YCTypes.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/heapRegionSet.inline.hpp" --- 36,59 ---- #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1EvacStats.inline.hpp" + #include "gc/g1/g1FullGCScope.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1HeapSizingPolicy.hpp" #include "gc/g1/g1HeapTransition.hpp" #include "gc/g1/g1HeapVerifier.hpp" #include "gc/g1/g1HotCardCache.hpp" #include "gc/g1/g1OopClosures.inline.hpp" #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RegionToSpaceMapper.hpp" #include "gc/g1/g1RemSet.inline.hpp" #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RootProcessor.hpp" + #include "gc/g1/g1SerialFullCollector.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/g1YCTypes.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/heapRegionSet.inline.hpp"
*** 1069,1145 **** } ShouldNotReachHere(); } - class PostMCRemSetClearClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - ModRefBarrierSet* _mr_bs; - public: - PostMCRemSetClearClosure(G1CollectedHeap* g1h, ModRefBarrierSet* mr_bs) : - _g1h(g1h), _mr_bs(mr_bs) {} - - bool doHeapRegion(HeapRegion* r) { - HeapRegionRemSet* hrrs = r->rem_set(); - - _g1h->reset_gc_time_stamps(r); - - if (r->is_continues_humongous()) { - // We'll assert that the strong code root list and RSet is empty - assert(hrrs->strong_code_roots_list_length() == 0, "sanity"); - assert(hrrs->occupied() == 0, "RSet should be empty"); - } else { - hrrs->clear(); - } - // You might think here that we could clear just the cards - // corresponding to the used region. But no: if we leave a dirty card - // in a region we might allocate into, then it would prevent that card - // from being enqueued, and cause it to be missed. - // Re: the performance cost: we shouldn't be doing full GC anyway! - _mr_bs->clear(MemRegion(r->bottom(), r->end())); - - return false; - } - }; - - void G1CollectedHeap::clear_rsets_post_compaction() { - PostMCRemSetClearClosure rs_clear(this, g1_barrier_set()); - heap_region_iterate(&rs_clear); - } - - class RebuildRSOutOfRegionClosure: public HeapRegionClosure { - G1CollectedHeap* _g1h; - UpdateRSOopClosure _cl; - public: - RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, uint worker_i = 0) : - _cl(g1->g1_rem_set(), worker_i), - _g1h(g1) - { } - - bool doHeapRegion(HeapRegion* r) { - if (!r->is_continues_humongous()) { - _cl.set_from(r); - r->oop_iterate(&_cl); - } - return false; - } - }; - - class ParRebuildRSTask: public AbstractGangTask { - G1CollectedHeap* _g1; - HeapRegionClaimer _hrclaimer; - - public: - ParRebuildRSTask(G1CollectedHeap* g1) : - AbstractGangTask("ParRebuildRSTask"), _g1(g1), _hrclaimer(g1->workers()->active_workers()) {} - - void work(uint worker_id) { - RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id); - _g1->heap_region_par_iterate(&rebuild_rs, worker_id, &_hrclaimer); - } - }; - class PostCompactionPrinterClosure: public HeapRegionClosure { private: G1HRPrinter* _hr_printer; public: bool doHeapRegion(HeapRegion* hr) { --- 1070,1079 ----
*** 1158,1213 **** heap_region_iterate(&cl); } } ! bool G1CollectedHeap::do_full_collection(bool explicit_gc, ! bool clear_all_soft_refs) { ! assert_at_safepoint(true /* should_be_vm_thread */); ! ! if (GCLocker::check_active_before_gc()) { ! return false; ! } ! ! STWGCTimer* gc_timer = G1MarkSweep::gc_timer(); ! gc_timer->register_gc_start(); ! ! SerialOldTracer* gc_tracer = G1MarkSweep::gc_tracer(); ! GCIdMark gc_id_mark; ! gc_tracer->report_gc_start(gc_cause(), gc_timer->gc_start()); ! ! SvcGCMarker sgcm(SvcGCMarker::FULL); ! ResourceMark rm; ! ! print_heap_before_gc(); ! print_heap_regions(); ! trace_heap_before_gc(gc_tracer); ! ! size_t metadata_prev_used = MetaspaceAux::used_bytes(); ! ! _verifier->verify_region_sets_optional(); ! ! const bool do_clear_all_soft_refs = clear_all_soft_refs || ! collector_policy()->should_clear_all_soft_refs(); ! ! ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy()); ! ! { ! IsGCActiveMark x; ! ! // Timing ! assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant"); ! GCTraceCPUTime tcpu; ! ! { ! GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); ! TraceCollectorStats tcs(g1mm()->full_collection_counters()); ! TraceMemoryManagerStats tms(true /* fullGC */, gc_cause()); ! ! G1HeapTransition heap_transition(this); ! g1_policy()->record_full_collection_start(); ! // Note: When we have a more flexible GC logging framework that // allows us to add optional attributes to a GC log record we // could consider timing and reporting how long we wait in the // following two methods. wait_while_free_regions_coming(); --- 1092,1102 ---- heap_region_iterate(&cl); } } ! void G1CollectedHeap::abort_concurrent_cycle() { // Note: When we have a more flexible GC logging framework that // allows us to add optional attributes to a GC log record we // could consider timing and reporting how long we wait in the // following two methods. wait_while_free_regions_coming();
*** 1218,1252 **** // early. _cm->root_regions()->abort(); _cm->root_regions()->wait_until_scan_finished(); append_secondary_free_list_if_not_empty_with_lock(); - gc_prologue(true); - increment_total_collections(true /* full gc */); - increment_old_marking_cycles_started(); - - assert(used() == recalculate_used(), "Should be equal"); - - _verifier->verify_before_gc(); - - _verifier->check_bitmaps("Full GC Start"); - pre_full_gc_dump(gc_timer); - - #if defined(COMPILER2) || INCLUDE_JVMCI - DerivedPointerTable::clear(); - #endif - // Disable discovery and empty the discovered lists // for the CM ref processor. ref_processor_cm()->disable_discovery(); ref_processor_cm()->abandon_partial_discovery(); ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent // refinement, if any are in progress. concurrent_mark()->abort(); // Make sure we'll choose a new allocation region afterwards. _allocator->release_mutator_alloc_region(); _allocator->abandon_gc_alloc_regions(); g1_rem_set()->cleanupHRRS(); --- 1107,1128 ---- // early. _cm->root_regions()->abort(); _cm->root_regions()->wait_until_scan_finished(); append_secondary_free_list_if_not_empty_with_lock(); // Disable discovery and empty the discovered lists // for the CM ref processor. ref_processor_cm()->disable_discovery(); ref_processor_cm()->abandon_partial_discovery(); ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent // refinement, if any are in progress. concurrent_mark()->abort(); + } + void G1CollectedHeap::prepare_heap_for_full_collection() { // Make sure we'll choose a new allocation region afterwards. _allocator->release_mutator_alloc_region(); _allocator->abandon_gc_alloc_regions(); g1_rem_set()->cleanupHRRS();
*** 1256,1369 **** // after this full GC. abandon_collection_set(collection_set()); tear_down_region_sets(false /* free_list_only */); collector_state()->set_gcs_are_young(true); ! // See the comments in g1CollectedHeap.hpp and ! // G1CollectedHeap::ref_processing_init() about ! // how reference processing currently works in G1. ! ! // Temporarily make discovery by the STW ref processor single threaded (non-MT). ! ReferenceProcessorMTDiscoveryMutator stw_rp_disc_ser(ref_processor_stw(), false); ! ! // Temporarily clear the STW ref processor's _is_alive_non_header field. ! ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL); ! ! ref_processor_stw()->enable_discovery(); ! ref_processor_stw()->setup_policy(do_clear_all_soft_refs); ! ! // Do collection work ! { ! HandleMark hm; // Discard invalid handles created during gc ! G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs); ! } ! ! assert(num_free_regions() == 0, "we should not have added any free regions"); ! rebuild_region_sets(false /* free_list_only */); ! ! // Enqueue any discovered reference objects that have ! // not been removed from the discovered lists. ! ref_processor_stw()->enqueue_discovered_references(); ! ! #if defined(COMPILER2) || INCLUDE_JVMCI ! DerivedPointerTable::update_pointers(); ! #endif ! ! MemoryService::track_memory_usage(); ! ! assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); ! ref_processor_stw()->verify_no_references_recorded(); // Delete metaspaces for unloaded class loaders and clean up loader_data graph ClassLoaderDataGraph::purge(); MetaspaceAux::verify_metrics(); ! // Note: since we've just done a full GC, concurrent ! // marking is no longer active. Therefore we need not ! // re-enable reference discovery for the CM ref processor. ! // That will be done at the start of the next marking cycle. ! assert(!ref_processor_cm()->discovery_enabled(), "Postcondition"); ! ref_processor_cm()->verify_no_references_recorded(); ! reset_gc_time_stamp(); ! // Since everything potentially moved, we will clear all remembered ! // sets, and clear all cards. Later we will rebuild remembered ! // sets. We will also reset the GC time stamps of the regions. ! clear_rsets_post_compaction(); ! check_gc_time_stamps(); ! resize_if_necessary_after_full_collection(); ! // We should do this after we potentially resize the heap so ! // that all the COMMIT / UNCOMMIT events are generated before ! // the compaction events. ! print_hrm_post_compaction(); if (_hot_card_cache->use_cache()) { _hot_card_cache->reset_card_counts(); _hot_card_cache->reset_hot_cache(); } ! // Rebuild remembered sets of all regions. ! uint n_workers = ! AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), ! workers()->active_workers(), ! Threads::number_of_non_daemon_threads()); ! workers()->update_active_workers(n_workers); ! log_info(gc,task)("Using %u workers of %u to rebuild remembered set", n_workers, workers()->total_workers()); ! ! ParRebuildRSTask rebuild_rs_task(this); ! workers()->run_task(&rebuild_rs_task); ! ! // Rebuild the strong code root lists for each region ! rebuild_strong_code_roots(); ! ! if (true) { // FIXME ! MetaspaceGC::compute_new_size(); ! } ! ! #ifdef TRACESPINNING ! ParallelTaskTerminator::print_termination_counts(); ! #endif ! ! // Discard all rset updates JavaThread::dirty_card_queue_set().abandon_logs(); assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty"); ! // At this point there should be no regions in the ! // entire heap tagged as young. ! assert(check_young_list_empty(), "young list should be empty at this point"); ! ! // Update the number of full collections that have been completed. ! increment_old_marking_cycles_completed(false /* concurrent */); ! _hrm.verify_optional(); _verifier->verify_region_sets_optional(); - _verifier->verify_after_gc(); - // Clear the previous marking bitmap, if needed for bitmap verification. // Note we cannot do this when we clear the next marking bitmap in // G1ConcurrentMark::abort() above since VerifyDuringGC verifies the // objects marked during a full GC against the previous bitmap. // But we need to clear it before calling check_bitmaps below since --- 1132,1190 ---- // after this full GC. abandon_collection_set(collection_set()); tear_down_region_sets(false /* free_list_only */); collector_state()->set_gcs_are_young(true); + } ! void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) { ! assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant"); ! assert(used() == recalculate_used(), "Should be equal"); ! _verifier->verify_region_sets_optional(); ! _verifier->verify_before_gc(); ! _verifier->check_bitmaps("Full GC Start"); ! } + void G1CollectedHeap::prepare_heap_for_mutators() { // Delete metaspaces for unloaded class loaders and clean up loader_data graph ClassLoaderDataGraph::purge(); MetaspaceAux::verify_metrics(); ! // Prepare heap for normal collections. ! assert(num_free_regions() == 0, "we should not have added any free regions"); ! rebuild_region_sets(false /* free_list_only */); ! abort_refinement(); ! resize_if_necessary_after_full_collection(); ! // Rebuild the strong code root lists for each region ! rebuild_strong_code_roots(); ! // Start a new incremental collection set for the next pause ! start_new_collection_set(); ! _allocator->init_mutator_alloc_region(); ! ! // Post collection state updates. ! MetaspaceGC::compute_new_size(); ! } + void G1CollectedHeap::abort_refinement() { if (_hot_card_cache->use_cache()) { _hot_card_cache->reset_card_counts(); _hot_card_cache->reset_hot_cache(); } ! // Discard all remembered set updates. JavaThread::dirty_card_queue_set().abandon_logs(); assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty"); + } ! void G1CollectedHeap::verify_after_full_collection() { ! check_gc_time_stamps(); _hrm.verify_optional(); _verifier->verify_region_sets_optional(); _verifier->verify_after_gc(); // Clear the previous marking bitmap, if needed for bitmap verification. // Note we cannot do this when we clear the next marking bitmap in // G1ConcurrentMark::abort() above since VerifyDuringGC verifies the // objects marked during a full GC against the previous bitmap. // But we need to clear it before calling check_bitmaps below since
*** 1373,1409 **** GCTraceTime(Debug, gc)("Clear Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); ! start_new_collection_set(); ! _allocator->init_mutator_alloc_region(); ! g1_policy()->record_full_collection_end(); ! // We must call G1MonitoringSupport::update_sizes() in the same scoping level ! // as an active TraceMemoryManagerStats object (i.e. before the destructor for the ! // TraceMemoryManagerStats is called) so that the G1 memory pools are updated ! // before any GC notifications are raised. ! g1mm()->update_sizes(); gc_epilogue(true); ! heap_transition.print(); ! print_heap_after_gc(); ! print_heap_regions(); ! trace_heap_after_gc(gc_tracer); ! post_full_gc_dump(gc_timer); ! } ! gc_timer->register_gc_end(); ! gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); } return true; } void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { // Currently, there is no facility in the do_full_collection(bool) API to notify --- 1194,1278 ---- GCTraceTime(Debug, gc)("Clear Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } _verifier->check_bitmaps("Full GC End"); ! // At this point there should be no regions in the ! // entire heap tagged as young. ! assert(check_young_list_empty(), "young list should be empty at this point"); ! // Note: since we've just done a full GC, concurrent ! // marking is no longer active. Therefore we need not ! // re-enable reference discovery for the CM ref processor. ! // That will be done at the start of the next marking cycle. ! // We also know that the STW processor should no longer ! // discover any new references. ! assert(!ref_processor_stw()->discovery_enabled(), "Postcondition"); ! assert(!ref_processor_cm()->discovery_enabled(), "Postcondition"); ! ref_processor_stw()->verify_no_references_recorded(); ! ref_processor_cm()->verify_no_references_recorded(); ! } ! void G1CollectedHeap::print_heap_after_full_collection(G1HeapTransition* heap_transition) { ! print_hrm_post_compaction(); ! heap_transition->print(); ! print_heap_after_gc(); ! print_heap_regions(); ! #ifdef TRACESPINNING ! ParallelTaskTerminator::print_termination_counts(); ! #endif ! } ! void G1CollectedHeap::do_full_collection_inner(G1FullGCScope* scope) { ! GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true); ! g1_policy()->record_full_collection_start(); ! ! print_heap_before_gc(); ! print_heap_regions(); ! ! abort_concurrent_cycle(); ! verify_before_full_collection(scope->is_explicit_gc()); + gc_prologue(true); + prepare_heap_for_full_collection(); + + G1SerialFullCollector serial(scope, ref_processor_stw()); + serial.prepare_collection(); + serial.collect(); + serial.complete_collection(); + + prepare_heap_for_mutators(); + + g1_policy()->record_full_collection_end(); gc_epilogue(true); ! // Post collection verification. ! verify_after_full_collection(); ! // Post collection logging. ! // We should do this after we potentially resize the heap so ! // that all the COMMIT / UNCOMMIT events are generated before ! // the compaction events. ! print_heap_after_full_collection(scope->heap_transition()); ! } ! bool G1CollectedHeap::do_full_collection(bool explicit_gc, ! bool clear_all_soft_refs) { ! assert_at_safepoint(true /* should_be_vm_thread */); ! if (GCLocker::check_active_before_gc()) { ! // Full GC was not completed. ! return false; } + const bool do_clear_all_soft_refs = clear_all_soft_refs || + collector_policy()->should_clear_all_soft_refs(); + + G1FullGCScope scope(explicit_gc, do_clear_all_soft_refs); + do_full_collection_inner(&scope); + + // Full collection was successfully completed. return true; } void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) { // Currently, there is no facility in the do_full_collection(bool) API to notify
*** 2695,2719 **** assert(heap != NULL, "Uninitialized access to G1CollectedHeap::heap()"); assert(heap->kind() == CollectedHeap::G1CollectedHeap, "Not a G1CollectedHeap"); return (G1CollectedHeap*)heap; } ! void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { // always_do_update_barrier = false; assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); ! double start = os::elapsedTime(); // Fill TLAB's and such accumulate_statistics_all_tlabs(); ensure_parsability(true); g1_policy()->phase_times()->record_prepare_tlab_time_ms((os::elapsedTime() - start) * 1000.0); - - g1_rem_set()->print_periodic_summary_info("Before GC RS summary", total_collections()); } void G1CollectedHeap::gc_epilogue(bool full) { ! // we are at the end of the GC. Total collections has already been increased. g1_rem_set()->print_periodic_summary_info("After GC RS summary", total_collections() - 1); // FIXME: what is this about? // I'm ignoring the "fill_newgen()" call if "alloc_event_enabled" // is set. --- 2564,2604 ---- assert(heap != NULL, "Uninitialized access to G1CollectedHeap::heap()"); assert(heap->kind() == CollectedHeap::G1CollectedHeap, "Not a G1CollectedHeap"); return (G1CollectedHeap*)heap; } ! void G1CollectedHeap::gc_prologue(bool full) { // always_do_update_barrier = false; assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); ! // This summary needs to be printed before incrementing total collections. ! g1_rem_set()->print_periodic_summary_info("Before GC RS summary", total_collections()); ! ! // Update common counters. ! increment_total_collections(full /* full gc */); ! if (full) { ! increment_old_marking_cycles_started(); ! reset_gc_time_stamp(); ! } else { ! increment_gc_time_stamp(); ! } ! // Fill TLAB's and such + double start = os::elapsedTime(); accumulate_statistics_all_tlabs(); ensure_parsability(true); g1_policy()->phase_times()->record_prepare_tlab_time_ms((os::elapsedTime() - start) * 1000.0); } void G1CollectedHeap::gc_epilogue(bool full) { ! // Update common counters. ! if (full) { ! // Update the number of full collections that have been completed. ! increment_old_marking_cycles_completed(false /* concurrent */); ! } ! ! // We are at the end of the GC. Total collections has already been increased. g1_rem_set()->print_periodic_summary_info("After GC RS summary", total_collections() - 1); // FIXME: what is this about? // I'm ignoring the "fill_newgen()" call if "alloc_event_enabled" // is set.
*** 2726,2735 **** --- 2611,2621 ---- resize_all_tlabs(); g1_policy()->phase_times()->record_resize_tlab_time_ms((os::elapsedTime() - start) * 1000.0); allocation_context_stats().update(full); + MemoryService::track_memory_usage(); // We have just completed a GC. Update the soft reference // policy with the new heap occupancy Universe::update_heap_info_at_gc(); }
*** 3115,3126 **** { // Call to jvmpi::post_class_unload_events must occur outside of active GC IsGCActiveMark x; gc_prologue(false); - increment_total_collections(false /* full gc */); - increment_gc_time_stamp(); if (VerifyRememberedSets) { log_info(gc, verify)("[Verifying RemSets before GC]"); VerifyRegionRemSetClosure v_cl; heap_region_iterate(&v_cl); --- 3001,3010 ----
*** 3278,3289 **** g1_policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc); evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before()); evacuation_info.set_bytes_copied(g1_policy()->bytes_copied_during_gc()); - MemoryService::track_memory_usage(); - // In prepare_for_verify() below we'll need to scan the deferred // update buffers to bring the RSets up-to-date if // G1HRRSFlushLogBuffersOnVerify has been set. While scanning // the update buffers we'll probably need to scan cards on the // regions we just allocated to (i.e., the GC alloc --- 3162,3171 ----
< prev index next >