Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: 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
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | 5d254928c888 |
children | c96030fff130 |
comparison
equal
deleted
inserted
replaced
443:b5e603f2e024 | 452:00b023ae2d78 |
---|---|
536 _survivor_plab_array(NULL), // -- ditto -- | 536 _survivor_plab_array(NULL), // -- ditto -- |
537 _survivor_chunk_array(NULL), // -- ditto -- | 537 _survivor_chunk_array(NULL), // -- ditto -- |
538 _survivor_chunk_capacity(0), // -- ditto -- | 538 _survivor_chunk_capacity(0), // -- ditto -- |
539 _survivor_chunk_index(0), // -- ditto -- | 539 _survivor_chunk_index(0), // -- ditto -- |
540 _ser_pmc_preclean_ovflw(0), | 540 _ser_pmc_preclean_ovflw(0), |
541 _ser_kac_preclean_ovflw(0), | |
541 _ser_pmc_remark_ovflw(0), | 542 _ser_pmc_remark_ovflw(0), |
542 _par_pmc_remark_ovflw(0), | 543 _par_pmc_remark_ovflw(0), |
543 _ser_kac_ovflw(0), | 544 _ser_kac_ovflw(0), |
544 _par_kac_ovflw(0), | 545 _par_kac_ovflw(0), |
545 #ifndef PRODUCT | 546 #ifndef PRODUCT |
4386 if (clean_refs) { | 4387 if (clean_refs) { |
4387 ReferenceProcessor* rp = ref_processor(); | 4388 ReferenceProcessor* rp = ref_processor(); |
4388 CMSPrecleanRefsYieldClosure yield_cl(this); | 4389 CMSPrecleanRefsYieldClosure yield_cl(this); |
4389 assert(rp->span().equals(_span), "Spans should be equal"); | 4390 assert(rp->span().equals(_span), "Spans should be equal"); |
4390 CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, | 4391 CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, |
4391 &_markStack); | 4392 &_markStack, true /* preclean */); |
4392 CMSDrainMarkingStackClosure complete_trace(this, | 4393 CMSDrainMarkingStackClosure complete_trace(this, |
4393 _span, &_markBitMap, &_markStack, | 4394 _span, &_markBitMap, &_markStack, |
4394 &keep_alive); | 4395 &keep_alive, true /* preclean */); |
4395 | 4396 |
4396 // We don't want this step to interfere with a young | 4397 // We don't want this step to interfere with a young |
4397 // collection because we don't want to take CPU | 4398 // collection because we don't want to take CPU |
4398 // or memory bandwidth away from the young GC threads | 4399 // or memory bandwidth away from the young GC threads |
4399 // (which may be as many as there are CPUs). | 4400 // (which may be as many as there are CPUs). |
4850 // events during the current CMS cycle, take appropriate | 4851 // events during the current CMS cycle, take appropriate |
4851 // remedial measures, where possible, so as to try and avoid | 4852 // remedial measures, where possible, so as to try and avoid |
4852 // recurrence of that condition. | 4853 // recurrence of that condition. |
4853 assert(_markStack.isEmpty(), "No grey objects"); | 4854 assert(_markStack.isEmpty(), "No grey objects"); |
4854 size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw + | 4855 size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw + |
4855 _ser_kac_ovflw; | 4856 _ser_kac_ovflw + _ser_kac_preclean_ovflw; |
4856 if (ser_ovflw > 0) { | 4857 if (ser_ovflw > 0) { |
4857 if (PrintCMSStatistics != 0) { | 4858 if (PrintCMSStatistics != 0) { |
4858 gclog_or_tty->print_cr("Marking stack overflow (benign) " | 4859 gclog_or_tty->print_cr("Marking stack overflow (benign) " |
4859 "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")", | 4860 "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT |
4861 ", kac_preclean="SIZE_FORMAT")", | |
4860 _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw, | 4862 _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw, |
4861 _ser_kac_ovflw); | 4863 _ser_kac_ovflw, _ser_kac_preclean_ovflw); |
4862 } | 4864 } |
4863 _markStack.expand(); | 4865 _markStack.expand(); |
4864 _ser_pmc_remark_ovflw = 0; | 4866 _ser_pmc_remark_ovflw = 0; |
4865 _ser_pmc_preclean_ovflw = 0; | 4867 _ser_pmc_preclean_ovflw = 0; |
4868 _ser_kac_preclean_ovflw = 0; | |
4866 _ser_kac_ovflw = 0; | 4869 _ser_kac_ovflw = 0; |
4867 } | 4870 } |
4868 if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) { | 4871 if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) { |
4869 if (PrintCMSStatistics != 0) { | 4872 if (PrintCMSStatistics != 0) { |
4870 gclog_or_tty->print_cr("Work queue overflow (benign) " | 4873 gclog_or_tty->print_cr("Work queue overflow (benign) " |
5691 verify_work_stacks_empty(); | 5694 verify_work_stacks_empty(); |
5692 | 5695 |
5693 ReferenceProcessor* rp = ref_processor(); | 5696 ReferenceProcessor* rp = ref_processor(); |
5694 assert(rp->span().equals(_span), "Spans should be equal"); | 5697 assert(rp->span().equals(_span), "Spans should be equal"); |
5695 CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap, | 5698 CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap, |
5696 &_markStack); | 5699 &_markStack, false /* !preclean */); |
5697 CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this, | 5700 CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this, |
5698 _span, &_markBitMap, &_markStack, | 5701 _span, &_markBitMap, &_markStack, |
5699 &cmsKeepAliveClosure); | 5702 &cmsKeepAliveClosure, false /* !preclean */); |
5700 { | 5703 { |
5701 TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty); | 5704 TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty); |
5702 if (rp->processing_is_mt()) { | 5705 if (rp->processing_is_mt()) { |
5703 CMSRefProcTaskExecutor task_executor(*this); | 5706 CMSRefProcTaskExecutor task_executor(*this); |
5704 rp->process_discovered_references(soft_ref_policy, | 5707 rp->process_discovered_references(soft_ref_policy, |
8300 // simulate a stack overflow | 8303 // simulate a stack overflow |
8301 simulate_overflow = true; | 8304 simulate_overflow = true; |
8302 } | 8305 } |
8303 ) | 8306 ) |
8304 if (simulate_overflow || !_mark_stack->push(obj)) { | 8307 if (simulate_overflow || !_mark_stack->push(obj)) { |
8305 _collector->push_on_overflow_list(obj); | 8308 if (_concurrent_precleaning) { |
8306 _collector->_ser_kac_ovflw++; | 8309 // We dirty the overflown object and let the remark |
8310 // phase deal with it. | |
8311 assert(_collector->overflow_list_is_empty(), "Error"); | |
8312 // In the case of object arrays, we need to dirty all of | |
8313 // the cards that the object spans. No locking or atomics | |
8314 // are needed since no one else can be mutating the mod union | |
8315 // table. | |
8316 if (obj->is_objArray()) { | |
8317 size_t sz = obj->size(); | |
8318 HeapWord* end_card_addr = | |
8319 (HeapWord*)round_to((intptr_t)(addr+sz), CardTableModRefBS::card_size); | |
8320 MemRegion redirty_range = MemRegion(addr, end_card_addr); | |
8321 assert(!redirty_range.is_empty(), "Arithmetical tautology"); | |
8322 _collector->_modUnionTable.mark_range(redirty_range); | |
8323 } else { | |
8324 _collector->_modUnionTable.mark(addr); | |
8325 } | |
8326 _collector->_ser_kac_preclean_ovflw++; | |
8327 } else { | |
8328 _collector->push_on_overflow_list(obj); | |
8329 _collector->_ser_kac_ovflw++; | |
8330 } | |
8307 } | 8331 } |
8308 } | 8332 } |
8309 } | 8333 } |
8310 | 8334 |
8311 void CMSKeepAliveClosure::do_oop(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } | 8335 void CMSKeepAliveClosure::do_oop(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } |
8398 } | 8422 } |
8399 | 8423 |
8400 void CMSDrainMarkingStackClosure::do_void() { | 8424 void CMSDrainMarkingStackClosure::do_void() { |
8401 // the max number to take from overflow list at a time | 8425 // the max number to take from overflow list at a time |
8402 const size_t num = _mark_stack->capacity()/4; | 8426 const size_t num = _mark_stack->capacity()/4; |
8427 assert(!_concurrent_precleaning || _collector->overflow_list_is_empty(), | |
8428 "Overflow list should be NULL during concurrent phases"); | |
8403 while (!_mark_stack->isEmpty() || | 8429 while (!_mark_stack->isEmpty() || |
8404 // if stack is empty, check the overflow list | 8430 // if stack is empty, check the overflow list |
8405 _collector->take_from_overflow_list(num, _mark_stack)) { | 8431 _collector->take_from_overflow_list(num, _mark_stack)) { |
8406 oop obj = _mark_stack->pop(); | 8432 oop obj = _mark_stack->pop(); |
8407 HeapWord* addr = (HeapWord*)obj; | 8433 HeapWord* addr = (HeapWord*)obj; |