< prev index next >
src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp
Print this page
*** 40,49 ****
--- 40,50 ----
#include "gc/shared/cardGeneration.inline.hpp"
#include "gc/shared/cardTableRS.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/collectorCounters.hpp"
#include "gc/shared/collectorPolicy.hpp"
+ #include "gc/shared/gcId.hpp"
#include "gc/shared/gcLocker.inline.hpp"
#include "gc/shared/gcPolicyCounters.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/gcTraceTime.hpp"
*** 1591,1601 ****
gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
! GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL, gc_tracer->gc_id());
// Temporarily widen the span of the weak reference processing to
// the entire heap.
MemRegion new_span(GenCollectedHeap::heap()->reserved_region());
ReferenceProcessorSpanMutator rp_mut_span(ref_processor(), new_span);
--- 1592,1602 ----
gc_timer->register_gc_start();
SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
! GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL);
// Temporarily widen the span of the weak reference processing to
// the entire heap.
MemRegion new_span(GenCollectedHeap::heap()->reserved_region());
ReferenceProcessorSpanMutator rp_mut_span(ref_processor(), new_span);
*** 2823,2842 ****
// phases.
class CMSPhaseAccounting: public StackObj {
public:
CMSPhaseAccounting(CMSCollector *collector,
const char *phase,
- const GCId gc_id,
bool print_cr = true);
~CMSPhaseAccounting();
private:
CMSCollector *_collector;
const char *_phase;
elapsedTimer _wallclock;
bool _print_cr;
- const GCId _gc_id;
public:
// Not MT-safe; so do not pass around these StackObj's
// where they may be accessed by other threads.
jlong wallclock_millis() {
--- 2824,2841 ----
*** 2848,2866 ****
}
};
CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector,
const char *phase,
- const GCId gc_id,
bool print_cr) :
! _collector(collector), _phase(phase), _print_cr(print_cr), _gc_id(gc_id) {
if (PrintCMSStatistics != 0) {
_collector->resetYields();
}
if (PrintGCDetails) {
! gclog_or_tty->gclog_stamp(_gc_id);
gclog_or_tty->print_cr("[%s-concurrent-%s-start]",
_collector->cmsGen()->short_name(), _phase);
}
_collector->resetTimer();
_wallclock.start();
--- 2847,2864 ----
}
};
CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector,
const char *phase,
bool print_cr) :
! _collector(collector), _phase(phase), _print_cr(print_cr) {
if (PrintCMSStatistics != 0) {
_collector->resetYields();
}
if (PrintGCDetails) {
! gclog_or_tty->gclog_stamp();
gclog_or_tty->print_cr("[%s-concurrent-%s-start]",
_collector->cmsGen()->short_name(), _phase);
}
_collector->resetTimer();
_wallclock.start();
*** 2870,2880 ****
CMSPhaseAccounting::~CMSPhaseAccounting() {
assert(_wallclock.is_active(), "Wall clock should not have stopped");
_collector->stopTimer();
_wallclock.stop();
if (PrintGCDetails) {
! gclog_or_tty->gclog_stamp(_gc_id);
gclog_or_tty->print("[%s-concurrent-%s: %3.3f/%3.3f secs]",
_collector->cmsGen()->short_name(),
_phase, _collector->timerValue(), _wallclock.seconds());
if (_print_cr) {
gclog_or_tty->cr();
--- 2868,2878 ----
CMSPhaseAccounting::~CMSPhaseAccounting() {
assert(_wallclock.is_active(), "Wall clock should not have stopped");
_collector->stopTimer();
_wallclock.stop();
if (PrintGCDetails) {
! gclog_or_tty->gclog_stamp();
gclog_or_tty->print("[%s-concurrent-%s: %3.3f/%3.3f secs]",
_collector->cmsGen()->short_name(),
_phase, _collector->timerValue(), _wallclock.seconds());
if (_print_cr) {
gclog_or_tty->cr();
*** 2949,2959 ****
// Setup the verification and class unloading state for this
// CMS collection cycle.
setup_cms_unloading_and_verification_state();
NOT_PRODUCT(GCTraceTime t("\ncheckpointRootsInitialWork",
! PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());)
// Reset all the PLAB chunk arrays if necessary.
if (_survivor_plab_array != NULL && !CMSPLABRecordAlways) {
reset_survivor_plab_arrays();
}
--- 2947,2957 ----
// Setup the verification and class unloading state for this
// CMS collection cycle.
setup_cms_unloading_and_verification_state();
NOT_PRODUCT(GCTraceTime t("\ncheckpointRootsInitialWork",
! PrintGCDetails && Verbose, true, _gc_timer_cm);)
// Reset all the PLAB chunk arrays if necessary.
if (_survivor_plab_array != NULL && !CMSPLABRecordAlways) {
reset_survivor_plab_arrays();
}
*** 3052,3062 ****
// refs in this generation concurrent (but interleaved) with
// weak ref discovery by the young generation collector.
CMSTokenSyncWithLocks ts(true, bitMapLock());
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "mark", _gc_tracer_cm->gc_id(), !PrintGCDetails);
bool res = markFromRootsWork();
if (res) {
_collectorState = Precleaning;
} else { // We failed and a foreground collection wants to take over
assert(_foregroundGCIsActive, "internal state inconsistency");
--- 3050,3060 ----
// refs in this generation concurrent (but interleaved) with
// weak ref discovery by the young generation collector.
CMSTokenSyncWithLocks ts(true, bitMapLock());
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "mark", !PrintGCDetails);
bool res = markFromRootsWork();
if (res) {
_collectorState = Precleaning;
} else { // We failed and a foreground collection wants to take over
assert(_foregroundGCIsActive, "internal state inconsistency");
*** 3749,3759 ****
_start_sampling = true;
} else {
_start_sampling = false;
}
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails);
preclean_work(CMSPrecleanRefLists1, CMSPrecleanSurvivors1);
}
CMSTokenSync x(true); // is cms thread
if (CMSPrecleaningEnabled) {
sample_eden();
--- 3747,3757 ----
_start_sampling = true;
} else {
_start_sampling = false;
}
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "preclean", !PrintGCDetails);
preclean_work(CMSPrecleanRefLists1, CMSPrecleanSurvivors1);
}
CMSTokenSync x(true); // is cms thread
if (CMSPrecleaningEnabled) {
sample_eden();
*** 3778,3788 ****
// schedule the pause as described above. By choosing
// CMSScheduleRemarkEdenSizeThreshold >= max eden size
// we will never do an actual abortable preclean cycle.
if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) {
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "abortable-preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails);
// We need more smarts in the abortable preclean
// loop below to deal with cases where allocation
// in young gen is very very slow, and our precleaning
// is running a losing race against a horde of
// mutators intent on flooding us with CMS updates
--- 3776,3786 ----
// schedule the pause as described above. By choosing
// CMSScheduleRemarkEdenSizeThreshold >= max eden size
// we will never do an actual abortable preclean cycle.
if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) {
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails);
// We need more smarts in the abortable preclean
// loop below to deal with cases where allocation
// in young gen is very very slow, and our precleaning
// is running a losing race against a horde of
// mutators intent on flooding us with CMS updates
*** 3923,3933 ****
// tweaking for better performance and some restructuring
// for cleaner interfaces.
GCTimer *gc_timer = NULL; // Currently not tracing concurrent phases
rp->preclean_discovered_references(
rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl,
! gc_timer, _gc_tracer_cm->gc_id());
}
if (clean_survivor) { // preclean the active survivor space(s)
PushAndMarkClosure pam_cl(this, _span, ref_processor(),
&_markBitMap, &_modUnionTable,
--- 3921,3931 ----
// tweaking for better performance and some restructuring
// for cleaner interfaces.
GCTimer *gc_timer = NULL; // Currently not tracing concurrent phases
rp->preclean_discovered_references(
rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl,
! gc_timer);
}
if (clean_survivor) { // preclean the active survivor space(s)
PushAndMarkClosure pam_cl(this, _span, ref_processor(),
&_markBitMap, &_modUnionTable,
*** 4259,4269 ****
GenCollectedHeap* gch = GenCollectedHeap::heap();
// Temporarily set flag to false, GCH->do_collection will
// expect it to be false and set to true
FlagSetting fl(gch->_is_gc_active, false);
NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark",
! PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());)
gch->do_collection(true, // full (i.e. force, see below)
false, // !clear_all_soft_refs
0, // size
false, // is_tlab
GenCollectedHeap::YoungGen // type
--- 4257,4267 ----
GenCollectedHeap* gch = GenCollectedHeap::heap();
// Temporarily set flag to false, GCH->do_collection will
// expect it to be false and set to true
FlagSetting fl(gch->_is_gc_active, false);
NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark",
! PrintGCDetails && Verbose, true, _gc_timer_cm);)
gch->do_collection(true, // full (i.e. force, see below)
false, // !clear_all_soft_refs
0, // size
false, // is_tlab
GenCollectedHeap::YoungGen // type
*** 4277,4287 ****
verify_work_stacks_empty();
verify_overflow_empty();
}
void CMSCollector::checkpointRootsFinalWork() {
! NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());)
assert(haveFreelistLocks(), "must have free list locks");
assert_lock_strong(bitMapLock());
ResourceMark rm;
--- 4275,4285 ----
verify_work_stacks_empty();
verify_overflow_empty();
}
void CMSCollector::checkpointRootsFinalWork() {
! NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm);)
assert(haveFreelistLocks(), "must have free list locks");
assert_lock_strong(bitMapLock());
ResourceMark rm;
*** 4327,4349 ****
// are detected via the mod union table which is the set of all cards
// dirtied since the first checkpoint in this GC cycle and prior to
// the most recent young generation GC, minus those cleaned up by the
// concurrent precleaning.
if (CMSParallelRemarkEnabled) {
! GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
do_remark_parallel();
} else {
! GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false,
! _gc_timer_cm, _gc_tracer_cm->gc_id());
do_remark_non_parallel();
}
}
verify_work_stacks_empty();
verify_overflow_empty();
{
! NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());)
refProcessingWork();
}
verify_work_stacks_empty();
verify_overflow_empty();
--- 4325,4346 ----
// are detected via the mod union table which is the set of all cards
// dirtied since the first checkpoint in this GC cycle and prior to
// the most recent young generation GC, minus those cleaned up by the
// concurrent precleaning.
if (CMSParallelRemarkEnabled) {
! GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm);
do_remark_parallel();
} else {
! GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false, _gc_timer_cm);
do_remark_non_parallel();
}
}
verify_work_stacks_empty();
verify_overflow_empty();
{
! NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm);)
refProcessingWork();
}
verify_work_stacks_empty();
verify_overflow_empty();
*** 5114,5124 ****
MarkFromDirtyCardsClosure
markFromDirtyCardsClosure(this, _span,
NULL, // space is set further below
&_markBitMap, &_markStack, &mrias_cl);
{
! GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
// Iterate over the dirty cards, setting the corresponding bits in the
// mod union table.
{
ModUnionClosure modUnionClosure(&_modUnionTable);
_ct->ct_bs()->dirty_card_iterate(
--- 5111,5121 ----
MarkFromDirtyCardsClosure
markFromDirtyCardsClosure(this, _span,
NULL, // space is set further below
&_markBitMap, &_markStack, &mrias_cl);
{
! GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm);
// Iterate over the dirty cards, setting the corresponding bits in the
// mod union table.
{
ModUnionClosure modUnionClosure(&_modUnionTable);
_ct->ct_bs()->dirty_card_iterate(
*** 5151,5161 ****
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
Universe::verify();
}
{
! GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
StrongRootsScope srs(1);
--- 5148,5158 ----
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
Universe::verify();
}
{
! GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm);
verify_work_stacks_empty();
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
StrongRootsScope srs(1);
*** 5173,5183 ****
|| (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
}
{
! GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
// Scan all class loader data objects that might have been introduced
// during concurrent marking.
--- 5170,5180 ----
|| (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
}
{
! GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm);
verify_work_stacks_empty();
// Scan all class loader data objects that might have been introduced
// during concurrent marking.
*** 5192,5202 ****
verify_work_stacks_empty();
}
{
! GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
RemarkKlassClosure remark_klass_closure(&mrias_cl);
ClassLoaderDataGraph::classes_do(&remark_klass_closure);
--- 5189,5199 ----
verify_work_stacks_empty();
}
{
! GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm);
verify_work_stacks_empty();
RemarkKlassClosure remark_klass_closure(&mrias_cl);
ClassLoaderDataGraph::classes_do(&remark_klass_closure);
*** 5401,5411 ****
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure, false /* !preclean */);
{
! GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
ReferenceProcessorStats stats;
if (rp->processing_is_mt()) {
// Set the degree of MT here. If the discovery is done MT, there
// may have been a different number of threads doing the discovery
--- 5398,5408 ----
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure, false /* !preclean */);
{
! GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm);
ReferenceProcessorStats stats;
if (rp->processing_is_mt()) {
// Set the degree of MT here. If the discovery is done MT, there
// may have been a different number of threads doing the discovery
*** 5426,5455 ****
CMSRefProcTaskExecutor task_executor(*this);
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor,
! _gc_timer_cm,
! _gc_tracer_cm->gc_id());
} else {
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL,
! _gc_timer_cm,
! _gc_tracer_cm->gc_id());
}
_gc_tracer_cm->report_gc_reference_stats(stats);
}
// This is the point where the entire marking should have completed.
verify_work_stacks_empty();
if (should_unload_classes()) {
{
! GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
// Unload nmethods.
--- 5423,5450 ----
CMSRefProcTaskExecutor task_executor(*this);
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor,
! _gc_timer_cm);
} else {
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL,
! _gc_timer_cm);
}
_gc_tracer_cm->report_gc_reference_stats(stats);
}
// This is the point where the entire marking should have completed.
verify_work_stacks_empty();
if (should_unload_classes()) {
{
! GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm);
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
// Unload nmethods.
*** 5458,5474 ****
// Prune dead klasses from subklass/sibling/implementor lists.
Klass::clean_weak_klass_links(&_is_alive_closure);
}
{
! GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
// Clean up unreferenced symbols in symbol table.
SymbolTable::unlink();
}
{
! GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
// Delete entries for dead interned strings.
StringTable::unlink(&_is_alive_closure);
}
}
--- 5453,5469 ----
// Prune dead klasses from subklass/sibling/implementor lists.
Klass::clean_weak_klass_links(&_is_alive_closure);
}
{
! GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm);
// Clean up unreferenced symbols in symbol table.
SymbolTable::unlink();
}
{
! GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm);
// Delete entries for dead interned strings.
StringTable::unlink(&_is_alive_closure);
}
}
*** 5532,5542 ****
assert(!_intra_sweep_timer.is_active(), "Should not be active");
_intra_sweep_timer.reset();
_intra_sweep_timer.start();
{
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "sweep", _gc_tracer_cm->gc_id(), !PrintGCDetails);
// First sweep the old gen
{
CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(),
bitMapLock());
sweepWork(_cmsGen);
--- 5527,5537 ----
assert(!_intra_sweep_timer.is_active(), "Should not be active");
_intra_sweep_timer.reset();
_intra_sweep_timer.start();
{
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails);
// First sweep the old gen
{
CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(),
bitMapLock());
sweepWork(_cmsGen);
*** 5717,5727 ****
}
// Clear the mark bitmap (no grey objects to start with)
// for the next cycle.
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting cmspa(this, "reset", _gc_tracer_cm->gc_id(), !PrintGCDetails);
HeapWord* curAddr = _markBitMap.startWord();
while (curAddr < _markBitMap.endWord()) {
size_t remaining = pointer_delta(_markBitMap.endWord(), curAddr);
MemRegion chunk(curAddr, MIN2(CMSBitMapYieldQuantum, remaining));
--- 5712,5722 ----
}
// Clear the mark bitmap (no grey objects to start with)
// for the next cycle.
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! CMSPhaseAccounting cmspa(this, "reset", !PrintGCDetails);
HeapWord* curAddr = _markBitMap.startWord();
while (curAddr < _markBitMap.endWord()) {
size_t remaining = pointer_delta(_markBitMap.endWord(), curAddr);
MemRegion chunk(curAddr, MIN2(CMSBitMapYieldQuantum, remaining));
*** 5769,5779 ****
register_gc_end();
}
void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer_cm->gc_id());
TraceCollectorStats tcs(counters());
switch (op) {
case CMS_op_checkpointRootsInitial: {
SvcGCMarker sgcm(SvcGCMarker::OTHER);
--- 5764,5774 ----
register_gc_end();
}
void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
! GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL);
TraceCollectorStats tcs(counters());
switch (op) {
case CMS_op_checkpointRootsInitial: {
SvcGCMarker sgcm(SvcGCMarker::OTHER);
< prev index next >