# HG changeset patch # User cjplummer # Date 1458591586 0 # Node ID 53914a6631b556d5c3d222b01433954091e35f1b # Parent 8a5f1594e692205962a6a0be959c9cd0f48dda49# Parent ed7da23aaa1622617127eb060eab99f752c552ec Merge diff -r 8a5f1594e692 -r 53914a6631b5 hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 21 13:14:31 2016 -0700 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Mar 21 20:19:46 2016 +0000 @@ -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); diff -r 8a5f1594e692 -r 53914a6631b5 hotspot/src/share/vm/gc/shared/referenceProcessor.cpp --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Mar 21 13:14:31 2016 -0700 +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp Mon Mar 21 20:19:46 2016 +0000 @@ -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; diff -r 8a5f1594e692 -r 53914a6631b5 hotspot/src/share/vm/gc/shared/referenceProcessor.hpp --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Mar 21 13:14:31 2016 -0700 +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.hpp Mon Mar 21 20:19:46 2016 +0000 @@ -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[]); diff -r 8a5f1594e692 -r 53914a6631b5 hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java --- a/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Mon Mar 21 13:14:31 2016 -0700 +++ b/hotspot/test/gc/ergonomics/TestDynamicNumberOfGCThreads.java Mon Mar 21 20:19:46 2016 +0000 @@ -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 {