6722113: CMS: Incorrect overflow handling during precleaning of Reference lists

When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.

Reviewed-by: apetrusenko, jcoomes
This commit is contained in:
Y. Srinivas Ramakrishna 2008-11-20 12:27:41 -08:00
parent 28b2c4aeaf
commit db6bef2c70
5 changed files with 95 additions and 48 deletions

View file

@ -592,6 +592,7 @@ class CMSCollector: public CHeapObj {
size_t _ser_pmc_preclean_ovflw;
size_t _ser_pmc_remark_ovflw;
size_t _par_pmc_remark_ovflw;
size_t _ser_kac_preclean_ovflw;
size_t _ser_kac_ovflw;
size_t _par_kac_ovflw;
NOT_PRODUCT(size_t _num_par_pushes;)
@ -1749,21 +1750,30 @@ class SweepClosure: public BlkClosureCareful {
// work-routine/closure used to complete transitive
// marking of objects as live after a certain point
// in which an initial set has been completely accumulated.
// This closure is currently used both during the final
// remark stop-world phase, as well as during the concurrent
// precleaning of the discovered reference lists.
class CMSDrainMarkingStackClosure: public VoidClosure {
CMSCollector* _collector;
MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
CMSKeepAliveClosure* _keep_alive;
bool _concurrent_precleaning;
public:
CMSDrainMarkingStackClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
CMSKeepAliveClosure* keep_alive):
CMSKeepAliveClosure* keep_alive,
bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_keep_alive(keep_alive) { }
_keep_alive(keep_alive),
_concurrent_precleaning(cpc) {
assert(_concurrent_precleaning == _keep_alive->concurrent_precleaning(),
"Mismatch");
}
void do_void();
};