8149343: assert(rp->num_q() == no_of_gc_workers) failed: sanity
Reviewed-by: tschatzl, kbarrett
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 07 11:28:06 2016 -0800
@@ -4247,7 +4247,7 @@
_workers(workers),
_active_workers(n_workers)
{
- assert(n_workers > 0, "shouldn't call this otherwise");
+ g1h->ref_processor_stw()->set_active_mt_degree(n_workers);
}
// Executes the given task using concurrent marking worker threads.
@@ -4368,7 +4368,9 @@
_queues(task_queues),
_terminator(workers, _queues),
_n_workers(workers)
- { }
+ {
+ g1h->ref_processor_cm()->set_active_mt_degree(workers);
+ }
void work(uint worker_id) {
G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id);
@@ -4511,8 +4513,9 @@
uint no_of_gc_workers = workers()->active_workers();
// Parallel reference processing
- assert(rp->num_q() == no_of_gc_workers, "sanity");
- assert(no_of_gc_workers <= rp->max_num_q(), "sanity");
+ assert(no_of_gc_workers <= rp->max_num_q(),
+ "Mismatch between the number of GC workers %u and the maximum number of Reference process queues %u",
+ no_of_gc_workers, rp->max_num_q());
G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, no_of_gc_workers);
stats = rp->process_discovered_references(&is_alive,
@@ -4548,8 +4551,9 @@
uint n_workers = workers()->active_workers();
- assert(rp->num_q() == n_workers, "sanity");
- assert(n_workers <= rp->max_num_q(), "sanity");
+ assert(n_workers <= rp->max_num_q(),
+ "Mismatch between the number of GC workers %u and the maximum number of Reference process queues %u",
+ n_workers, rp->max_num_q());
G1STWRefProcTaskExecutor par_task_executor(this, per_thread_states, workers(), _task_queues, n_workers);
rp->enqueue_discovered_references(&par_task_executor);
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Mar 07 11:28:06 2016 -0800
@@ -134,7 +134,7 @@
guarantee(!_discovering_refs, "Discovering refs?");
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
guarantee(_discovered_refs[i].is_empty(),
- "Found non-empty discovered list");
+ "Found non-empty discovered list at %u", i);
}
}
#endif
@@ -683,19 +683,30 @@
};
#ifndef PRODUCT
-void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], size_t total_refs) {
+void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_refs) {
if (!log_is_enabled(Trace, gc, ref)) {
return;
}
stringStream st;
- for (uint i = 0; i < _max_num_q; ++i) {
+ for (uint i = 0; i < active_length; ++i) {
st.print(SIZE_FORMAT " ", ref_lists[i].length());
}
log_develop_trace(gc, ref)("%s= " SIZE_FORMAT, st.as_string(), total_refs);
+#ifdef ASSERT
+ for (uint i = active_length; i < _max_num_q; i++) {
+ assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u",
+ ref_lists[i].length(), i);
+ }
+#endif
}
#endif
+void ReferenceProcessor::set_active_mt_degree(uint v) {
+ _num_q = v;
+ _next_id = 0;
+}
+
// Balances reference queues.
// Move entries from all queues[0, 1, ..., _max_num_q-1] to
// queues[0, 1, ..., _num_q-1] because only the first _num_q
@@ -708,8 +719,8 @@
for (uint i = 0; i < _max_num_q; ++i) {
total_refs += ref_lists[i].length();
- }
- log_reflist_counts(ref_lists, total_refs);
+ }
+ log_reflist_counts(ref_lists, _max_num_q, total_refs);
size_t avg_refs = total_refs / _num_q + 1;
uint to_idx = 0;
for (uint from_idx = 0; from_idx < _max_num_q; from_idx++) {
@@ -771,10 +782,10 @@
}
#ifdef ASSERT
size_t balanced_total_refs = 0;
- for (uint i = 0; i < _max_num_q; ++i) {
+ for (uint i = 0; i < _num_q; ++i) {
balanced_total_refs += ref_lists[i].length();
- }
- log_reflist_counts(ref_lists, balanced_total_refs);
+ }
+ log_reflist_counts(ref_lists, _num_q, balanced_total_refs);
assert(total_refs == balanced_total_refs, "Balancing was incomplete");
#endif
}
@@ -868,7 +879,7 @@
id = next_id();
}
}
- assert(id < _max_num_q, "Id is out-of-bounds (call Freud?)");
+ assert(id < _max_num_q, "Id is out-of-bounds id %u and max id %u)", id, _max_num_q);
// Get the discovered queue to which we will add
DiscoveredList* list = NULL;
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Mar 07 11:28:06 2016 -0800
@@ -225,7 +225,7 @@
uint num_q() { return _num_q; }
uint max_num_q() { return _max_num_q; }
- void set_active_mt_degree(uint v) { _num_q = v; }
+ void set_active_mt_degree(uint v);
DiscoveredList* discovered_refs() { return _discovered_refs; }
@@ -326,9 +326,11 @@
// round-robin mod _num_q (not: _not_ mode _max_num_q)
uint next_id() {
uint id = _next_id;
+ assert(!_discovery_is_mt, "Round robin should only be used in serial discovery");
if (++_next_id == _num_q) {
_next_id = 0;
}
+ assert(_next_id < _num_q, "_next_id %u _num_q %u _max_num_q %u", _next_id, _num_q, _max_num_q);
return id;
}
DiscoveredList* get_discovered_list(ReferenceType rt);
@@ -340,7 +342,7 @@
// Calculate the number of jni handles.
size_t count_jni_refs();
- void log_reflist_counts(DiscoveredList ref_lists[], size_t total_count) PRODUCT_RETURN;
+ void log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_count) PRODUCT_RETURN;
// Balances reference queues.
void balance_queues(DiscoveredList ref_lists[]);
--- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Mon Mar 21 12:52:24 2016 +0100
+++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Mon Mar 07 11:28:06 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -63,6 +63,14 @@
System.arraycopy(baseArgs, 0, finalArgs, extraArgs.length, baseArgs.length);
pb_enabled = ProcessTools.createJavaProcessBuilder(finalArgs);
verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
+
+ // Turn on parallel reference processing
+ String[] parRefProcArg = {"-XX:+ParallelRefProcEnabled", "-XX:-ShowMessageBoxOnError"};
+ String[] parRefArgs = new String[baseArgs.length + parRefProcArg.length];
+ System.arraycopy(parRefProcArg, 0, parRefArgs, 0, parRefProcArg.length);
+ System.arraycopy(baseArgs, 0, parRefArgs, parRefProcArg.length, baseArgs.length);
+ pb_enabled = ProcessTools.createJavaProcessBuilder(parRefArgs);
+ verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()));
}
static class GCTest {