Tue, 19 Aug 2014 02:05:49 -0700
8044406: JVM crash with JDK8 (build 1.8.0-b132) with G1 GC
Summary: Fill the last card that has been allocated into with a dummy object
Reviewed-by: tschatzl, mgerdin
1.1 --- a/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp Wed Aug 13 17:37:11 2014 -0700 1.2 +++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp Tue Aug 19 02:05:49 2014 -0700 1.3 @@ -173,7 +173,7 @@ 1.4 1.5 // Should be called when we want to release the active region which 1.6 // is returned after it's been retired. 1.7 - HeapRegion* release(); 1.8 + virtual HeapRegion* release(); 1.9 1.10 #if G1_ALLOC_REGION_TRACING 1.11 void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL);
2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Aug 13 17:37:11 2014 -0700 2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Aug 19 02:05:49 2014 -0700 2.3 @@ -7053,6 +7053,35 @@ 2.4 _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, 2.5 GCAllocForTenured); 2.6 } 2.7 + 2.8 +HeapRegion* OldGCAllocRegion::release() { 2.9 + HeapRegion* cur = get(); 2.10 + if (cur != NULL) { 2.11 + // Determine how far we are from the next card boundary. If it is smaller than 2.12 + // the minimum object size we can allocate into, expand into the next card. 2.13 + HeapWord* top = cur->top(); 2.14 + HeapWord* aligned_top = (HeapWord*)align_ptr_up(top, G1BlockOffsetSharedArray::N_bytes); 2.15 + 2.16 + size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize); 2.17 + 2.18 + if (to_allocate_words != 0) { 2.19 + // We are not at a card boundary. Fill up, possibly into the next, taking the 2.20 + // end of the region and the minimum object size into account. 2.21 + to_allocate_words = MIN2(pointer_delta(cur->end(), cur->top(), HeapWordSize), 2.22 + MAX2(to_allocate_words, G1CollectedHeap::min_fill_size())); 2.23 + 2.24 + // Skip allocation if there is not enough space to allocate even the smallest 2.25 + // possible object. In this case this region will not be retained, so the 2.26 + // original problem cannot occur. 2.27 + if (to_allocate_words >= G1CollectedHeap::min_fill_size()) { 2.28 + HeapWord* dummy = attempt_allocation(to_allocate_words, true /* bot_updates */); 2.29 + CollectedHeap::fill_with_object(dummy, to_allocate_words); 2.30 + } 2.31 + } 2.32 + } 2.33 + return G1AllocRegion::release(); 2.34 +} 2.35 + 2.36 // Heap region set verification 2.37 2.38 class VerifyRegionListsClosure : public HeapRegionClosure {
3.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Aug 13 17:37:11 2014 -0700 3.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Aug 19 02:05:49 2014 -0700 3.3 @@ -183,6 +183,13 @@ 3.4 public: 3.5 OldGCAllocRegion() 3.6 : G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { } 3.7 + 3.8 + // This specialization of release() makes sure that the last card that has been 3.9 + // allocated into has been completely filled by a dummy object. 3.10 + // This avoids races when remembered set scanning wants to update the BOT of the 3.11 + // last card in the retained old gc alloc region, and allocation threads 3.12 + // allocating into that card at the same time. 3.13 + virtual HeapRegion* release(); 3.14 }; 3.15 3.16 // The G1 STW is alive closure.