--- old/src/share/vm/gc/g1/g1RemSet.cpp 2016-11-15 18:28:26.951538025 -0500 +++ new/src/share/vm/gc/g1/g1RemSet.cpp 2016-11-15 18:28:26.859533382 -0500 @@ -675,21 +675,16 @@ card_ptr); // If unable to process the card then we encountered an unparsable - // part of the heap (e.g. a partially allocated object). Redirty - // and re-enqueue: if we put off the card until a GC pause, then the - // allocation will have completed. + // part of the heap (e.g. a partially allocated object) while + // processing a stale card. Despite the card being stale, redirty + // and re-enqueue, because we've already cleaned the card. Without + // this we could incorrectly discard a non-stale card. if (!card_processed) { assert(!_g1->is_gc_active(), "Unparsable heap during GC"); - // The card might have gotten re-dirtied and re-enqueued while we - // worked. (In fact, it's pretty likely.) - if (*card_ptr != CardTableModRefBS::dirty_card_val()) { - *card_ptr = CardTableModRefBS::dirty_card_val(); - MutexLockerEx x(Shared_DirtyCardQ_lock, - Mutex::_no_safepoint_check_flag); - DirtyCardQueue* sdcq = - JavaThread::dirty_card_queue_set().shared_dirty_card_queue(); - sdcq->enqueue(card_ptr); - } + // Using invalidate for one card is simple but expensive, but this + // should be rare; processing a stale card while a humongous + // object is in the midst of being allocated in the same region. + _ct_bs->invalidate(dirtyRegion); } else { _conc_refine_cards++; }