Mercurial > hg > truffle
diff src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | d2a62e0f25eb |
children | 9646b7ff4d14 |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Aug 31 16:39:35 2012 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Sat Sep 01 13:25:18 2012 -0400 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" @@ -260,17 +261,17 @@ // The field "_initiating_occupancy" represents the occupancy percentage // at which we trigger a new collection cycle. Unless explicitly specified -// via CMSInitiating[Perm]OccupancyFraction (argument "io" below), it +// via CMSInitiatingOccupancyFraction (argument "io" below), it // is calculated by: // // Let "f" be MinHeapFreeRatio in // // _intiating_occupancy = 100-f + -// f * (CMSTrigger[Perm]Ratio/100) -// where CMSTrigger[Perm]Ratio is the argument "tr" below. +// f * (CMSTriggerRatio/100) +// where CMSTriggerRatio is the argument "tr" below. // // That is, if we assume the heap is at its desired maximum occupancy at the -// end of a collection, we let CMSTrigger[Perm]Ratio of the (purported) free +// end of a collection, we let CMSTriggerRatio of the (purported) free // space be allocated before initiating a new collection cycle. // void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) { @@ -304,12 +305,6 @@ // Initialize the _ref_processor field of CMSGen _cmsGen->set_ref_processor(_ref_processor); - // Allocate a dummy ref processor for perm gen. - ReferenceProcessor* rp2 = new ReferenceProcessor(); - if (rp2 == NULL) { - vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); - } - _permGen->set_ref_processor(rp2); } } @@ -546,11 +541,9 @@ bool CMSCollector::_foregroundGCShouldWait = false; CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, - ConcurrentMarkSweepGeneration* permGen, CardTableRS* ct, ConcurrentMarkSweepPolicy* cp): _cmsGen(cmsGen), - _permGen(permGen), _ct(ct), _ref_processor(NULL), // will be set later _conc_workers(NULL), // may be set later @@ -558,13 +551,12 @@ _start_sampling(false), _between_prologue_and_epilogue(false), _markBitMap(0, Mutex::leaf + 1, "CMS_markBitMap_lock"), - _perm_gen_verify_bit_map(0, -1 /* no mutex */, "No_lock"), _modUnionTable((CardTableModRefBS::card_shift - LogHeapWordSize), -1 /* lock-free */, "No_lock" /* dummy */), _modUnionClosure(&_modUnionTable), _modUnionClosurePar(&_modUnionTable), - // Adjust my span to cover old (cms) gen and perm gen - _span(cmsGen->reserved()._union(permGen->reserved())), + // Adjust my span to cover old (cms) gen + _span(cmsGen->reserved()), // Construct the is_alive_closure with _span & markBitMap _is_alive_closure(_span, &_markBitMap), _restart_addr(NULL), @@ -606,18 +598,8 @@ // (MUT, marking bit map etc.) to cover both generations subject to // collection. - // First check that _permGen is adjacent to _cmsGen and above it. - assert( _cmsGen->reserved().word_size() > 0 - && _permGen->reserved().word_size() > 0, - "generations should not be of zero size"); - assert(_cmsGen->reserved().intersection(_permGen->reserved()).is_empty(), - "_cmsGen and _permGen should not overlap"); - assert(_cmsGen->reserved().end() == _permGen->reserved().start(), - "_cmsGen->end() different from _permGen->start()"); - // For use by dirty card to oop closures. _cmsGen->cmsSpace()->set_collector(this); - _permGen->cmsSpace()->set_collector(this); // Allocate MUT and marking bit map { @@ -637,10 +619,6 @@ warning("Failed to allocate CMS Marking Stack"); return; } - if (!_revisitStack.allocate(CMSRevisitStackSize)) { - warning("Failed to allocate CMS Revisit Stack"); - return; - } // Support for multi-threaded concurrent phases if (CMSConcurrentMTEnabled) { @@ -710,7 +688,6 @@ } _cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio); - _permGen->init_initiating_occupancy(CMSInitiatingPermOccupancyFraction, CMSTriggerPermRatio); // Clip CMSBootstrapOccupancy between 0 and 100. _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy))) @@ -801,7 +778,6 @@ "Error"); // Choose what strong roots should be scanned depending on verification options - // and perm gen collection mode. if (!CMSClassUnloadingEnabled) { // If class unloading is disabled we want to include all classes into the root set. add_root_scanning_option(SharedHeap::SO_AllClasses); @@ -1054,15 +1030,15 @@ MutexLockerEx y(_markBitMap.lock(), Mutex::_no_safepoint_check_flag); // [see comments preceding SweepClosure::do_blk() below for details] + // + // Can the P-bits be deleted now? JJJ + // // 1. need to mark the object as live so it isn't collected // 2. need to mark the 2nd bit to indicate the object may be uninitialized // 3. need to mark the end of the object so marking, precleaning or sweeping // can skip over uninitialized or unparsable objects. An allocated // object is considered uninitialized for our purposes as long as - // its klass word is NULL. (Unparsable objects are those which are - // initialized in the sense just described, but whose sizes can still - // not be correctly determined. Note that the class of unparsable objects - // can only occur in the perm gen. All old gen objects are parsable + // its klass word is NULL. All old gen objects are parsable // as soon as they are initialized.) _markBitMap.mark(start); // object is live _markBitMap.mark(start + 1); // object is potentially uninitialized? @@ -1324,7 +1300,6 @@ // // OBJECT: klass_word installed; klass_word != 0 && klass_word & 1 == 0; // obj->size() computes correct size -// [Perm Gen objects needs to be "parsable" before they can be navigated] // // TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT // @@ -1334,7 +1309,6 @@ // // OBJECT: klass_word installed; klass_word != 0; // obj->size() computes correct size -// [Perm Gen comment above continues to hold] // // TRANSIENT: klass_word == 0; size is indeterminate until we become an OBJECT // @@ -1403,7 +1377,7 @@ assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size"); OrderAccess::storestore(); - if (UseCompressedOops) { + if (UseCompressedKlassPointers) { // Copy gap missed by (aligned) header size calculation below obj->set_klass_gap(old->klass_gap()); } @@ -1464,7 +1438,6 @@ ps->promo.promoted_oops_iterate_nv(dummy_cl); } -// XXXPERM bool ConcurrentMarkSweepGeneration::should_collect(bool full, size_t size, bool tlab) @@ -1517,7 +1490,8 @@ gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate()); gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy()); gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); - gclog_or_tty->print_cr("initiatingPermOccupancy=%3.7f", _permGen->initiating_occupancy()); + gclog_or_tty->print_cr("metadata initialized %d", + MetaspaceGC::should_concurrent_collect()); } // ------------------------------------------------------------------ @@ -1546,7 +1520,7 @@ } } - // Otherwise, we start a collection cycle if either the perm gen or + // Otherwise, we start a collection cycle if // old gen want a collection cycle started. Each may use // an appropriate criterion for making this decision. // XXX We need to make sure that the gen expansion @@ -1571,22 +1545,19 @@ return true; } - if (CMSClassUnloadingEnabled && _permGen->should_concurrent_collect()) { - bool res = update_should_unload_classes(); - if (res) { + if (MetaspaceGC::should_concurrent_collect()) { if (Verbose && PrintGCDetails) { - gclog_or_tty->print_cr("CMS perm gen initiated"); + gclog_or_tty->print("CMSCollector: collect for metadata allocation "); } return true; } - } + return false; } // Clear _expansion_cause fields of constituent generations void CMSCollector::clear_expansion_cause() { _cmsGen->clear_expansion_cause(); - _permGen->clear_expansion_cause(); } // We should be conservative in starting a collection cycle. To @@ -1609,7 +1580,7 @@ // going to fail, or there is believed to be excessive fragmentation in // the generation, etc... or ... // [.(currently done by CMSCollector::shouldConcurrentCollect() only for -// the case of the old generation, not the perm generation; see CR 6543076): +// the case of the old generation; see CR 6543076): // we may be approaching a point at which allocation requests may fail because // we will be out of sufficient free space given allocation rate estimates.] bool ConcurrentMarkSweepGeneration::should_concurrent_collect() const { @@ -1902,13 +1873,13 @@ return; } -// Resize the perm generation and the tenured generation +// Resize the tenured generation // after obtaining the free list locks for the // two generations. void CMSCollector::compute_new_size() { assert_locked_or_safepoint(Heap_lock); FreelistLocker z(this); - _permGen->compute_new_size(); + MetaspaceGC::compute_new_size(); _cmsGen->compute_new_size(); } @@ -2012,6 +1983,9 @@ assert(_collectorState != Idling || _modUnionTable.isAllClear(), "_modUnionTable should be clear if the baton was not passed"); _modUnionTable.clear_all(); + assert(_collectorState != Idling || _ct->klass_rem_set()->mod_union_is_clear(), + "mod union for klasses should be clear if the baton was passed"); + _ct->klass_rem_set()->clear_mod_union(); // We must adjust the allocation statistics being maintained // in the free list space. We do so by reading and clearing @@ -2050,10 +2024,6 @@ _cmsGen->reset_after_compaction(); _concurrent_cycles_since_last_unload = 0; - if (verifying() && !should_unload_classes()) { - perm_gen_verify_bit_map()->clear_all(); - } - // Clear any data recorded in the PLAB chunk arrays. if (_survivor_plab_array != NULL) { reset_survivor_plab_arrays(); @@ -2117,21 +2087,18 @@ // Get locks for all free lists in all generations that this // collector is responsible for _cmsGen->freelistLock()->lock_without_safepoint_check(); - _permGen->freelistLock()->lock_without_safepoint_check(); } void CMSCollector::releaseFreelistLocks() const { // Release locks for all free lists in all generations that this // collector is responsible for _cmsGen->freelistLock()->unlock(); - _permGen->freelistLock()->unlock(); } bool CMSCollector::haveFreelistLocks() const { // Check locks for all free lists in all generations that this // collector is responsible for assert_lock_strong(_cmsGen->freelistLock()); - assert_lock_strong(_permGen->freelistLock()); PRODUCT_ONLY(ShouldNotReachHere()); return true; } @@ -2191,6 +2158,10 @@ // Reset the expansion cause, now that we are about to begin // a new cycle. clear_expansion_cause(); + + // Clear the MetaspaceGC flag since a concurrent collection + // is starting but also clear it after the collection. + MetaspaceGC::set_should_concurrent_collect(false); } // Decide if we want to enable class unloading as part of the // ensuing concurrent GC cycle. @@ -2368,6 +2339,9 @@ reset(true); assert(_collectorState == Idling, "Collector state should " "have changed"); + + MetaspaceGC::set_should_concurrent_collect(false); + stats().record_cms_end(); // Don't move the concurrent_phases_end() and compute_new_size() // calls to here because a preempted background collection @@ -2584,7 +2558,7 @@ // The role of the varaible _between_prologue_and_epilogue is to // enforce the invocation protocol. void CMSCollector::gc_prologue(bool full) { - // Call gc_prologue_work() for each CMSGen and PermGen that + // Call gc_prologue_work() for the CMSGen // we are responsible for. // The following locking discipline assumes that we are only called @@ -2592,7 +2566,7 @@ assert(SafepointSynchronize::is_at_safepoint(), "world is stopped assumption"); // The CMSCollector prologue must call the gc_prologues for the - // "generations" (including PermGen if any) that it's responsible + // "generations" that it's responsible // for. assert( Thread::current()->is_VM_thread() @@ -2610,19 +2584,29 @@ // set a bit saying prologue has been called; cleared in epilogue _between_prologue_and_epilogue = true; // Claim locks for common data structures, then call gc_prologue_work() - // for each CMSGen and PermGen that we are responsible for. + // for each CMSGen. getFreelistLocks(); // gets free list locks on constituent spaces bitMapLock()->lock_without_safepoint_check(); // Should call gc_prologue_work() for all cms gens we are responsible for - bool registerClosure = _collectorState >= Marking + bool duringMarking = _collectorState >= Marking && _collectorState < Sweeping; + + // The young collections clear the modified oops state, which tells if + // there are any modified oops in the class. The remark phase also needs + // that information. Tell the young collection to save the union of all + // modified klasses. + if (duringMarking) { + _ct->klass_rem_set()->set_accumulate_modified_oops(true); + } + + bool registerClosure = duringMarking; + ModUnionClosure* muc = CollectedHeap::use_parallel_gc_threads() ? &_modUnionClosurePar : &_modUnionClosure; _cmsGen->gc_prologue_work(full, registerClosure, muc); - _permGen->gc_prologue_work(full, registerClosure, muc); if (!full) { stats().record_gc0_begin(); @@ -2686,8 +2670,9 @@ assert(haveFreelistLocks(), "must have freelist locks"); assert_lock_strong(bitMapLock()); + _ct->klass_rem_set()->set_accumulate_modified_oops(false); + _cmsGen->gc_epilogue_work(full); - _permGen->gc_epilogue_work(full); if (_collectorState == AbortablePreclean || _collectorState == Precleaning) { // in case sampling was not already enabled, enable it @@ -2697,14 +2682,12 @@ _eden_chunk_index = 0; size_t cms_used = _cmsGen->cmsSpace()->used(); - size_t perm_used = _permGen->cmsSpace()->used(); // update performance counters - this uses a special version of // update_counters() that allows the utilization to be passed as a // parameter, avoiding multiple calls to used(). // _cmsGen->update_counters(cms_used); - _permGen->update_counters(perm_used); if (CMSIncrementalMode) { icms_update_allocation_limits(); @@ -2902,6 +2885,9 @@ HandleMark hm; GenCollectedHeap* gch = GenCollectedHeap::heap(); + // Get a clear set of claim bits for the strong roots processing to work with. + ClassLoaderDataGraph::clear_claimed_marks(); + // Mark from roots one level into CMS MarkRefsIntoClosure notOlder(_span, verification_mark_bm()); gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. @@ -2909,16 +2895,16 @@ gch->gen_process_strong_roots(_cmsGen->level(), true, // younger gens are roots true, // activate StrongRootsScope - true, // collecting perm gen + false, // not scavenging SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, true, // walk code active on stacks - NULL); + NULL, + NULL); // SSS: Provide correct closure // Now mark from the roots - assert(_revisitStack.isEmpty(), "Should be empty"); MarkFromRootsClosure markFromRootsClosure(this, _span, - verification_mark_bm(), verification_mark_stack(), &_revisitStack, + verification_mark_bm(), verification_mark_stack(), false /* don't yield */, true /* verifying */); assert(_restart_addr == NULL, "Expected pre-condition"); verification_mark_bm()->iterate(&markFromRootsClosure); @@ -2932,9 +2918,6 @@ } assert(verification_mark_stack()->isEmpty(), "Should have been drained"); verify_work_stacks_empty(); - // Should reset the revisit stack above, since no class tree - // surgery is forthcoming. - _revisitStack.reset(); // throwing away all contents // Marking completed -- now verify that each bit marked in // verification_mark_bm() is also marked in markBitMap(); flag all @@ -2948,26 +2931,46 @@ } } +class VerifyKlassOopsKlassClosure : public KlassClosure { + class VerifyKlassOopsClosure : public OopClosure { + CMSBitMap* _bitmap; + public: + VerifyKlassOopsClosure(CMSBitMap* bitmap) : _bitmap(bitmap) { } + void do_oop(oop* p) { guarantee(*p == NULL || _bitmap->isMarked((HeapWord*) *p), "Should be marked"); } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } + } _oop_closure; + public: + VerifyKlassOopsKlassClosure(CMSBitMap* bitmap) : _oop_closure(bitmap) {} + void do_klass(Klass* k) { + k->oops_do(&_oop_closure); + } +}; + void CMSCollector::verify_after_remark_work_2() { ResourceMark rm; HandleMark hm; GenCollectedHeap* gch = GenCollectedHeap::heap(); + // Get a clear set of claim bits for the strong roots processing to work with. + ClassLoaderDataGraph::clear_claimed_marks(); + // Mark from roots one level into CMS MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(), markBitMap()); + CMKlassClosure klass_closure(¬Older); + gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. gch->gen_process_strong_roots(_cmsGen->level(), true, // younger gens are roots true, // activate StrongRootsScope - true, // collecting perm gen + false, // not scavenging SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, true, // walk code active on stacks - NULL); + NULL, + &klass_closure); // Now mark from the roots - assert(_revisitStack.isEmpty(), "Should be empty"); MarkFromRootsVerifyClosure markFromRootsClosure(this, _span, verification_mark_bm(), markBitMap(), verification_mark_stack()); assert(_restart_addr == NULL, "Expected pre-condition"); @@ -2982,9 +2985,9 @@ } assert(verification_mark_stack()->isEmpty(), "Should have been drained"); verify_work_stacks_empty(); - // Should reset the revisit stack above, since no class tree - // surgery is forthcoming. - _revisitStack.reset(); // throwing away all contents + + VerifyKlassOopsKlassClosure verify_klass_oops(verification_mark_bm()); + ClassLoaderDataGraph::classes_do(&verify_klass_oops); // Marking completed -- now verify that each bit marked in // verification_mark_bm() is also marked in markBitMap(); flag all @@ -3046,7 +3049,7 @@ } void -ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, OopClosure* cl) { +ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { if (freelistLock()->owned_by_self()) { Generation::oop_iterate(mr, cl); } else { @@ -3056,7 +3059,7 @@ } void -ConcurrentMarkSweepGeneration::oop_iterate(OopClosure* cl) { +ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) { if (freelistLock()->owned_by_self()) { Generation::oop_iterate(cl); } else { @@ -3086,10 +3089,6 @@ } void -ConcurrentMarkSweepGeneration::pre_adjust_pointers() { -} - -void ConcurrentMarkSweepGeneration::post_compact() { } @@ -3123,7 +3122,6 @@ void CMSCollector::verify() { _cmsGen->verify(); - _permGen->verify(); } #ifndef PRODUCT @@ -3149,15 +3147,12 @@ #endif // PRODUCT // Decide if we want to enable class unloading as part of the -// ensuing concurrent GC cycle. We will collect the perm gen and +// ensuing concurrent GC cycle. We will collect and // unload classes if it's the case that: // (1) an explicit gc request has been made and the flag // ExplicitGCInvokesConcurrentAndUnloadsClasses is set, OR // (2) (a) class unloading is enabled at the command line, and -// (b) (i) perm gen threshold has been crossed, or -// (ii) old gen is getting really full, or -// (iii) the previous N CMS collections did not collect the -// perm gen +// (b) old gen is getting really full // NOTE: Provided there is no change in the state of the heap between // calls to this method, it should have idempotent results. Moreover, // its results should be monotonically increasing (i.e. going from 0 to 1, @@ -3165,10 +3160,10 @@ // not collected. For the implementation below, it must thus rely on // the property that concurrent_cycles_since_last_unload() // will not decrease unless a collection cycle happened and that -// _permGen->should_concurrent_collect() and _cmsGen->is_too_full() are +// _cmsGen->is_too_full() are // themselves also monotonic in that sense. See check_monotonicity() // below. -bool CMSCollector::update_should_unload_classes() { +void CMSCollector::update_should_unload_classes() { _should_unload_classes = false; // Condition 1 above if (_full_gc_requested && ExplicitGCInvokesConcurrentAndUnloadsClasses) { @@ -3177,10 +3172,8 @@ // Disjuncts 2.b.(i,ii,iii) above _should_unload_classes = (concurrent_cycles_since_last_unload() >= CMSClassUnloadingMaxInterval) - || _permGen->should_concurrent_collect() || _cmsGen->is_too_full(); } - return _should_unload_classes; } bool ConcurrentMarkSweepGeneration::is_too_full() const { @@ -3203,25 +3196,6 @@ // Not unloading classes this cycle assert(!should_unload_classes(), "Inconsitency!"); if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { - // We were not verifying, or we _were_ unloading classes in the last cycle, - // AND some verification options are enabled this cycle; in this case, - // we must make sure that the deadness map is allocated if not already so, - // and cleared (if already allocated previously -- - // CMSBitMap::sizeInBits() is used to determine if it's allocated). - if (perm_gen_verify_bit_map()->sizeInBits() == 0) { - if (!perm_gen_verify_bit_map()->allocate(_permGen->reserved())) { - warning("Failed to allocate permanent generation verification CMS Bit Map;\n" - "permanent generation verification disabled"); - return; // Note that we leave verification disabled, so we'll retry this - // allocation next cycle. We _could_ remember this failure - // and skip further attempts and permanently disable verification - // attempts if that is considered more desirable. - } - assert(perm_gen_verify_bit_map()->covers(_permGen->reserved()), - "_perm_gen_ver_bit_map inconsistency?"); - } else { - perm_gen_verify_bit_map()->clear_all(); - } // Include symbols, strings and code cache elements to prevent their resurrection. add_root_scanning_option(rso); set_verifying(true); @@ -3241,10 +3215,6 @@ if (_span.contains(p)) { if (_cmsGen->cmsSpace()->is_in_reserved(addr)) { return _cmsGen->cmsSpace()->block_start(p); - } else { - assert(_permGen->cmsSpace()->is_in_reserved(addr), - "Inconsistent _span?"); - return _permGen->cmsSpace()->block_start(p); } } return NULL; @@ -3560,18 +3530,27 @@ // weak reference processing has not started yet. ref_processor()->set_enqueuing_is_done(false); + // Need to remember all newly created CLDs, + // so that we can guarantee that the remark finds them. + ClassLoaderDataGraph::remember_new_clds(true); + + // Whenever a CLD is found, it will be claimed before proceeding to mark + // the klasses. The claimed marks need to be cleared before marking starts. + ClassLoaderDataGraph::clear_claimed_marks(); + + CMKlassClosure klass_closure(¬Older); { - // This is not needed. DEBUG_ONLY(RememberKlassesChecker imx(true);) COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;) gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. gch->gen_process_strong_roots(_cmsGen->level(), true, // younger gens are roots true, // activate StrongRootsScope - true, // collecting perm gen + false, // not scavenging SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, true, // walk all of code cache if (so & SO_CodeCache) - NULL); + NULL, + &klass_closure); } // Clear mod-union table; it will be dirtied in the prologue of @@ -3582,6 +3561,8 @@ " or no bits are set in the gc_prologue before the start of the next " "subsequent marking phase."); + assert(_ct->klass_rem_set()->mod_union_is_clear(), "Must be"); + // Save the end of the used_region of the constituent generations // to be used to limit the extent of sweep in each generation. save_sweep_limits(); @@ -3672,13 +3653,8 @@ // already have locks assert_lock_strong(bitMapLock()); - // Clear the revisit stack, just in case there are any - // obsolete contents from a short-circuited previous CMS cycle. - _revisitStack.reset(); verify_work_stacks_empty(); verify_overflow_empty(); - assert(_revisitStack.isEmpty(), "tabula rasa"); - DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());) bool result = false; if (CMSConcurrentMTEnabled && ConcGCThreads > 0) { result = do_marking_mt(asynch); @@ -3726,7 +3702,6 @@ bool _asynch; bool _result; CompactibleFreeListSpace* _cms_space; - CompactibleFreeListSpace* _perm_space; char _pad_front[64]; // padding to ... HeapWord* _global_finger; // ... avoid sharing cache line char _pad_back[64]; @@ -3745,14 +3720,12 @@ public: CMSConcMarkingTask(CMSCollector* collector, CompactibleFreeListSpace* cms_space, - CompactibleFreeListSpace* perm_space, bool asynch, YieldingFlexibleWorkGang* workers, OopTaskQueueSet* task_queues): YieldingFlexibleGangTask("Concurrent marking done multi-threaded"), _collector(collector), _cms_space(cms_space), - _perm_space(perm_space), _asynch(asynch), _n_workers(0), _result(true), _task_queues(task_queues), _term(_n_workers, task_queues, _collector), @@ -3761,8 +3734,6 @@ _requested_size = _n_workers; _term.set_task(this); _term_term.set_task(this); - assert(_cms_space->bottom() < _perm_space->bottom(), - "Finger incorrectly initialized below"); _restart_addr = _global_finger = _cms_space->bottom(); } @@ -3791,8 +3762,6 @@ void reset(HeapWord* ra) { assert(_global_finger >= _cms_space->end(), "Postcondition of ::work(i)"); - assert(_global_finger >= _perm_space->end(), "Postcondition of ::work(i)"); - assert(ra < _perm_space->end(), "ra too large"); _restart_addr = _global_finger = ra; _term.reset_for_reuse(); } @@ -3871,17 +3840,6 @@ // XXX: need xxx/xxx type of notation, two timers } - // ... do the same for the _perm_space - _timer.reset(); - _timer.start(); - do_scan_and_mark(worker_id, _perm_space); - _timer.stop(); - if (PrintCMSStatistics != 0) { - gclog_or_tty->print_cr("Finished perm space scanning in %dth thread: %3.3f sec", - worker_id, _timer.seconds()); - // XXX: need xxx/xxx type of notation, two timers - } - // ... do work stealing _timer.reset(); _timer.start(); @@ -3899,8 +3857,12 @@ // expanded since the completion of the concurrent // marking. XXX This will likely change under a strict // ABORT semantics. - assert(_global_finger > _cms_space->end() && - _global_finger >= _perm_space->end(), + // After perm removal the comparison was changed to + // greater than or equal to from strictly greater than. + // Before perm removal the highest address sweep would + // have been at the end of perm gen but now is at the + // end of the tenured gen. + assert(_global_finger >= _cms_space->end(), "All tasks have been completed"); DEBUG_ONLY(_collector->verify_overflow_empty();) } @@ -4025,7 +3987,6 @@ &_collector->_markBitMap, work_queue(i), &_collector->_markStack, - &_collector->_revisitStack, _asynch); _collector->_markBitMap.iterate(&cl, my_span.start(), my_span.end()); } // else nothing to do for this task @@ -4042,8 +4003,9 @@ pst->all_tasks_completed(); } -class Par_ConcMarkingClosure: public Par_KlassRememberingOopClosure { +class Par_ConcMarkingClosure: public CMSOopClosure { private: + CMSCollector* _collector; CMSConcMarkingTask* _task; MemRegion _span; CMSBitMap* _bit_map; @@ -4053,9 +4015,9 @@ DO_OOP_WORK_DEFN public: Par_ConcMarkingClosure(CMSCollector* collector, CMSConcMarkingTask* task, OopTaskQueue* work_queue, - CMSBitMap* bit_map, CMSMarkStack* overflow_stack, - CMSMarkStack* revisit_stack): - Par_KlassRememberingOopClosure(collector, collector->ref_processor(), revisit_stack), + CMSBitMap* bit_map, CMSMarkStack* overflow_stack): + CMSOopClosure(collector->ref_processor()), + _collector(collector), _task(task), _span(collector->_span), _work_queue(work_queue), @@ -4064,6 +4026,7 @@ { } virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); + void trim_queue(size_t max); void handle_stack_overflow(HeapWord* lost); void do_yield_check() { @@ -4128,7 +4091,6 @@ assert(new_oop->is_oop(), "Should be an oop"); assert(_bit_map->isMarked((HeapWord*)new_oop), "Grey object"); assert(_span.contains((HeapWord*)new_oop), "Not in span"); - assert(new_oop->is_parsable(), "Should be parsable"); new_oop->oop_iterate(this); // do_oop() above do_yield_check(); } @@ -4156,9 +4118,8 @@ oop obj_to_scan; CMSBitMap* bm = &(_collector->_markBitMap); CMSMarkStack* ovflw = &(_collector->_markStack); - CMSMarkStack* revisit = &(_collector->_revisitStack); int* seed = _collector->hash_seed(i); - Par_ConcMarkingClosure cl(_collector, this, work_q, bm, ovflw, revisit); + Par_ConcMarkingClosure cl(_collector, this, work_q, bm, ovflw); while (true) { cl.trim_queue(0); assert(work_q->size() == 0, "Should have been emptied above"); @@ -4184,7 +4145,6 @@ void CMSConcMarkingTask::coordinator_yield() { assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "CMS thread should hold CMS token"); - DEBUG_ONLY(RememberKlassesChecker mux(false);) // First give up the locks, then yield, then re-lock // We should probably use a constructor/destructor idiom to // do this unlock/lock or modify the MutexUnlocker class to @@ -4244,11 +4204,9 @@ conc_workers()->set_active_workers(num_workers); CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace(); - CompactibleFreeListSpace* perm_space = _permGen->cmsSpace(); CMSConcMarkingTask tsk(this, cms_space, - perm_space, asynch, conc_workers(), task_queues()); @@ -4258,12 +4216,10 @@ // below? In particular, may be we need to subclass the SequantialSubTasksDone // class?? XXX cms_space ->initialize_sequential_subtasks_for_marking(num_workers); - perm_space->initialize_sequential_subtasks_for_marking(num_workers); // Refs discovery is already non-atomic. assert(!ref_processor()->discovery_is_atomic(), "Should be non-atomic"); assert(ref_processor()->discovery_is_mt(), "Discovery should be MT"); - DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());) conc_workers()->start_task(&tsk); while (tsk.yielded()) { tsk.coordinator_yield(); @@ -4296,8 +4252,6 @@ tsk.reset(_restart_addr); cms_space ->initialize_sequential_subtasks_for_marking(num_workers, _restart_addr); - perm_space->initialize_sequential_subtasks_for_marking(num_workers, - _restart_addr); _restart_addr = NULL; // Get the workers going again conc_workers()->start_task(&tsk); @@ -4318,7 +4272,7 @@ // Temporarily make refs discovery single threaded (non-MT) ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); MarkFromRootsClosure markFromRootsClosure(this, _span, &_markBitMap, - &_markStack, &_revisitStack, CMSYield && asynch); + &_markStack, CMSYield && asynch); // the last argument to iterate indicates whether the iteration // should be incremental with periodic yields. _markBitMap.iterate(&markFromRootsClosure); @@ -4510,8 +4464,7 @@ CMSPrecleanRefsYieldClosure yield_cl(this); assert(rp->span().equals(_span), "Spans should be equal"); CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, - &_markStack, &_revisitStack, - true /* preclean */); + &_markStack, true /* preclean */); CMSDrainMarkingStackClosure complete_trace(this, _span, &_markBitMap, &_markStack, &keep_alive, true /* preclean */); @@ -4538,8 +4491,7 @@ // tweaking for better performance and some restructuring // for cleaner interfaces. rp->preclean_discovered_references( - rp->is_alive_non_header(), &keep_alive, &complete_trace, - &yield_cl, should_unload_classes()); + rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl); } if (clean_survivor) { // preclean the active survivor space(s) @@ -4550,8 +4502,7 @@ DefNewGeneration* dng = (DefNewGeneration*)_young_gen; PushAndMarkClosure pam_cl(this, _span, ref_processor(), &_markBitMap, &_modUnionTable, - &_markStack, &_revisitStack, - true /* precleaning phase */); + &_markStack, true /* precleaning phase */); stopTimer(); CMSTokenSyncWithLocks ts(true /* is cms thread */, bitMapLock()); @@ -4561,20 +4512,19 @@ SurvivorSpacePrecleanClosure sss_cl(this, _span, &_markBitMap, &_markStack, &pam_cl, before_count, CMSYield); - DEBUG_ONLY(RememberKlassesChecker mx(should_unload_classes());) dng->from()->object_iterate_careful(&sss_cl); dng->to()->object_iterate_careful(&sss_cl); } MarkRefsIntoAndScanClosure mrias_cl(_span, ref_processor(), &_markBitMap, &_modUnionTable, - &_markStack, &_revisitStack, this, CMSYield, + &_markStack, this, CMSYield, true /* precleaning phase */); // CAUTION: The following closure has persistent state that may need to // be reset upon a decrease in the sequence of addresses it // processes. ScanMarkedObjectsAgainCarefullyClosure smoac_cl(this, _span, - &_markBitMap, &_markStack, &_revisitStack, &mrias_cl, CMSYield); + &_markBitMap, &_markStack, &mrias_cl, CMSYield); // Preclean dirty cards in ModUnionTable and CardTable using // appropriate convergence criterion; @@ -4591,9 +4541,6 @@ numIter < CMSPrecleanIter; numIter++, lastNumCards = curNumCards, cumNumCards += curNumCards) { curNumCards = preclean_mod_union_table(_cmsGen, &smoac_cl); - if (CMSPermGenPrecleaningEnabled) { - curNumCards += preclean_mod_union_table(_permGen, &smoac_cl); - } if (Verbose && PrintGCDetails) { gclog_or_tty->print(" (modUnionTable: %d cards)", curNumCards); } @@ -4611,10 +4558,10 @@ break; } } + + preclean_klasses(&mrias_cl, _cmsGen->freelistLock()); + curNumCards = preclean_card_table(_cmsGen, &smoac_cl); - if (CMSPermGenPrecleaningEnabled) { - curNumCards += preclean_card_table(_permGen, &smoac_cl); - } cumNumCards += curNumCards; if (PrintGCDetails && PrintCMSStatistics != 0) { gclog_or_tty->print_cr(" (cardTable: %d cards, re-scanned %d cards, %d iterations)", @@ -4663,13 +4610,6 @@ verify_work_stacks_empty(); verify_overflow_empty(); - // Turn off checking for this method but turn it back on - // selectively. There are yield points in this method - // but it is difficult to turn the checking off just around - // the yield points. It is simpler to selectively turn - // it on. - DEBUG_ONLY(RememberKlassesChecker mux(false);) - // strategy: starting with the first card, accumulate contiguous // ranges of dirty cards; clear these cards, then scan the region // covered by these cards. @@ -4732,7 +4672,6 @@ verify_work_stacks_empty(); verify_overflow_empty(); sample_eden(); - DEBUG_ONLY(RememberKlassesChecker mx(should_unload_classes());) stop_point = gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl); } @@ -4743,9 +4682,8 @@ // the bits corresponding to the partially-scanned or unscanned // cards. We'll either restart at the next block boundary or // abort the preclean. - assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) || - (_collectorState == AbortablePreclean && should_abort_preclean()), - "Unparsable objects should only be in perm gen."); + assert((_collectorState == AbortablePreclean && should_abort_preclean()), + "Should only be AbortablePreclean."); _modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end())); if (should_abort_preclean()) { break; // out of preclean loop @@ -4820,17 +4758,11 @@ sample_eden(); verify_work_stacks_empty(); verify_overflow_empty(); - DEBUG_ONLY(RememberKlassesChecker mx(should_unload_classes());) HeapWord* stop_point = gen->cmsSpace()->object_iterate_careful_m(dirtyRegion, cl); if (stop_point != NULL) { - // The careful iteration stopped early because it found an - // uninitialized object. Redirty the bits corresponding to the - // partially-scanned or unscanned cards, and start again at the - // next block boundary. - assert(CMSPermGenPrecleaningEnabled || - (_collectorState == AbortablePreclean && should_abort_preclean()), - "Unparsable objects should only be in perm gen."); + assert((_collectorState == AbortablePreclean && should_abort_preclean()), + "Should only be AbortablePreclean."); _ct->ct_bs()->invalidate(MemRegion(stop_point, dirtyRegion.end())); if (should_abort_preclean()) { break; // out of preclean loop @@ -4848,6 +4780,35 @@ return cumNumDirtyCards; } +class PrecleanKlassClosure : public KlassClosure { + CMKlassClosure _cm_klass_closure; + public: + PrecleanKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {} + void do_klass(Klass* k) { + if (k->has_accumulated_modified_oops()) { + k->clear_accumulated_modified_oops(); + + _cm_klass_closure.do_klass(k); + } + } +}; + +// The freelist lock is needed to prevent asserts, is it really needed? +void CMSCollector::preclean_klasses(MarkRefsIntoAndScanClosure* cl, Mutex* freelistLock) { + + cl->set_freelistLock(freelistLock); + + CMSTokenSyncWithLocks ts(true, freelistLock, bitMapLock()); + + // SSS: Add equivalent to ScanMarkedObjectsAgainCarefullyClosure::do_yield_check and should_abort_preclean? + // SSS: We should probably check if precleaning should be aborted, at suitable intervals? + PrecleanKlassClosure preclean_klass_closure(cl); + ClassLoaderDataGraph::classes_do(&preclean_klass_closure); + + verify_work_stacks_empty(); + verify_overflow_empty(); +} + void CMSCollector::checkpointRootsFinal(bool asynch, bool clear_all_soft_refs, bool init_mark_was_synchronous) { assert(_collectorState == FinalMarking, "incorrect state transition?"); @@ -4922,7 +4883,6 @@ assert(haveFreelistLocks(), "must have free list locks"); assert_lock_strong(bitMapLock()); - DEBUG_ONLY(RememberKlassesChecker fmx(should_unload_classes());) if (!init_mark_was_synchronous) { // We might assume that we need not fill TLAB's when // CMSScavengeBeforeRemark is set, because we may have just done @@ -5027,9 +4987,6 @@ _markStack._hit_limit = 0; _markStack._failed_double = 0; - // Check that all the klasses have been checked - assert(_revisitStack.isEmpty(), "Not all klasses revisited"); - if ((VerifyAfterGC || VerifyDuringGC) && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { verify_after_remark(); @@ -5038,8 +4995,10 @@ // Change under the freelistLocks. _collectorState = Sweeping; // Call isAllClear() under bitMapLock - assert(_modUnionTable.isAllClear(), "Should be clear by end of the" - " final marking"); + assert(_modUnionTable.isAllClear(), + "Should be clear by end of the final marking"); + assert(_ct->klass_rem_set()->mod_union_is_clear(), + "Should be clear by end of the final marking"); if (UseAdaptiveSizePolicy) { size_policy()->checkpoint_roots_final_end(gch->gc_cause()); } @@ -5050,7 +5009,6 @@ CMSCollector* _collector; int _n_workers; CompactibleFreeListSpace* _cms_space; - CompactibleFreeListSpace* _perm_space; // The per-thread work queues, available here for stealing. OopTaskQueueSet* _task_queues; @@ -5061,12 +5019,11 @@ // workers to be taken from the active workers in the work gang. CMSParRemarkTask(CMSCollector* collector, CompactibleFreeListSpace* cms_space, - CompactibleFreeListSpace* perm_space, int n_workers, FlexibleWorkGang* workers, OopTaskQueueSet* task_queues): AbstractGangTask("Rescan roots and grey objects in parallel"), _collector(collector), - _cms_space(cms_space), _perm_space(perm_space), + _cms_space(cms_space), _n_workers(n_workers), _task_queues(task_queues), _term(n_workers, task_queues) { } @@ -5094,6 +5051,29 @@ void do_work_steal(int i, Par_MarkRefsIntoAndScanClosure* cl, int* seed); }; +class RemarkKlassClosure : public KlassClosure { + CMKlassClosure _cm_klass_closure; + public: + RemarkKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {} + void do_klass(Klass* k) { + // Check if we have modified any oops in the Klass during the concurrent marking. + if (k->has_accumulated_modified_oops()) { + k->clear_accumulated_modified_oops(); + + // We could have transfered the current modified marks to the accumulated marks, + // like we do with the Card Table to Mod Union Table. But it's not really necessary. + } else if (k->has_modified_oops()) { + // Don't clear anything, this info is needed by the next young collection. + } else { + // No modified oops in the Klass. + return; + } + + // The klass has modified fields, need to scan the klass. + _cm_klass_closure.do_klass(k); + } +}; + // work_queue(i) is passed to the closure // Par_MarkRefsIntoAndScanClosure. The "i" parameter // also is passed to do_dirty_card_rescan_tasks() and to @@ -5110,7 +5090,7 @@ Par_MarkRefsIntoAndScanClosure par_mrias_cl(_collector, _collector->_span, _collector->ref_processor(), &(_collector->_markBitMap), - work_queue(worker_id), &(_collector->_revisitStack)); + work_queue(worker_id)); // Rescan young gen roots first since these are likely // coarsely partitioned and may, on that account, constitute @@ -5149,11 +5129,12 @@ gch->gen_process_strong_roots(_collector->_cmsGen->level(), false, // yg was scanned above false, // this is parallel code - true, // collecting perm gen + false, // not scavenging SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()), &par_mrias_cl, true, // walk all of code cache if (so & SO_CodeCache) - NULL); + NULL, + NULL); // The dirty klasses will be handled below assert(_collector->should_unload_classes() || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache), "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); @@ -5164,15 +5145,61 @@ worker_id, _timer.seconds()); } + // ---------- unhandled CLD scanning ---------- + if (worker_id == 0) { // Single threaded at the moment. + _timer.reset(); + _timer.start(); + + // Scan all new class loader data objects and new dependencies that were + // introduced during concurrent marking. + ResourceMark rm; + GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds(); + for (int i = 0; i < array->length(); i++) { + par_mrias_cl.do_class_loader_data(array->at(i)); + } + + // We don't need to keep track of new CLDs anymore. + ClassLoaderDataGraph::remember_new_clds(false); + + _timer.stop(); + if (PrintCMSStatistics != 0) { + gclog_or_tty->print_cr( + "Finished unhandled CLD scanning work in %dth thread: %3.3f sec", + worker_id, _timer.seconds()); + } + } + + // ---------- dirty klass scanning ---------- + if (worker_id == 0) { // Single threaded at the moment. + _timer.reset(); + _timer.start(); + + // Scan all classes that was dirtied during the concurrent marking phase. + RemarkKlassClosure remark_klass_closure(&par_mrias_cl); + ClassLoaderDataGraph::classes_do(&remark_klass_closure); + + _timer.stop(); + if (PrintCMSStatistics != 0) { + gclog_or_tty->print_cr( + "Finished dirty klass scanning work in %dth thread: %3.3f sec", + worker_id, _timer.seconds()); + } + } + + // We might have added oops to ClassLoaderData::_handles during the + // concurrent marking phase. These oops point to newly allocated objects + // that are guaranteed to be kept alive. Either by the direct allocation + // code, or when the young collector processes the strong roots. Hence, + // we don't have to revisit the _handles block during the remark phase. + // ---------- rescan dirty cards ------------ _timer.reset(); _timer.start(); // Do the rescan tasks for each of the two spaces - // (cms_space and perm_space) in turn. + // (cms_space) in turn. // "worker_id" is passed to select the task_queue for "worker_id" do_dirty_card_rescan_tasks(_cms_space, worker_id, &par_mrias_cl); - do_dirty_card_rescan_tasks(_perm_space, worker_id, &par_mrias_cl); _timer.stop(); if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr( @@ -5284,10 +5311,9 @@ // address that performance anomaly if at all possible. XXX MemRegion full_span = _collector->_span; CMSBitMap* bm = &(_collector->_markBitMap); // shared - CMSMarkStack* rs = &(_collector->_revisitStack); // shared MarkFromDirtyCardsClosure greyRescanClosure(_collector, full_span, // entire span of interest - sp, bm, work_q, rs, cl); + sp, bm, work_q, cl); SequentialSubTasksDone* pst = sp->conc_par_seq_tasks(); assert(pst->valid(), "Uninitialized use?"); @@ -5551,10 +5577,9 @@ workers->set_active_workers(n_workers); } CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace(); - CompactibleFreeListSpace* perm_space = _permGen->cmsSpace(); CMSParRemarkTask tsk(this, - cms_space, perm_space, + cms_space, n_workers, workers, task_queues()); // Set up for parallel process_strong_roots work. @@ -5580,7 +5605,6 @@ // of parallel tasks (per constituent space) that are dynamically // claimed by the parallel threads. cms_space->initialize_sequential_subtasks_for_rescan(n_workers); - perm_space->initialize_sequential_subtasks_for_rescan(n_workers); // It turns out that even when we're using 1 thread, doing the work in a // separate thread causes wide variance in run times. We can't help this @@ -5598,6 +5622,7 @@ GenCollectedHeap::StrongRootsScope srs(gch); tsk.work(0); } + gch->set_par_threads(0); // 0 ==> non-parallel. // restore, single-threaded for now, any preserved marks // as a result of work_q overflow @@ -5612,14 +5637,13 @@ ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false); MarkRefsIntoAndScanClosure - mrias_cl(_span, ref_processor(), &_markBitMap, &_modUnionTable, - &_markStack, &_revisitStack, this, + mrias_cl(_span, ref_processor(), &_markBitMap, NULL /* not precleaning */, + &_markStack, this, false /* should_yield */, false /* not precleaning */); MarkFromDirtyCardsClosure markFromDirtyCardsClosure(this, _span, NULL, // space is set further below - &_markBitMap, &_markStack, &_revisitStack, - &mrias_cl); + &_markBitMap, &_markStack, &mrias_cl); { TraceTime t("grey object rescan", PrintGCDetails, false, gclog_or_tty); // Iterate over the dirty cards, setting the corresponding bits in the @@ -5629,9 +5653,6 @@ _ct->ct_bs()->dirty_card_iterate( _cmsGen->used_region(), &modUnionClosure); - _ct->ct_bs()->dirty_card_iterate( - _permGen->used_region(), - &modUnionClosure); } // Having transferred these marks into the modUnionTable, we just need // to rescan the marked objects on the dirty cards in the modUnionTable. @@ -5654,21 +5675,6 @@ markFromDirtyCardsClosure.num_dirty_cards()); } } - { - // .. and then repeat for dirty cards in perm gen - markFromDirtyCardsClosure.set_space(_permGen->cmsSpace()); - MemRegion ur = _permGen->used_region(); - HeapWord* lb = ur.start(); - HeapWord* ub = (HeapWord*)round_to((intptr_t)ur.end(), alignment); - MemRegion perm_span(lb, ub); - _modUnionTable.dirty_range_iterate_clear(perm_span, - &markFromDirtyCardsClosure); - verify_work_stacks_empty(); - if (PrintCMSStatistics != 0) { - gclog_or_tty->print(" (re-scanned "SIZE_FORMAT" dirty cards in perm gen) ", - markFromDirtyCardsClosure.num_dirty_cards()); - } - } } if (VerifyDuringGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { @@ -5685,15 +5691,54 @@ gch->gen_process_strong_roots(_cmsGen->level(), true, // younger gens as roots false, // use the local StrongRootsScope - true, // collecting perm gen + false, // not scavenging SharedHeap::ScanningOption(roots_scanning_options()), &mrias_cl, true, // walk code active on stacks - NULL); + NULL, + NULL); // The dirty klasses will be handled below + assert(should_unload_classes() || (roots_scanning_options() & SharedHeap::SO_CodeCache), "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops"); } + + { + TraceTime t("visit unhandled CLDs", PrintGCDetails, false, gclog_or_tty); + + verify_work_stacks_empty(); + + // Scan all class loader data objects that might have been introduced + // during concurrent marking. + ResourceMark rm; + GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds(); + for (int i = 0; i < array->length(); i++) { + mrias_cl.do_class_loader_data(array->at(i)); + } + + // We don't need to keep track of new CLDs anymore. + ClassLoaderDataGraph::remember_new_clds(false); + + verify_work_stacks_empty(); + } + + { + TraceTime t("dirty klass scan", PrintGCDetails, false, gclog_or_tty); + + verify_work_stacks_empty(); + + RemarkKlassClosure remark_klass_closure(&mrias_cl); + ClassLoaderDataGraph::classes_do(&remark_klass_closure); + + verify_work_stacks_empty(); + } + + // We might have added oops to ClassLoaderData::_handles during the + // concurrent marking phase. These oops point to newly allocated objects + // that are guaranteed to be kept alive. Either by the direct allocation + // code, or when the young collector processes the strong roots. Hence, + // we don't have to revisit the _handles block during the remark phase. + verify_work_stacks_empty(); // Restore evacuated mark words, if any, used for overflow list links if (!CMSOverflowEarlyRestoration) { @@ -5749,11 +5794,9 @@ assert(_collector->_span.equals(_span), "Inconsistency in _span"); CMSParKeepAliveClosure par_keep_alive(_collector, _span, _mark_bit_map, - &_collector->_revisitStack, work_queue(worker_id)); CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span, _mark_bit_map, - &_collector->_revisitStack, work_queue(worker_id)); CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map); _task.work(worker_id, is_alive_closure, par_keep_alive, par_drain_stack); @@ -5782,13 +5825,11 @@ }; CMSParKeepAliveClosure::CMSParKeepAliveClosure(CMSCollector* collector, - MemRegion span, CMSBitMap* bit_map, CMSMarkStack* revisit_stack, - OopTaskQueue* work_queue): - Par_KlassRememberingOopClosure(collector, NULL, revisit_stack), + MemRegion span, CMSBitMap* bit_map, OopTaskQueue* work_queue): _span(span), _bit_map(bit_map), _work_queue(work_queue), - _mark_and_push(collector, span, bit_map, revisit_stack, work_queue), + _mark_and_push(collector, span, bit_map, work_queue), _low_water_mark(MIN2((uint)(work_queue->max_elems()/4), (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads))) { } @@ -5879,8 +5920,7 @@ verify_work_stacks_empty(); CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap, - &_markStack, &_revisitStack, - false /* !preclean */); + &_markStack, false /* !preclean */); CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this, _span, &_markBitMap, &_markStack, &cmsKeepAliveClosure, false /* !preclean */); @@ -5933,18 +5973,8 @@ verify_work_stacks_empty(); // Update subklass/sibling/implementor links in KlassKlass descendants - assert(!_revisitStack.isEmpty(), "revisit stack should not be empty"); - oop k; - while ((k = _revisitStack.pop()) != NULL) { - ((Klass*)(oopDesc*)k)->follow_weak_klass_links( - &_is_alive_closure, - &cmsKeepAliveClosure); - } - assert(!ClassUnloading || - (_markStack.isEmpty() && overflow_list_is_empty()), - "Should not have found new reachable objects"); - assert(_revisitStack.isEmpty(), "revisit stack should have been drained"); - cmsDrainMarkingStackClosure.do_void(); + Klass::clean_weak_klass_links(&_is_alive_closure); + // Nothing should have been pushed onto the working stacks. verify_work_stacks_empty(); } @@ -5955,7 +5985,9 @@ } } - if (should_unload_classes() || !JavaObjectsInPerm) { + // CMS doesn't use the StringTable as hard roots when class unloading is turned off. + // Need to check if we really scanned the StringTable. + if ((roots_scanning_options() & SharedHeap::SO_Strings) == 0) { TraceTime t("scrub string table", PrintGCDetails, false, gclog_or_tty); // Now clean up stale oops in StringTable StringTable::unlink(&_is_alive_closure); @@ -6019,53 +6051,25 @@ _inter_sweep_estimate.sample(_inter_sweep_timer.seconds()); size_policy()->avg_cms_free_at_sweep()->sample(_cmsGen->free()); - // PermGen verification support: If perm gen sweeping is disabled in - // this cycle, we preserve the perm gen object "deadness" information - // in the perm_gen_verify_bit_map. In order to do that we traverse - // all blocks in perm gen and mark all dead objects. - if (verifying() && !should_unload_classes()) { - assert(perm_gen_verify_bit_map()->sizeInBits() != 0, - "Should have already been allocated"); - MarkDeadObjectsClosure mdo(this, _permGen->cmsSpace(), - markBitMap(), perm_gen_verify_bit_map()); - if (asynch) { - CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(), - bitMapLock()); - _permGen->cmsSpace()->blk_iterate(&mdo); - } else { - // In the case of synchronous sweep, we already have - // the requisite locks/tokens. - _permGen->cmsSpace()->blk_iterate(&mdo); - } - } - assert(!_intra_sweep_timer.is_active(), "Should not be active"); _intra_sweep_timer.reset(); _intra_sweep_timer.start(); if (asynch) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails); - // First sweep the old gen then the perm gen + // First sweep the old gen { CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(), bitMapLock()); sweepWork(_cmsGen, asynch); } - // Now repeat for perm gen - if (should_unload_classes()) { - CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(), - bitMapLock()); - sweepWork(_permGen, asynch); - } - // Update Universe::_heap_*_at_gc figures. // We need all the free list locks to make the abstract state // transition from Sweeping to Resetting. See detailed note // further below. { - CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(), - _permGen->freelistLock()); + CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock()); // Update heap occupancy information which is used as // input to soft ref clearing policy at the next gc. Universe::update_heap_info_at_gc(); @@ -6074,10 +6078,6 @@ } else { // already have needed locks sweepWork(_cmsGen, asynch); - - if (should_unload_classes()) { - sweepWork(_permGen, asynch); - } // Update heap occupancy information which is used as // input to soft ref clearing policy at the next gc. Universe::update_heap_info_at_gc(); @@ -6412,7 +6412,7 @@ HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const { size_t sz = 0; oop p = (oop)addr; - if (p->klass_or_null() != NULL && p->is_parsable()) { + if (p->klass_or_null() != NULL) { sz = CompactibleFreeListSpace::adjustObjectSize(p->size()); } else { sz = block_size_using_printezis_bits(addr); @@ -6601,7 +6601,7 @@ // This closure is used to mark refs into the CMS generation in // the CMS bit map. Called at the first checkpoint. This closure // assumes that we do not need to re-mark dirty cards; if the CMS -// generation on which this is used is not an oldest (modulo perm gen) +// generation on which this is used is not an oldest // generation then this will lose younger_gen cards! MarkRefsIntoClosure::MarkRefsIntoClosure( @@ -6663,7 +6663,6 @@ CMSBitMap* bit_map, CMSBitMap* mod_union_table, CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, CMSCollector* collector, bool should_yield, bool concurrent_precleaning): @@ -6672,7 +6671,7 @@ _bit_map(bit_map), _mark_stack(mark_stack), _pushAndMarkClosure(collector, span, rp, bit_map, mod_union_table, - mark_stack, revisit_stack, concurrent_precleaning), + mark_stack, concurrent_precleaning), _yield(should_yield), _concurrent_precleaning(concurrent_precleaning), _freelistLock(NULL) @@ -6707,7 +6706,6 @@ do { oop new_oop = _mark_stack->pop(); assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop"); - assert(new_oop->is_parsable(), "Found unparsable oop"); assert(_bit_map->isMarked((HeapWord*)new_oop), "only grey objects on this stack"); // iterate over the oops in this oop, marking and pushing @@ -6747,7 +6745,6 @@ assert_lock_strong(_freelistLock); assert_lock_strong(_bit_map->lock()); // relinquish the free_list_lock and bitMaplock() - DEBUG_ONLY(RememberKlassesChecker mux(false);) _bit_map->lock()->unlock(); _freelistLock->unlock(); ConcurrentMarkSweepThread::desynchronize(true); @@ -6781,14 +6778,13 @@ /////////////////////////////////////////////////////////// Par_MarkRefsIntoAndScanClosure::Par_MarkRefsIntoAndScanClosure( CMSCollector* collector, MemRegion span, ReferenceProcessor* rp, - CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack* revisit_stack): + CMSBitMap* bit_map, OopTaskQueue* work_queue): _span(span), _bit_map(bit_map), _work_queue(work_queue), _low_water_mark(MIN2((uint)(work_queue->max_elems()/4), (uint)(CMSWorkQueueDrainThreshold * ParallelGCThreads))), - _par_pushAndMarkClosure(collector, span, rp, bit_map, work_queue, - revisit_stack) + _par_pushAndMarkClosure(collector, span, rp, bit_map, work_queue) { _ref_processor = rp; assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL"); @@ -6849,16 +6845,6 @@ if (_bitMap->isMarked(addr)) { // it's marked; is it potentially uninitialized? if (p->klass_or_null() != NULL) { - // If is_conc_safe is false, the object may be undergoing - // change by the VM outside a safepoint. Don't try to - // scan it, but rather leave it for the remark phase. - if (CMSPermGenPrecleaningEnabled && - (!p->is_conc_safe() || !p->is_parsable())) { - // Signal precleaning to redirty the card since - // the klass pointer is already installed. - assert(size == 0, "Initial value"); - } else { - assert(p->is_parsable(), "must be parsable."); // an initialized object; ignore mark word in verification below // since we are running concurrent with mutators assert(p->is_oop(true), "should be an oop"); @@ -6886,7 +6872,6 @@ "inconsistent Printezis mark"); } #endif // DEBUG - } } else { // an unitialized object assert(_bitMap->isMarked(addr+1), "missing Printezis mark?"); @@ -6900,7 +6885,7 @@ } } else { // Either a not yet marked object or an uninitialized object - if (p->klass_or_null() == NULL || !p->is_parsable()) { + if (p->klass_or_null() == NULL) { // An uninitialized object, skip to the next card, since // we may not be able to read its P-bits yet. assert(size == 0, "Initial value"); @@ -6920,7 +6905,6 @@ "CMS thread should hold CMS token"); assert_lock_strong(_freelistLock); assert_lock_strong(_bitMap->lock()); - DEBUG_ONLY(RememberKlassesChecker mux(false);) // relinquish the free_list_lock and bitMaplock() _bitMap->lock()->unlock(); _freelistLock->unlock(); @@ -6959,7 +6943,6 @@ DEBUG_ONLY(_collector->verify_work_stacks_empty();) assert(!_span.contains(addr), "we are scanning the survivor spaces"); assert(p->klass_or_null() != NULL, "object should be initializd"); - assert(p->is_parsable(), "must be parsable."); // an initialized object; ignore mark word in verification below // since we are running concurrent with mutators assert(p->is_oop(true), "should be an oop"); @@ -6977,7 +6960,6 @@ while (!_mark_stack->isEmpty()) { oop new_oop = _mark_stack->pop(); assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop"); - assert(new_oop->is_parsable(), "Found unparsable oop"); assert(_bit_map->isMarked((HeapWord*)new_oop), "only grey objects on this stack"); // iterate over the oops in this oop, marking and pushing @@ -6997,7 +6979,6 @@ assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "CMS thread should hold CMS token"); assert_lock_strong(_bit_map->lock()); - DEBUG_ONLY(RememberKlassesChecker smx(false);) // Relinquish the bit map lock _bit_map->lock()->unlock(); ConcurrentMarkSweepThread::desynchronize(true); @@ -7073,14 +7054,12 @@ MarkFromRootsClosure::MarkFromRootsClosure(CMSCollector* collector, MemRegion span, CMSBitMap* bitMap, CMSMarkStack* markStack, - CMSMarkStack* revisitStack, bool should_yield, bool verifying): _collector(collector), _span(span), _bitMap(bitMap), _mut(&collector->_modUnionTable), _markStack(markStack), - _revisitStack(revisitStack), _yield(should_yield), _skipBits(0) { @@ -7117,7 +7096,7 @@ assert(_skipBits == 0, "tautology"); _skipBits = 2; // skip next two marked bits ("Printezis-marks") oop p = oop(addr); - if (p->klass_or_null() == NULL || !p->is_parsable()) { + if (p->klass_or_null() == NULL) { DEBUG_ONLY(if (!_verifying) {) // We re-dirty the cards on which this object lies and increase // the _threshold so that we'll come back to scan this object @@ -7160,7 +7139,6 @@ assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "CMS thread should hold CMS token"); assert_lock_strong(_bitMap->lock()); - DEBUG_ONLY(RememberKlassesChecker mux(false);) _bitMap->lock()->unlock(); ConcurrentMarkSweepThread::desynchronize(true); ConcurrentMarkSweepThread::acknowledge_yield_request(); @@ -7227,10 +7205,6 @@ MemRegion mr(old_threshold, _threshold); assert(!mr.is_empty(), "Control point invariant"); assert(_span.contains(mr), "Should clear within span"); - // XXX When _finger crosses from old gen into perm gen - // we may be doing unnecessary cleaning; do better in the - // future by detecting that condition and clearing fewer - // MUT/CT entries. _mut->clear_range(mr); } DEBUG_ONLY(}) @@ -7238,7 +7212,6 @@ // the stack below. PushOrMarkClosure pushOrMarkClosure(_collector, _span, _bitMap, _markStack, - _revisitStack, _finger, this); bool res = _markStack->push(obj); assert(res, "Empty non-zero size stack should have space for single push"); @@ -7259,7 +7232,6 @@ CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack* overflow_stack, - CMSMarkStack* revisit_stack, bool should_yield): _collector(collector), _whole_span(collector->_span), @@ -7268,7 +7240,6 @@ _mut(&collector->_modUnionTable), _work_queue(work_queue), _overflow_stack(overflow_stack), - _revisit_stack(revisit_stack), _yield(should_yield), _skip_bits(0), _task(task) @@ -7296,7 +7267,7 @@ assert(_skip_bits == 0, "tautology"); _skip_bits = 2; // skip next two marked bits ("Printezis-marks") oop p = oop(addr); - if (p->klass_or_null() == NULL || !p->is_parsable()) { + if (p->klass_or_null() == NULL) { // in the case of Clean-on-Enter optimization, redirty card // and avoid clearing card by increasing the threshold. return true; @@ -7350,10 +7321,6 @@ MemRegion mr(old_threshold, _threshold); assert(!mr.is_empty(), "Control point invariant"); assert(_span.contains(mr), "Should clear within span"); // _whole_span ?? - // XXX When _finger crosses from old gen into perm gen - // we may be doing unnecessary cleaning; do better in the - // future by detecting that condition and clearing fewer - // MUT/CT entries. _mut->clear_range(mr); } @@ -7364,7 +7331,6 @@ _span, _bit_map, _work_queue, _overflow_stack, - _revisit_stack, _finger, gfa, this); bool res = _work_queue->push(obj); // overflow could occur here @@ -7461,7 +7427,7 @@ CMSCollector* collector, MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm, CMSMarkStack* mark_stack): - OopClosure(collector->ref_processor()), + CMSOopClosure(collector->ref_processor()), _collector(collector), _span(span), _verification_bm(verification_bm), @@ -7513,9 +7479,9 @@ PushOrMarkClosure::PushOrMarkClosure(CMSCollector* collector, MemRegion span, CMSBitMap* bitMap, CMSMarkStack* markStack, - CMSMarkStack* revisitStack, HeapWord* finger, MarkFromRootsClosure* parent) : - KlassRememberingOopClosure(collector, collector->ref_processor(), revisitStack), + CMSOopClosure(collector->ref_processor()), + _collector(collector), _span(span), _bitMap(bitMap), _markStack(markStack), @@ -7528,13 +7494,11 @@ CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack* overflow_stack, - CMSMarkStack* revisit_stack, HeapWord* finger, HeapWord** global_finger_addr, Par_MarkFromRootsClosure* parent) : - Par_KlassRememberingOopClosure(collector, - collector->ref_processor(), - revisit_stack), + CMSOopClosure(collector->ref_processor()), + _collector(collector), _whole_span(collector->_span), _span(span), _bit_map(bit_map), @@ -7582,6 +7546,11 @@ _overflow_stack->expand(); // expand the stack if possible } +void CMKlassClosure::do_klass(Klass* k) { + assert(_oop_closure != NULL, "Not initialized?"); + k->oops_do(_oop_closure); +} + void PushOrMarkClosure::do_oop(oop obj) { // Ignore mark word because we are running concurrent with mutators. assert(obj->is_oop_or_null(true), "expected an oop or NULL"); @@ -7672,23 +7641,15 @@ void Par_PushOrMarkClosure::do_oop(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } void Par_PushOrMarkClosure::do_oop(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } -KlassRememberingOopClosure::KlassRememberingOopClosure(CMSCollector* collector, - ReferenceProcessor* rp, - CMSMarkStack* revisit_stack) : - OopClosure(rp), - _collector(collector), - _revisit_stack(revisit_stack), - _should_remember_klasses(collector->should_unload_classes()) {} - PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector, MemRegion span, ReferenceProcessor* rp, CMSBitMap* bit_map, CMSBitMap* mod_union_table, CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, bool concurrent_precleaning): - KlassRememberingOopClosure(collector, rp, revisit_stack), + CMSOopClosure(rp), + _collector(collector), _span(span), _bit_map(bit_map), _mod_union_table(mod_union_table), @@ -7759,9 +7720,9 @@ MemRegion span, ReferenceProcessor* rp, CMSBitMap* bit_map, - OopTaskQueue* work_queue, - CMSMarkStack* revisit_stack): - Par_KlassRememberingOopClosure(collector, rp, revisit_stack), + OopTaskQueue* work_queue): + CMSOopClosure(rp), + _collector(collector), _span(span), _bit_map(bit_map), _work_queue(work_queue) @@ -7817,16 +7778,7 @@ void Par_PushAndMarkClosure::do_oop(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } void Par_PushAndMarkClosure::do_oop(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } -void PushAndMarkClosure::remember_mdo(DataLayout* v) { - // TBD -} - -void Par_PushAndMarkClosure::remember_mdo(DataLayout* v) { - // TBD -} - void CMSPrecleanRefsYieldClosure::do_yield_work() { - DEBUG_ONLY(RememberKlassesChecker mux(false);) Mutex* bml = _collector->bitMapLock(); assert_lock_strong(bml); assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), @@ -8307,15 +8259,9 @@ "alignment problem"); #ifdef DEBUG - if (oop(addr)->klass_or_null() != NULL && - ( !_collector->should_unload_classes() - || (oop(addr)->is_parsable()) && - oop(addr)->is_conc_safe())) { + if (oop(addr)->klass_or_null() != NULL) { // Ignore mark word because we are running concurrent with mutators assert(oop(addr)->is_oop(true), "live block should be an oop"); - // is_conc_safe is checked before performing this assertion - // because an object that is not is_conc_safe may yet have - // the return from size() correct. assert(size == CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()), "P-mark and computed size do not agree"); @@ -8324,17 +8270,8 @@ } else { // This should be an initialized object that's alive. - assert(oop(addr)->klass_or_null() != NULL && - (!_collector->should_unload_classes() - || oop(addr)->is_parsable()), + assert(oop(addr)->klass_or_null() != NULL, "Should be an initialized object"); - // Note that there are objects used during class redefinition, - // e.g. merge_cp in VM_RedefineClasses::merge_cp_and_rewrite(), - // which are discarded with their is_conc_safe state still - // false. These object may be floating garbage so may be - // seen here. If they are floating garbage their size - // should be attainable from their klass. Do not that - // is_conc_safe() is true for oop(addr). // Ignore mark word because we are running concurrent with mutators assert(oop(addr)->is_oop(true), "live block should be an oop"); // Verify that the bit map has no bits marked between @@ -8576,11 +8513,12 @@ (!_span.contains(addr) || _bit_map->isMarked(addr)); } + CMSKeepAliveClosure::CMSKeepAliveClosure( CMSCollector* collector, MemRegion span, CMSBitMap* bit_map, CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, bool cpc): - KlassRememberingOopClosure(collector, NULL, revisit_stack), + bool cpc): + _collector(collector), _span(span), _bit_map(bit_map), _mark_stack(mark_stack), @@ -8675,9 +8613,8 @@ CMSInnerParMarkAndPushClosure::CMSInnerParMarkAndPushClosure( CMSCollector* collector, MemRegion span, CMSBitMap* bit_map, - CMSMarkStack* revisit_stack, OopTaskQueue* work_queue): - Par_KlassRememberingOopClosure(collector, NULL, revisit_stack), + _collector(collector), _span(span), _bit_map(bit_map), _work_queue(work_queue) { }