From 12508b32a7b7278a8244aef0252f27666b1b0afa Mon Sep 17 00:00:00 2001 From: poonam Date: Tue, 19 Aug 2014 02:05:49 -0700 Subject: [PATCH] 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 --- .../vm/gc_implementation/g1/g1AllocRegion.hpp | 2 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 29 +++++++++++++++++++ .../gc_implementation/g1/g1CollectedHeap.hpp | 7 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp b/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp index 050490dbb..50cc9be07 100644 --- a/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp +++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp @@ -173,7 +173,7 @@ public: // Should be called when we want to release the active region which // is returned after it's been retired. - HeapRegion* release(); + virtual HeapRegion* release(); #if G1_ALLOC_REGION_TRACING void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL); diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 56d30fe89..6ab61d666 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -6628,6 +6628,35 @@ void OldGCAllocRegion::retire_region(HeapRegion* alloc_region, _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, GCAllocForTenured); } + +HeapRegion* OldGCAllocRegion::release() { + HeapRegion* cur = get(); + if (cur != NULL) { + // Determine how far we are from the next card boundary. If it is smaller than + // the minimum object size we can allocate into, expand into the next card. + HeapWord* top = cur->top(); + HeapWord* aligned_top = (HeapWord*)align_ptr_up(top, G1BlockOffsetSharedArray::N_bytes); + + size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize); + + if (to_allocate_words != 0) { + // We are not at a card boundary. Fill up, possibly into the next, taking the + // end of the region and the minimum object size into account. + to_allocate_words = MIN2(pointer_delta(cur->end(), cur->top(), HeapWordSize), + MAX2(to_allocate_words, G1CollectedHeap::min_fill_size())); + + // Skip allocation if there is not enough space to allocate even the smallest + // possible object. In this case this region will not be retained, so the + // original problem cannot occur. + if (to_allocate_words >= G1CollectedHeap::min_fill_size()) { + HeapWord* dummy = attempt_allocation(to_allocate_words, true /* bot_updates */); + CollectedHeap::fill_with_object(dummy, to_allocate_words); + } + } + } + return G1AllocRegion::release(); +} + // Heap region set verification class VerifyRegionListsClosure : public HeapRegionClosure { diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index cc8b87533..753815a3e 100644 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -183,6 +183,13 @@ protected: public: OldGCAllocRegion() : G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { } + + // This specialization of release() makes sure that the last card that has been + // allocated into has been completely filled by a dummy object. + // This avoids races when remembered set scanning wants to update the BOT of the + // last card in the retained old gc alloc region, and allocation threads + // allocating into that card at the same time. + virtual HeapRegion* release(); }; // The G1 STW is alive closure. -- GitLab