--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Jun 07 09:33:01 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Mon Jun 10 11:30:51 2013 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, 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
@@ -29,6 +29,11 @@
#include "gc_implementation/shared/adaptiveSizePolicy.hpp"
#include "gc_implementation/shared/ageTable.hpp"
#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/gcHeapSummary.hpp"
+#include "gc_implementation/shared/gcTimer.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
+#include "gc_implementation/shared/gcTraceTime.hpp"
+#include "gc_implementation/shared/copyFailedInfo.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "memory/defNewGeneration.inline.hpp"
#include "memory/genCollectedHeap.hpp"
@@ -75,7 +80,6 @@
work_queue_set_, &term_),
_is_alive_closure(gen_), _scan_weak_ref_closure(gen_, this),
_keep_alive_closure(&_scan_weak_ref_closure),
- _promotion_failure_size(0),
_strong_roots_time(0.0), _term_time(0.0)
{
#if TASKQUEUE_STATS
@@ -279,13 +283,10 @@
}
}
-void ParScanThreadState::print_and_clear_promotion_failure_size() {
- if (_promotion_failure_size != 0) {
- if (PrintPromotionFailure) {
- gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
- _thread_num, _promotion_failure_size);
- }
- _promotion_failure_size = 0;
+void ParScanThreadState::print_promotion_failure_size() {
+ if (_promotion_failed_info.has_failed() && PrintPromotionFailure) {
+ gclog_or_tty->print(" (%d: promotion failure size = " SIZE_FORMAT ") ",
+ _thread_num, _promotion_failed_info.first_size());
}
}
@@ -305,6 +306,7 @@
inline ParScanThreadState& thread_state(int i);
+ void trace_promotion_failed(YoungGCTracer& gc_tracer);
void reset(int active_workers, bool promotion_failed);
void flush();
@@ -353,13 +355,21 @@
return ((ParScanThreadState*)_data)[i];
}
+void ParScanThreadStateSet::trace_promotion_failed(YoungGCTracer& gc_tracer) {
+ for (int i = 0; i < length(); ++i) {
+ if (thread_state(i).promotion_failed()) {
+ gc_tracer.report_promotion_failed(thread_state(i).promotion_failed_info());
+ thread_state(i).promotion_failed_info().reset();
+ }
+ }
+}
void ParScanThreadStateSet::reset(int active_threads, bool promotion_failed)
{
_term.reset_for_reuse(active_threads);
if (promotion_failed) {
for (int i = 0; i < length(); ++i) {
- thread_state(i).print_and_clear_promotion_failure_size();
+ thread_state(i).print_promotion_failure_size();
}
}
}
@@ -583,14 +593,6 @@
gch->set_n_termination(active_workers);
}
-// The "i" passed to this method is the part of the work for
-// this thread. It is not the worker ID. The "i" is derived
-// from _started_workers which is incremented in internal_note_start()
-// called in GangWorker loop() and which is called under the
-// which is called under the protection of the gang monitor and is
-// called after a task is started. So "i" is based on
-// first-come-first-served.
-
void ParNewGenTask::work(uint worker_id) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
// Since this is being done in a separate thread, need new resource
@@ -876,16 +878,45 @@
}
+// A Generation that does parallel young-gen collection.
+
bool ParNewGeneration::_avoid_promotion_undo = false;
-// A Generation that does parallel young-gen collection.
+void ParNewGeneration::handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set, ParNewTracer& gc_tracer) {
+ assert(_promo_failure_scan_stack.is_empty(), "post condition");
+ _promo_failure_scan_stack.clear(true); // Clear cached segments.
+
+ remove_forwarding_pointers();
+ if (PrintGCDetails) {
+ gclog_or_tty->print(" (promotion failed)");
+ }
+ // All the spaces are in play for mark-sweep.
+ swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
+ from()->set_next_compaction_space(to());
+ gch->set_incremental_collection_failed();
+ // Inform the next generation that a promotion failure occurred.
+ _next_gen->promotion_failure_occurred();
+
+ // Trace promotion failure in the parallel GC threads
+ thread_state_set.trace_promotion_failed(gc_tracer);
+ // Single threaded code may have reported promotion failure to the global state
+ if (_promotion_failed_info.has_failed()) {
+ gc_tracer.report_promotion_failed(_promotion_failed_info);
+ }
+ // Reset the PromotionFailureALot counters.
+ NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
+}
void ParNewGeneration::collect(bool full,
bool clear_all_soft_refs,
size_t size,
bool is_tlab) {
assert(full || size > 0, "otherwise we don't want to collect");
+
GenCollectedHeap* gch = GenCollectedHeap::heap();
+
+ _gc_timer->register_gc_start(os::elapsed_counter());
+
assert(gch->kind() == CollectedHeap::GenCollectedHeap,
"not a CMS generational heap");
AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
@@ -906,7 +937,7 @@
set_avoid_promotion_undo(true);
}
- // If the next generation is too full to accomodate worst-case promotion
+ // If the next generation is too full to accommodate worst-case promotion
// from this generation, pass on collection; let the next generation
// do it.
if (!collection_attempt_is_safe()) {
@@ -915,6 +946,10 @@
}
assert(to()->is_empty(), "Else not collection_attempt_is_safe");
+ ParNewTracer gc_tracer;
+ gc_tracer.report_gc_start(gch->gc_cause(), _gc_timer->gc_start());
+ gch->trace_heap_before_gc(&gc_tracer);
+
init_assuming_no_promotion_failure();
if (UseAdaptiveSizePolicy) {
@@ -922,7 +957,7 @@
size_policy->minor_collection_begin();
}
- TraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, gclog_or_tty);
+ GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
// Capture heap used before collection (for printing).
size_t gch_prev_used = gch->used();
@@ -975,17 +1010,21 @@
rp->setup_policy(clear_all_soft_refs);
// Can the mt_degree be set later (at run_task() time would be best)?
rp->set_active_mt_degree(active_workers);
+ ReferenceProcessorStats stats;
if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
- rp->process_discovered_references(&is_alive, &keep_alive,
- &evacuate_followers, &task_executor);
+ stats = rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, &task_executor,
+ _gc_timer);
} else {
thread_state_set.flush();
gch->set_par_threads(0); // 0 ==> non-parallel.
gch->save_marks();
- rp->process_discovered_references(&is_alive, &keep_alive,
- &evacuate_followers, NULL);
+ stats = rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, NULL,
+ _gc_timer);
}
+ gc_tracer.report_gc_reference_stats(stats);
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);
@@ -1010,22 +1049,7 @@
adjust_desired_tenuring_threshold();
} else {
- assert(_promo_failure_scan_stack.is_empty(), "post condition");
- _promo_failure_scan_stack.clear(true); // Clear cached segments.
-
- remove_forwarding_pointers();
- if (PrintGCDetails) {
- gclog_or_tty->print(" (promotion failed)");
- }
- // All the spaces are in play for mark-sweep.
- swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
- from()->set_next_compaction_space(to());
- gch->set_incremental_collection_failed();
- // Inform the next generation that a promotion failure occurred.
- _next_gen->promotion_failure_occurred();
-
- // Reset the PromotionFailureALot counters.
- NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
+ handle_promotion_failed(gch, thread_state_set, gc_tracer);
}
// set new iteration safe limit for the survivor spaces
from()->set_concurrent_iteration_safe_limit(from()->top());
@@ -1065,6 +1089,13 @@
rp->enqueue_discovered_references(NULL);
}
rp->verify_no_references_recorded();
+
+ gch->trace_heap_after_gc(&gc_tracer);
+ gc_tracer.report_tenuring_threshold(tenuring_threshold());
+
+ _gc_timer->register_gc_end(os::elapsed_counter());
+
+ gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
}
static int sum;
@@ -1174,8 +1205,7 @@
new_obj = old;
preserve_mark_if_necessary(old, m);
- // Log the size of the maiden promotion failure
- par_scan_state->log_promotion_failure(sz);
+ par_scan_state->register_promotion_failure(sz);
}
old->forward_to(new_obj);
@@ -1300,8 +1330,7 @@
failed_to_promote = true;
preserve_mark_if_necessary(old, m);
- // Log the size of the maiden promotion failure
- par_scan_state->log_promotion_failure(sz);
+ par_scan_state->register_promotion_failure(sz);
}
} else {
// Is in to-space; do copying ourselves.
@@ -1599,8 +1628,7 @@
}
#undef BUSY
-void ParNewGeneration::ref_processor_init()
-{
+void ParNewGeneration::ref_processor_init() {
if (_ref_processor == NULL) {
// Allocate and initialize a reference processor
_ref_processor =