# HG changeset patch # User rkennke # Date 1499093737 -7200 # Mon Jul 03 16:55:37 2017 +0200 # Node ID 7e06742759f7b0bba84386c4a6f1bdbb6266526b # Parent 16e7ba4b426e456875e067cdb1321eaacca947c9 [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,178 @@ +/* + * 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 "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"); + bool success = create_cms_collector(); + if (!success) return JNI_ENOMEM; + + return JNI_OK; +} + +#ifdef ASSERT +void CMSHeap::check_gen_kinds() { + assert(young_gen()->kind() == Generation::ParNew, + "Wrong youngest generation type"); + assert(old_gen()->kind() == Generation::ConcurrentMarkSweep, + "Wrong generation kind"); +} +#endif + + +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 { + this->GenCollectedHeap::print_on_error(st); + st->cr(); + CMSCollector::print_on_error(st); +} + +bool CMSHeap::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 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) { + 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 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()); +} + 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,103 @@ +/* + * 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/genCollectedHeap.hpp" + +class WorkGang; + +class CMSHeap : public GenCollectedHeap { + +private: + WorkGang* _workers; + +public: + CMSHeap(GenCollectorPolicy *policy); + + // Returns JNI_OK on success + virtual jint initialize(); + +#ifdef ASSERT + virtual void check_gen_kinds(); +#endif + + + // 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: + // 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); +}; + +#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" @@ -2325,7 +2326,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(); @@ -2394,7 +2395,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(); @@ -2839,7 +2840,7 @@ HandleMark hm; MarkRefsIntoClosure notOlder(_span, &_markBitMap); - GenCollectedHeap* gch = GenCollectedHeap::heap(); + CMSHeap* gch = CMSHeap::heap(); verify_work_stacks_empty(); verify_overflow_empty(); @@ -4259,7 +4260,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 -------------- @@ -4384,7 +4385,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), @@ -4839,7 +4840,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 @@ -4898,7 +4899,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 @@ -5150,7 +5151,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, @@ -5163,7 +5164,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); @@ -5196,7 +5197,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 @@ -742,8 +742,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 @@ -88,6 +88,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,30 +58,9 @@ #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(), _rem_set(NULL), @@ -90,15 +69,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 +109,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 +145,26 @@ void GenCollectedHeap::post_initialize() { ref_processing_init(); - assert((_young_gen->kind() == Generation::DefNew) || - (_young_gen->kind() == Generation::ParNew), - "Wrong youngest generation type"); +#ifdef ASSERT + check_gen_kinds(); +#endif 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(); } +#ifdef ASSERT +void GenCollectedHeap::check_gen_kinds() { + assert(young_gen()->kind() == Generation::DefNew, + "Wrong youngest generation type"); + assert(old_gen()->kind() == Generation::MarkSweepCompact, + "Wrong generation kind"); +} +#endif + void GenCollectedHeap::ref_processing_init() { _young_gen->ref_processor_init(); _old_gen->ref_processor_init(); @@ -310,19 +276,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 +629,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 +693,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 +740,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 +982,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 +1012,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 { @@ -1307,11 +1166,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 @@ -34,6 +34,23 @@ class SubTasksDone; class WorkGang; +// 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 +}; + // A "GenCollectedHeap" is a CollectedHeap that uses generational // collection. It has two generations, young and old. class GenCollectedHeap : public CollectedHeap { @@ -78,21 +95,16 @@ // 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: + // Data structure for claiming the (potentially) parallel tasks in + // (gen-specific) roots processing. + SubTasksDone* _process_strong_tasks; - WorkGang* _workers; - -protected: // Helper functions for allocation HeapWord* attempt_allocation(size_t size, bool is_tlab, @@ -124,8 +136,6 @@ public: GenCollectedHeap(GenCollectorPolicy *policy); - WorkGang* workers() const { return _workers; } - // Returns JNI_OK on success virtual jint initialize(); @@ -135,6 +145,10 @@ // Does operations required after initialization has been done. void post_initialize(); +#ifdef ASSERT + virtual void check_gen_kinds(); +#endif + // Initialize ("weak") refs processing support virtual void ref_processing_init(); @@ -143,11 +157,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 +200,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 +217,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 +284,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 +350,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 +388,7 @@ SO_ScavengeCodeCache = 0x10 }; - private: + protected: void process_roots(StrongRootsScope* scope, ScanningOption so, OopClosure* strong_roots, @@ -401,18 +406,6 @@ 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 +472,17 @@ oop obj, size_t obj_size); -private: + +protected: + // In block contents verification, the number of header words to skip + NOT_PRODUCT(static size_t _skip_header_HeapWords;) + // Accessor for memory state verification support NOT_PRODUCT( static size_t skip_header_HeapWords() { return _skip_header_HeapWords; } ) +private: // Override void check_for_non_bad_heap_word_value(HeapWord* addr, size_t size) PRODUCT_RETURN; @@ -499,13 +497,6 @@ // 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; @@ -513,8 +504,6 @@ 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 @@ -82,6 +82,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" @@ -709,7 +710,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; }