6977970: CMS: concurrentMarkSweepGeneration.cpp:7947 assert(addr <= _limit) failed: sweep invariant
Summary: Allow for the possibility (when the heap is expanding) that the sweep might skip over and past, rather than necessarily step on, the sweep limit determined at the beginning of a concurrent marking cycle.
Reviewed-by: jmasa, tonyp
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Aug 17 14:40:00 2010 -0400
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Aug 18 11:39:21 2010 -0700
@@ -7937,14 +7937,20 @@
FreeChunk* fc = (FreeChunk*)addr;
size_t res;
- // check if we are done sweepinrg
- if (addr == _limit) { // we have swept up to the limit, do nothing more
+ // Check if we are done sweeping. Below we check "addr >= _limit" rather
+ // than "addr == _limit" because although _limit was a block boundary when
+ // we started the sweep, it may no longer be one because heap expansion
+ // may have caused us to coalesce the block ending at the address _limit
+ // with a newly expanded chunk (this happens when _limit was set to the
+ // previous _end of the space), so we may have stepped past _limit; see CR 6977970.
+ if (addr >= _limit) { // we have swept up to or past the limit, do nothing more
assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
"sweep _limit out of bounds");
+ assert(addr < _sp->end(), "addr out of bounds");
// help the closure application finish
- return pointer_delta(_sp->end(), _limit);
- }
- assert(addr <= _limit, "sweep invariant");
+ return pointer_delta(_sp->end(), addr);
+ }
+ assert(addr < _limit, "sweep invariant");
// check if we should yield
do_yield_check(addr);