# HG changeset patch # User rkennke # Date 1499695605 -7200 # Mon Jul 10 16:06:45 2017 +0200 # Node ID ef3d69f9c58aad0c29c46e79e0d10efa8e6ce9ef # Parent b1812dde71dc6983405bf68d72d065b97422b1f9 [mq]: 8179387.patch diff --git a/src/share/vm/gc/cms/cmsHeap.cpp b/src/share/vm/gc/cms/cmsHeap.cpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc/cms/cmsHeap.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/cms/concurrentMarkSweepThread.hpp" +#include "gc/cms/cmsHeap.hpp" +#include "gc/cms/vmCMSOperations.hpp" +#include "gc/shared/genOopClosures.inline.hpp" +#include "gc/shared/strongRootsScope.hpp" +#include "gc/shared/workgroup.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/vmThread.hpp" +#include "utilities/stack.inline.hpp" + +CMSHeap::CMSHeap(GenCollectorPolicy *policy) : GenCollectedHeap(policy) { + _workers = new WorkGang("GC Thread", ParallelGCThreads, + /* are_GC_task_threads */true, + /* are_ConcurrentGC_threads */false); + _workers->initialize_workers(); +} + +jint CMSHeap::initialize() { + jint status = GenCollectedHeap::initialize(); + if (status != JNI_OK) return status; + + // If we are running CMS, create the collector responsible + // for collecting the CMS generations. + assert(collector_policy()->is_concurrent_mark_sweep_policy(), "must be CMS policy"); + create_cms_collector(); + + return JNI_OK; +} + +void CMSHeap::check_gen_kinds() { + assert(young_gen()->kind() == Generation::ParNew, + "Wrong youngest generation type"); + assert(old_gen()->kind() == Generation::ConcurrentMarkSweep, + "Wrong generation kind"); +} + +CMSHeap* CMSHeap::heap() { + CollectedHeap* heap = Universe::heap(); + assert(heap != NULL, "Uninitialized access to CMSHeap::heap()"); + assert(heap->kind() == CollectedHeap::CMSHeap, "Not a CMSHeap"); + return (CMSHeap*) heap; +} + +void CMSHeap::gc_threads_do(ThreadClosure* tc) const { + assert(workers() != NULL, "should have workers here"); + workers()->threads_do(tc); + ConcurrentMarkSweepThread::threads_do(tc); +} + +void CMSHeap::print_gc_threads_on(outputStream* st) const { + assert(workers() != NULL, "should have workers here"); + workers()->print_worker_threads_on(st); + ConcurrentMarkSweepThread::print_all_on(st); +} + +void CMSHeap::print_on_error(outputStream* st) const { + GenCollectedHeap::print_on_error(st); + st->cr(); + CMSCollector::print_on_error(st); +} + +void CMSHeap::create_cms_collector() { + assert(old_gen()->kind() == Generation::ConcurrentMarkSweep, + "Unexpected generation kinds"); + assert(gen_policy()->is_concurrent_mark_sweep_policy(), "Unexpected policy type"); + CMSCollector* collector = + new CMSCollector((ConcurrentMarkSweepGeneration*) old_gen(), + rem_set(), + gen_policy()->as_concurrent_mark_sweep_policy()); + + if (!collector->completed_initialization()) { + vm_shutdown_during_initialization("Could not create CMS collector"); + } +} + +void CMSHeap::collect(GCCause::Cause cause) { + if (should_do_concurrent_full_gc(cause)) { + // Mostly concurrent full collection. + collect_mostly_concurrent(cause); + } else { + GenCollectedHeap::collect(cause); + } +} + +bool CMSHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { + switch (cause) { + case GCCause::_gc_locker: return GCLockerInvokesConcurrent; + case GCCause::_java_lang_system_gc: + case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent; + default: return false; + } +} + +void CMSHeap::collect_mostly_concurrent(GCCause::Cause cause) { + assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock"); + + MutexLocker ml(Heap_lock); + // Read the GC counts while holding the Heap_lock + unsigned int full_gc_count_before = total_full_collections(); + unsigned int gc_count_before = total_collections(); + { + MutexUnlocker mu(Heap_lock); + VM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause); + VMThread::execute(&op); + } +} + +void CMSHeap::stop() { + ConcurrentMarkSweepThread::cmst()->stop(); +} + +void CMSHeap::cms_process_roots(StrongRootsScope* scope, + bool young_gen_as_roots, + ScanningOption so, + bool only_strong_roots, + OopsInGenClosure* root_closure, + CLDClosure* cld_closure) { + MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations); + OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure; + CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; + + process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure); + if (!only_strong_roots) { + process_string_table_roots(scope, root_closure); + } + + if (young_gen_as_roots && + !_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { + root_closure->set_generation(young_gen()); + young_gen()->oop_iterate(root_closure); + root_closure->reset_generation(); + } + + _process_strong_tasks->all_tasks_completed(scope->n_threads()); +} + +void CMSHeap::gc_prologue(bool full) { + always_do_update_barrier = false; + GenCollectedHeap::gc_prologue(full); +}; + +void CMSHeap::gc_epilogue(bool full) { + GenCollectedHeap::gc_epilogue(full); + always_do_update_barrier = true; +}; diff --git a/src/share/vm/gc/cms/cmsHeap.hpp b/src/share/vm/gc/cms/cmsHeap.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc/cms/cmsHeap.hpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_CMS_CMSHEAP_HPP +#define SHARE_VM_GC_CMS_CMSHEAP_HPP + +#include "gc/shared/collectedHeap.hpp" +#include "gc/shared/gcCause.hpp" +#include "gc/shared/genCollectedHeap.hpp" + +class CLDClosure; +class GenCollectorPolicy; +class OopsInGenClosure; +class outputStream; +class StrongRootsScope; +class ThreadClosure; +class WorkGang; + +class CMSHeap : public GenCollectedHeap { +public: + CMSHeap(GenCollectorPolicy *policy); + + // Returns JNI_OK on success + virtual jint initialize(); + + virtual void check_gen_kinds(); + + // Convenience function to be used in situations where the heap type can be + // asserted to be this type. + static CMSHeap* heap(); + + virtual Name kind() const { + return CollectedHeap::CMSHeap; + } + + virtual const char* name() const { + return "Concurrent Mark Sweep"; + } + + WorkGang* workers() const { return _workers; } + + virtual void print_gc_threads_on(outputStream* st) const; + virtual void gc_threads_do(ThreadClosure* tc) const; + virtual void print_on_error(outputStream* st) const; + + // Perform a full collection of the heap; intended for use in implementing + // "System.gc". This implies as full a collection as the CollectedHeap + // supports. Caller does not hold the Heap_lock on entry. + void collect(GCCause::Cause cause); + + bool is_in_closed_subset(const void* p) const { + return is_in_reserved(p); + } + + bool card_mark_must_follow_store() const { + return true; + } + + void stop(); + + // If "young_gen_as_roots" is false, younger generations are + // not scanned as roots; in this case, the caller must be arranging to + // scan the younger generations itself. (For example, a generation might + // explicitly mark reachable objects in younger generations, to avoid + // excess storage retention.) + void cms_process_roots(StrongRootsScope* scope, + bool young_gen_as_roots, + ScanningOption so, + bool only_strong_roots, + OopsInGenClosure* root_closure, + CLDClosure* cld_closure); + +private: + WorkGang* _workers; + + virtual void gc_prologue(bool full); + virtual void gc_epilogue(bool full); + + // Accessor for memory state verification support + NOT_PRODUCT( + virtual size_t skip_header_HeapWords() { return CMSCollector::skip_header_HeapWords(); } + ) + + // Returns success or failure. + void create_cms_collector(); + + // In support of ExplicitGCInvokesConcurrent functionality + bool should_do_concurrent_full_gc(GCCause::Cause cause); + + void collect_mostly_concurrent(GCCause::Cause cause); +}; + +#endif // SHARE_VM_GC_CMS_CMSHEAP_HPP diff --git a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -29,6 +29,7 @@ #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "gc/cms/cmsCollectorPolicy.hpp" +#include "gc/cms/cmsHeap.hpp" #include "gc/cms/cmsOopClosures.inline.hpp" #include "gc/cms/compactibleFreeListSpace.hpp" #include "gc/cms/concurrentMarkSweepGeneration.inline.hpp" @@ -2326,7 +2327,7 @@ void CMSCollector::verify_after_remark_work_1() { ResourceMark rm; HandleMark hm; - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); // Get a clear set of claim bits for the roots processing to work with. ClassLoaderDataGraph::clear_claimed_marks(); @@ -2395,7 +2396,7 @@ void CMSCollector::verify_after_remark_work_2() { ResourceMark rm; HandleMark hm; - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); // Get a clear set of claim bits for the roots processing to work with. ClassLoaderDataGraph::clear_claimed_marks(); @@ -2840,7 +2841,7 @@ HandleMark hm; MarkRefsIntoClosure notOlder(_span, &_markBitMap); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); verify_work_stacks_empty(); verify_overflow_empty(); @@ -4258,7 +4259,7 @@ // ---------- scan from roots -------------- _timer.start(); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); ParMarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap)); // ---------- young gen roots -------------- @@ -4383,7 +4384,7 @@ // ---------- rescan from roots -------------- _timer.start(); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); ParMarkRefsIntoAndScanClosure par_mrias_cl(_collector, _collector->_span, _collector->ref_processor(), &(_collector->_markBitMap), @@ -4835,7 +4836,7 @@ // Parallel version of remark void CMSCollector::do_remark_parallel() { - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); WorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); // Choose to use the number of GC workers most recently set @@ -4894,7 +4895,7 @@ void CMSCollector::do_remark_non_parallel() { ResourceMark rm; HandleMark hm; - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false); MarkRefsIntoAndScanClosure @@ -5146,7 +5147,7 @@ void CMSRefProcTaskExecutor::execute(ProcessTask& task) { - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); WorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); CMSRefProcTaskProxy rp_task(task, &_collector, @@ -5159,7 +5160,7 @@ void CMSRefProcTaskExecutor::execute(EnqueueTask& task) { - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); WorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); CMSRefEnqueueTaskProxy enq_task(task); @@ -5192,7 +5193,7 @@ // and a different number of discovered lists may have Ref objects. // That is OK as long as the Reference lists are balanced (see // balance_all_queues() and balance_queues()). - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); uint active_workers = ParallelGCThreads; WorkGang* workers = gch->workers(); if (workers != NULL) { diff --git a/src/share/vm/gc/cms/parNewGeneration.cpp b/src/share/vm/gc/cms/parNewGeneration.cpp --- a/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/src/share/vm/gc/cms/parNewGeneration.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/cms/cmsHeap.hpp" #include "gc/cms/compactibleFreeListSpace.hpp" #include "gc/cms/concurrentMarkSweepGeneration.hpp" #include "gc/cms/parNewGeneration.inline.hpp" @@ -804,7 +805,7 @@ }; void ParNewRefProcTaskExecutor::execute(ProcessTask& task) { - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); WorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); _state_set.reset(workers->active_workers(), _young_gen.promotion_failed()); @@ -816,7 +817,7 @@ } void ParNewRefProcTaskExecutor::execute(EnqueueTask& task) { - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); WorkGang* workers = gch->workers(); assert(workers != NULL, "Need parallel worker threads."); ParNewRefEnqueueTaskProxy enq_task(task); @@ -883,7 +884,7 @@ bool is_tlab) { assert(full || size > 0, "otherwise we don't want to collect"); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); _gc_timer->register_gc_start(); @@ -1060,7 +1061,7 @@ } size_t ParNewGeneration::desired_plab_sz() { - return _plab_stats.desired_plab_sz(GenCollectedHeap::heap()->workers()->active_workers()); + return _plab_stats.desired_plab_sz(CMSHeap::heap()->workers()->active_workers()); } static int sum; @@ -1471,3 +1472,9 @@ const char* ParNewGeneration::name() const { return "par new generation"; } + +void ParNewGeneration::restore_preserved_marks() { + SharedRestorePreservedMarksTaskExecutor task_executor(CMSHeap::heap()->workers()); + _preserved_marks_set.restore(&task_executor); +} + diff --git a/src/share/vm/gc/cms/parNewGeneration.hpp b/src/share/vm/gc/cms/parNewGeneration.hpp --- a/src/share/vm/gc/cms/parNewGeneration.hpp +++ b/src/share/vm/gc/cms/parNewGeneration.hpp @@ -345,6 +345,8 @@ bool survivor_overflow() { return _survivor_overflow; } void set_survivor_overflow(bool v) { _survivor_overflow = v; } + void restore_preserved_marks(); + public: ParNewGeneration(ReservedSpace rs, size_t initial_byte_size); diff --git a/src/share/vm/gc/serial/defNewGeneration.cpp b/src/share/vm/gc/serial/defNewGeneration.cpp --- a/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/src/share/vm/gc/serial/defNewGeneration.cpp @@ -743,8 +743,11 @@ RemoveForwardedPointerClosure rspc; eden()->object_iterate(&rspc); from()->object_iterate(&rspc); + restore_preserved_marks(); +} - SharedRestorePreservedMarksTaskExecutor task_executor(GenCollectedHeap::heap()->workers()); +void DefNewGeneration::restore_preserved_marks() { + SharedRestorePreservedMarksTaskExecutor task_executor(NULL); _preserved_marks_set.restore(&task_executor); } diff --git a/src/share/vm/gc/serial/defNewGeneration.hpp b/src/share/vm/gc/serial/defNewGeneration.hpp --- a/src/share/vm/gc/serial/defNewGeneration.hpp +++ b/src/share/vm/gc/serial/defNewGeneration.hpp @@ -89,6 +89,8 @@ // therefore we must remove their forwarding pointers. void remove_forwarding_pointers(); + virtual void restore_preserved_marks(); + // Preserved marks PreservedMarksSet _preserved_marks_set; diff --git a/src/share/vm/gc/shared/collectedHeap.hpp b/src/share/vm/gc/shared/collectedHeap.hpp --- a/src/share/vm/gc/shared/collectedHeap.hpp +++ b/src/share/vm/gc/shared/collectedHeap.hpp @@ -82,6 +82,7 @@ // GenCollectedHeap // G1CollectedHeap // ParallelScavengeHeap +// CMSHeap // class CollectedHeap : public CHeapObj { friend class VMStructs; @@ -193,7 +194,8 @@ enum Name { GenCollectedHeap, ParallelScavengeHeap, - G1CollectedHeap + G1CollectedHeap, + CMSHeap }; static inline size_t filler_array_max_size() { diff --git a/src/share/vm/gc/shared/genCollectedHeap.cpp b/src/share/vm/gc/shared/genCollectedHeap.cpp --- a/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -58,29 +58,6 @@ #include "utilities/macros.hpp" #include "utilities/stack.inline.hpp" #include "utilities/vmError.hpp" -#if INCLUDE_ALL_GCS -#include "gc/cms/concurrentMarkSweepThread.hpp" -#include "gc/cms/vmCMSOperations.hpp" -#endif // INCLUDE_ALL_GCS - -NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;) - -// The set of potentially parallel tasks in root scanning. -enum GCH_strong_roots_tasks { - GCH_PS_Universe_oops_do, - GCH_PS_JNIHandles_oops_do, - GCH_PS_ObjectSynchronizer_oops_do, - GCH_PS_FlatProfiler_oops_do, - GCH_PS_Management_oops_do, - GCH_PS_SystemDictionary_oops_do, - GCH_PS_ClassLoaderDataGraph_oops_do, - GCH_PS_jvmti_oops_do, - GCH_PS_CodeCache_oops_do, - GCH_PS_aot_oops_do, - GCH_PS_younger_gens, - // Leave this one last. - GCH_PS_NumElements -}; GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) : CollectedHeap(), @@ -90,15 +67,6 @@ _full_collections_completed(0) { assert(policy != NULL, "Sanity check"); - if (UseConcMarkSweepGC) { - _workers = new WorkGang("GC Thread", ParallelGCThreads, - /* are_GC_task_threads */true, - /* are_ConcurrentGC_threads */false); - _workers->initialize_workers(); - } else { - // Serial GC does not use workers. - _workers = NULL; - } } jint GenCollectedHeap::initialize() { @@ -139,15 +107,6 @@ _old_gen = gen_policy()->old_gen_spec()->init(old_rs, rem_set()); clear_incremental_collection_failed(); -#if INCLUDE_ALL_GCS - // If we are running CMS, create the collector responsible - // for collecting the CMS generations. - if (collector_policy()->is_concurrent_mark_sweep_policy()) { - bool success = create_cms_collector(); - if (!success) return JNI_ENOMEM; - } -#endif // INCLUDE_ALL_GCS - return JNI_OK; } @@ -184,21 +143,22 @@ void GenCollectedHeap::post_initialize() { ref_processing_init(); - assert((_young_gen->kind() == Generation::DefNew) || - (_young_gen->kind() == Generation::ParNew), - "Wrong youngest generation type"); + check_gen_kinds(); DefNewGeneration* def_new_gen = (DefNewGeneration*)_young_gen; - assert(_old_gen->kind() == Generation::ConcurrentMarkSweep || - _old_gen->kind() == Generation::MarkSweepCompact, - "Wrong generation kind"); - _gen_policy->initialize_size_policy(def_new_gen->eden()->capacity(), _old_gen->capacity(), def_new_gen->from()->capacity()); _gen_policy->initialize_gc_policy_counters(); } +void GenCollectedHeap::check_gen_kinds() { + assert(young_gen()->kind() == Generation::DefNew, + "Wrong youngest generation type"); + assert(old_gen()->kind() == Generation::MarkSweepCompact, + "Wrong generation kind"); +} + void GenCollectedHeap::ref_processing_init() { _young_gen->ref_processor_init(); _old_gen->ref_processor_init(); @@ -310,19 +270,6 @@ _gc_cause == GCCause::_wb_full_gc; } -bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { - if (!UseConcMarkSweepGC) { - return false; - } - - switch (cause) { - case GCCause::_gc_locker: return GCLockerInvokesConcurrent; - case GCCause::_java_lang_system_gc: - case GCCause::_dcmd_gc_run: return ExplicitGCInvokesConcurrent; - default: return false; - } -} - void GenCollectedHeap::collect_generation(Generation* gen, bool full, size_t size, bool is_tlab, bool run_verification, bool clear_soft_refs, bool restore_marks_for_biased_locking) { @@ -676,31 +623,6 @@ _process_strong_tasks->all_tasks_completed(scope->n_threads()); } -void GenCollectedHeap::cms_process_roots(StrongRootsScope* scope, - bool young_gen_as_roots, - ScanningOption so, - bool only_strong_roots, - OopsInGenClosure* root_closure, - CLDClosure* cld_closure) { - MarkingCodeBlobClosure mark_code_closure(root_closure, !CodeBlobToOopClosure::FixRelocations); - OopsInGenClosure* weak_roots = only_strong_roots ? NULL : root_closure; - CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; - - process_roots(scope, so, root_closure, weak_roots, cld_closure, weak_cld_closure, &mark_code_closure); - if (!only_strong_roots) { - process_string_table_roots(scope, root_closure); - } - - if (young_gen_as_roots && - !_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) { - root_closure->set_generation(_young_gen); - _young_gen->oop_iterate(root_closure); - root_closure->reset_generation(); - } - - _process_strong_tasks->all_tasks_completed(scope->n_threads()); -} - void GenCollectedHeap::full_process_roots(StrongRootsScope* scope, bool is_adjust_phase, ScanningOption so, @@ -765,14 +687,7 @@ // public collection interfaces void GenCollectedHeap::collect(GCCause::Cause cause) { - if (should_do_concurrent_full_gc(cause)) { -#if INCLUDE_ALL_GCS - // Mostly concurrent full collection. - collect_mostly_concurrent(cause); -#else // INCLUDE_ALL_GCS - ShouldNotReachHere(); -#endif // INCLUDE_ALL_GCS - } else if (cause == GCCause::_wb_young_gc) { + if (cause == GCCause::_wb_young_gc) { // Young collection for the WhiteBox API. collect(cause, YoungGen); } else { @@ -819,44 +734,6 @@ } } -#if INCLUDE_ALL_GCS -bool GenCollectedHeap::create_cms_collector() { - - assert(_old_gen->kind() == Generation::ConcurrentMarkSweep, - "Unexpected generation kinds"); - // Skip two header words in the block content verification - NOT_PRODUCT(_skip_header_HeapWords = CMSCollector::skip_header_HeapWords();) - assert(_gen_policy->is_concurrent_mark_sweep_policy(), "Unexpected policy type"); - CMSCollector* collector = - new CMSCollector((ConcurrentMarkSweepGeneration*)_old_gen, - _rem_set, - _gen_policy->as_concurrent_mark_sweep_policy()); - - if (collector == NULL || !collector->completed_initialization()) { - if (collector) { - delete collector; // Be nice in embedded situation - } - vm_shutdown_during_initialization("Could not create CMS collector"); - return false; - } - return true; // success -} - -void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) { - assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock"); - - MutexLocker ml(Heap_lock); - // Read the GC counts while holding the Heap_lock - unsigned int full_gc_count_before = total_full_collections(); - unsigned int gc_count_before = total_collections(); - { - MutexUnlocker mu(Heap_lock); - VM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause); - VMThread::execute(&op); - } -} -#endif // INCLUDE_ALL_GCS - void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { do_full_collection(clear_all_soft_refs, OldGen); } @@ -1099,8 +976,9 @@ GenCollectedHeap* GenCollectedHeap::heap() { CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "Uninitialized access to GenCollectedHeap::heap()"); - assert(heap->kind() == CollectedHeap::GenCollectedHeap, "Not a GenCollectedHeap"); - return (GenCollectedHeap*)heap; + assert(heap->kind() == CollectedHeap::GenCollectedHeap || + heap->kind() == CollectedHeap::CMSHeap, "Not a GenCollectedHeap"); + return (GenCollectedHeap*) heap; } void GenCollectedHeap::prepare_for_compaction() { @@ -1128,34 +1006,9 @@ } void GenCollectedHeap::gc_threads_do(ThreadClosure* tc) const { - if (workers() != NULL) { - workers()->threads_do(tc); - } -#if INCLUDE_ALL_GCS - if (UseConcMarkSweepGC) { - ConcurrentMarkSweepThread::threads_do(tc); - } -#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_gc_threads_on(outputStream* st) const { -#if INCLUDE_ALL_GCS - if (UseConcMarkSweepGC) { - workers()->print_worker_threads_on(st); - ConcurrentMarkSweepThread::print_all_on(st); - } -#endif // INCLUDE_ALL_GCS -} - -void GenCollectedHeap::print_on_error(outputStream* st) const { - this->CollectedHeap::print_on_error(st); - -#if INCLUDE_ALL_GCS - if (UseConcMarkSweepGC) { - st->cr(); - CMSCollector::print_on_error(st); - } -#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_tracing_info() const { @@ -1187,7 +1040,6 @@ void GenCollectedHeap::gc_prologue(bool full) { assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); - always_do_update_barrier = false; // Fill TLAB's and such CollectedHeap::accumulate_statistics_all_tlabs(); ensure_parsability(true); // retire TLABs @@ -1225,8 +1077,6 @@ MetaspaceCounters::update_performance_counters(); CompressedClassSpaceCounters::update_performance_counters(); - - always_do_update_barrier = UseConcMarkSweepGC; }; #ifndef PRODUCT @@ -1307,11 +1157,3 @@ } return retVal; } - -void GenCollectedHeap::stop() { -#if INCLUDE_ALL_GCS - if (UseConcMarkSweepGC) { - ConcurrentMarkSweepThread::cmst()->stop(); - } -#endif -} diff --git a/src/share/vm/gc/shared/genCollectedHeap.hpp b/src/share/vm/gc/shared/genCollectedHeap.hpp --- a/src/share/vm/gc/shared/genCollectedHeap.hpp +++ b/src/share/vm/gc/shared/genCollectedHeap.hpp @@ -78,21 +78,34 @@ // In support of ExplicitGCInvokesConcurrent functionality unsigned int _full_collections_completed; - // Data structure for claiming the (potentially) parallel tasks in - // (gen-specific) roots processing. - SubTasksDone* _process_strong_tasks; - // Collects the given generation. void collect_generation(Generation* gen, bool full, size_t size, bool is_tlab, bool run_verification, bool clear_soft_refs, bool restore_marks_for_biased_locking); - // In block contents verification, the number of header words to skip - NOT_PRODUCT(static size_t _skip_header_HeapWords;) +protected: - WorkGang* _workers; + // The set of potentially parallel tasks in root scanning. + enum GCH_strong_roots_tasks { + GCH_PS_Universe_oops_do, + GCH_PS_JNIHandles_oops_do, + GCH_PS_ObjectSynchronizer_oops_do, + GCH_PS_FlatProfiler_oops_do, + GCH_PS_Management_oops_do, + GCH_PS_SystemDictionary_oops_do, + GCH_PS_ClassLoaderDataGraph_oops_do, + GCH_PS_jvmti_oops_do, + GCH_PS_CodeCache_oops_do, + GCH_PS_aot_oops_do, + GCH_PS_younger_gens, + // Leave this one last. + GCH_PS_NumElements + }; -protected: + // Data structure for claiming the (potentially) parallel tasks in + // (gen-specific) roots processing. + SubTasksDone* _process_strong_tasks; + // Helper functions for allocation HeapWord* attempt_allocation(size_t size, bool is_tlab, @@ -124,8 +137,6 @@ public: GenCollectedHeap(GenCollectorPolicy *policy); - WorkGang* workers() const { return _workers; } - // Returns JNI_OK on success virtual jint initialize(); @@ -135,6 +146,8 @@ // Does operations required after initialization has been done. void post_initialize(); + virtual void check_gen_kinds(); + // Initialize ("weak") refs processing support virtual void ref_processing_init(); @@ -143,11 +156,7 @@ } virtual const char* name() const { - if (UseConcMarkSweepGC) { - return "Concurrent Mark Sweep"; - } else { - return "Serial"; - } + return "Serial"; } Generation* young_gen() const { return _young_gen; } @@ -190,7 +199,7 @@ // Perform a full collection of the heap; intended for use in implementing // "System.gc". This implies as full a collection as the CollectedHeap // supports. Caller does not hold the Heap_lock on entry. - void collect(GCCause::Cause cause); + virtual void collect(GCCause::Cause cause); // The same as above but assume that the caller holds the Heap_lock. void collect_locked(GCCause::Cause cause); @@ -207,12 +216,8 @@ bool is_in(const void* p) const; // override - bool is_in_closed_subset(const void* p) const { - if (UseConcMarkSweepGC) { - return is_in_reserved(p); - } else { - return is_in(p); - } + virtual bool is_in_closed_subset(const void* p) const { + return is_in(p); } // Returns true if the reference is to an object in the reserved space @@ -278,7 +283,7 @@ } virtual bool card_mark_must_follow_store() const { - return UseConcMarkSweepGC; + return false; } // We don't need barriers for stores to objects in the @@ -344,7 +349,6 @@ virtual void print_gc_threads_on(outputStream* st) const; virtual void gc_threads_do(ThreadClosure* tc) const; virtual void print_tracing_info() const; - virtual void print_on_error(outputStream* st) const; void print_heap_change(size_t young_prev_used, size_t old_prev_used) const; @@ -383,7 +387,7 @@ SO_ScavengeCodeCache = 0x10 }; - private: + protected: void process_roots(StrongRootsScope* scope, ScanningOption so, OopClosure* strong_roots, @@ -395,24 +399,20 @@ void process_string_table_roots(StrongRootsScope* scope, OopClosure* root_closure); + // Accessor for memory state verification support + NOT_PRODUCT( + virtual size_t skip_header_HeapWords() { return 0; } + ) + + virtual void gc_prologue(bool full); + virtual void gc_epilogue(bool full); + public: void young_process_roots(StrongRootsScope* scope, OopsInGenClosure* root_closure, OopsInGenClosure* old_gen_closure, CLDClosure* cld_closure); - // If "young_gen_as_roots" is false, younger generations are - // not scanned as roots; in this case, the caller must be arranging to - // scan the younger generations itself. (For example, a generation might - // explicitly mark reachable objects in younger generations, to avoid - // excess storage retention.) - void cms_process_roots(StrongRootsScope* scope, - bool young_gen_as_roots, - ScanningOption so, - bool only_strong_roots, - OopsInGenClosure* root_closure, - CLDClosure* cld_closure); - void full_process_roots(StrongRootsScope* scope, bool is_adjust_phase, ScanningOption so, @@ -479,12 +479,8 @@ oop obj, size_t obj_size); + private: - // Accessor for memory state verification support - NOT_PRODUCT( - static size_t skip_header_HeapWords() { return _skip_header_HeapWords; } - ) - // Override void check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) PRODUCT_RETURN; @@ -499,22 +495,8 @@ // collect() and collect_locked(). Caller holds the Heap_lock on entry. void collect_locked(GCCause::Cause cause, GenerationType max_generation); - // Returns success or failure. - bool create_cms_collector(); - - // In support of ExplicitGCInvokesConcurrent functionality - bool should_do_concurrent_full_gc(GCCause::Cause cause); - void collect_mostly_concurrent(GCCause::Cause cause); - // Save the tops of the spaces in all generations void record_gen_tops_before_GC() PRODUCT_RETURN; - -protected: - void gc_prologue(bool full); - void gc_epilogue(bool full); - -public: - void stop(); }; #endif // SHARE_VM_GC_SHARED_GENCOLLECTEDHEAP_HPP diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp +++ b/src/share/vm/memory/universe.cpp @@ -83,6 +83,7 @@ #include "utilities/preserveException.hpp" #if INCLUDE_ALL_GCS #include "gc/cms/cmsCollectorPolicy.hpp" +#include "gc/cms/cmsHeap.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" @@ -710,7 +711,7 @@ } else if (UseG1GC) { return Universe::create_heap_with_policy(); } else if (UseConcMarkSweepGC) { - return Universe::create_heap_with_policy(); + return Universe::create_heap_with_policy(); #endif } else if (UseSerialGC) { return Universe::create_heap_with_policy(); diff --git a/src/share/vm/services/memoryService.cpp b/src/share/vm/services/memoryService.cpp --- a/src/share/vm/services/memoryService.cpp +++ b/src/share/vm/services/memoryService.cpp @@ -86,7 +86,8 @@ void MemoryService::set_universe_heap(CollectedHeap* heap) { CollectedHeap::Name kind = heap->kind(); switch (kind) { - case CollectedHeap::GenCollectedHeap : { + case CollectedHeap::GenCollectedHeap : + case CollectedHeap::CMSHeap : { add_gen_collected_heap_info(GenCollectedHeap::heap()); break; }