JDK-6978187 : G1: assert(ParallelGCThreads> 1 || n_yielded() == _hrrs->occupied()) strikes again
  • Type: Bug
  • Component: hotspot
  • Sub-Component: gc
  • Affected Version: hs19
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-08-18
  • Updated: 2013-09-18
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u25Fixed 7Fixed hs20Fixed
Related Reports
Relates :  
Description
We hit again this failure during nightly testing:

assert(ParallelGCThreads>  1 || n_yielded() == _hrrs->occupied()) failed: Should have yielded all the cards in the rem set (in the non-par case).

It should have been fixed when the changes for 6930581 were pushed.

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/build/hotspot/rev/878b57474103
25-12-2010

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/878b57474103
17-11-2010

SUGGESTED FIX Background: In concurrentRefineOneCard_impl, we detect if the card contains reference that point into the collection set (if the check_for_refs_into_cset) is set and return a true value. In the code that calls concurrentRefineOneCard, if the result is true then we add the card to a special dirty card queue. After RSet scanning, if an evacuation failure occurs, the entries associated with this special DirtyCardQueue are processed and the RSets for the regions in the collection set updated. There is a really simple and localized fix: remove the extra "!is_self_forwarded(obj)" check from the code in par_write_ref_nv. This will add the reference to the _refs queue in the G1ParScanThreadState rather than adding it directly to the remembered set. The mechanism described above will record the card containing the reference and update the RSet. Adding the reference to the G1ParScanThreadState::_refs queue should be "relatively" benign - the object has already to been forwarded to itself - the copy code should just skip this object as it has already been forwarded. The only risk is potentially overflowing the _refs queue. An alternative is to structure the code : if (_trav_in_progress && to->in_collection_set()) { if (!self_forwarded(obj)) { _closure-do_oop(p); } } else { // Add ref directly to RSet } This would achieve the same goal while not adding the reference to the _refs queue. Another larger alternative is to simplify par_write_ref to just add to the remembered set and have another routine that records the reference in the _refs queue (par_scan_ref??) and move the control logic from par_write_ref into the callers of par_write_ref. Currently there are only 2 callers: UpdateRSOopClosure::do_oop_work and UpdateSetImmediate::do_oop_work. The second of these is called when _traversal_in_progress is false and so will always add directly to the RSet. The first of these is called from * updating the RSets after a full GC. In this case we would want to update the RSets directly. SO we could employ the UpdateRSetImmediate closure here. * concurrent refinement and RSet updates during a pause. Both these cases go through the routine concurrentRefineOneCard. During CR the flags check_for_refs_into_cset is false and the value of _traversal_in_progress is false so we want to update the RSet directly. During the actual pause we want to record references that point into the collection set _OR_ update the RSet directly. In this case _traversal_in_progress is true and so is check_for_refs. It would appear that _traversal_in_progress is equivalent to check_for_refs_into_cset (for the instances of UpdateRSOopClosure in concurrentRefineOneCard).
20-08-2010

EVALUATION During copying (RSet scanning), we get an evacuation failure that causes an object, A, to be forwarded to itself. In parallel, during RSet updating, we process the logged update of a reference field that points to A. Since A has been forwarded to itself the code in HRInto_G1RemSet::par_write_ref_nv executes the code path that add the reference to the RSet of the region containing A. This causes the Remembered Set to expand resulting in the assertion when the scanning of RSet for A's region is complete.
19-08-2010