# HG changeset patch # Parent 8e73bb107e364540f8856a8c661a635f82bf0943 diff -r 8e73bb107e36 src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.cpp --- a/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.cpp Mon Nov 04 16:44:31 2019 +0100 +++ b/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.cpp Mon Nov 04 16:46:21 2019 +0100 @@ -48,6 +48,8 @@ size_t ShenandoahHeapRegion::MaxTLABSizeBytes = 0; size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0; +ShenandoahHeapRegion::PaddedAllocSeqNum ShenandoahHeapRegion::_alloc_seq_num; + ShenandoahHeapRegion::ShenandoahHeapRegion(ShenandoahHeap* heap, HeapWord* start, size_t size_words, size_t index, bool committed) : _heap(heap), @@ -59,6 +61,10 @@ _tlab_allocs(0), _gclab_allocs(0), _shared_allocs(0), + _seqnum_first_alloc_mutator(0), + _seqnum_first_alloc_gc(0), + _seqnum_last_alloc_mutator(0), + _seqnum_last_alloc_gc(0), _live_data(0), _critical_pins(0) { @@ -301,6 +307,10 @@ _tlab_allocs = 0; _gclab_allocs = 0; _shared_allocs = 0; + _seqnum_first_alloc_mutator = 0; + _seqnum_last_alloc_mutator = 0; + _seqnum_first_alloc_gc = 0; + _seqnum_last_alloc_gc = 0; } void ShenandoahHeapRegion::reset_alloc_metadata_to_shared() { @@ -308,6 +318,11 @@ _tlab_allocs = 0; _gclab_allocs = 0; _shared_allocs = used() >> LogHeapWordSize; + uint64_t next = _alloc_seq_num.value++; + _seqnum_first_alloc_mutator = next; + _seqnum_last_alloc_mutator = next; + _seqnum_first_alloc_gc = 0; + _seqnum_last_alloc_gc = 0; } else { reset_alloc_metadata(); } @@ -401,7 +416,9 @@ st->print("|S " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_shared_allocs()), proper_unit_for_byte_size(get_shared_allocs())); st->print("|L " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_live_data_bytes()), proper_unit_for_byte_size(get_live_data_bytes())); st->print("|CP " SIZE_FORMAT_W(3), pin_count()); - + st->print("|SN " UINT64_FORMAT_X_W(12) ", " UINT64_FORMAT_X_W(8) ", " UINT64_FORMAT_X_W(8) ", " UINT64_FORMAT_X_W(8), + seqnum_first_alloc_mutator(), seqnum_last_alloc_mutator(), + seqnum_first_alloc_gc(), seqnum_last_alloc_gc()); st->cr(); } diff -r 8e73bb107e36 src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.hpp --- a/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.hpp Mon Nov 04 16:44:31 2019 +0100 +++ b/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.hpp Mon Nov 04 16:46:21 2019 +0100 @@ -212,6 +212,21 @@ static size_t MaxTLABSizeBytes; static size_t MaxTLABSizeWords; + // Global allocation counter, increased for each allocation under Shenandoah heap lock. + // Padded to avoid false sharing with the read-only fields above. + struct PaddedAllocSeqNum { + char _pad0[DEFAULT_CACHE_LINE_SIZE]; + uint64_t value; + char _pad1[DEFAULT_CACHE_LINE_SIZE]; + + PaddedAllocSeqNum() { + // start with 1, reserve 0 for uninitialized value + value = 1; + } + }; + + static PaddedAllocSeqNum _alloc_seq_num; + // Never updated fields ShenandoahHeap* _heap; MemRegion _reserved; @@ -229,6 +244,11 @@ size_t _gclab_allocs; size_t _shared_allocs; + uint64_t _seqnum_first_alloc_mutator; + uint64_t _seqnum_first_alloc_gc; + uint64_t _seqnum_last_alloc_mutator; + uint64_t _seqnum_last_alloc_gc; + volatile jint _live_data; volatile jint _critical_pins; @@ -318,6 +338,11 @@ return ShenandoahHeapRegion::MaxTLABSizeWords; } + static uint64_t seqnum_current_alloc() { + // Last used seq number + return _alloc_seq_num.value - 1; + } + size_t region_number() const; // Allocation (return NULL if full) @@ -364,6 +389,32 @@ size_t get_tlab_allocs() const; size_t get_gclab_allocs() const; + uint64_t seqnum_first_alloc() const { + if (_seqnum_first_alloc_mutator == 0) return _seqnum_first_alloc_gc; + if (_seqnum_first_alloc_gc == 0) return _seqnum_first_alloc_mutator; + return MIN2(_seqnum_first_alloc_mutator, _seqnum_first_alloc_gc); + } + + uint64_t seqnum_last_alloc() const { + return MAX2(_seqnum_last_alloc_mutator, _seqnum_last_alloc_gc); + } + + uint64_t seqnum_first_alloc_mutator() const { + return _seqnum_first_alloc_mutator; + } + + uint64_t seqnum_last_alloc_mutator() const { + return _seqnum_last_alloc_mutator; + } + + uint64_t seqnum_first_alloc_gc() const { + return _seqnum_first_alloc_gc; + } + + uint64_t seqnum_last_alloc_gc() const { + return _seqnum_last_alloc_gc; + } + private: void do_commit(); void do_uncommit(); diff -r 8e73bb107e36 src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.inline.hpp --- a/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.inline.hpp Mon Nov 04 16:44:31 2019 +0100 +++ b/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.inline.hpp Mon Nov 04 16:46:21 2019 +0100 @@ -52,6 +52,29 @@ } inline void ShenandoahHeapRegion::adjust_alloc_metadata(ShenandoahAllocRequest::Type type, size_t size) { + bool is_first_alloc = (top() == bottom()); + + switch (type) { + case ShenandoahAllocRequest::_alloc_shared: + case ShenandoahAllocRequest::_alloc_tlab: + _seqnum_last_alloc_mutator = _alloc_seq_num.value++; + if (is_first_alloc) { + assert (_seqnum_first_alloc_mutator == 0, err_msg("Region " SIZE_FORMAT " metadata is correct", _region_number)); + _seqnum_first_alloc_mutator = _seqnum_last_alloc_mutator; + } + break; + case ShenandoahAllocRequest::_alloc_shared_gc: + case ShenandoahAllocRequest::_alloc_gclab: + _seqnum_last_alloc_gc = _alloc_seq_num.value++; + if (is_first_alloc) { + assert (_seqnum_first_alloc_gc == 0, err_msg("Region " SIZE_FORMAT " metadata is correct", _region_number)); + _seqnum_first_alloc_gc = _seqnum_last_alloc_gc; + } + break; + default: + ShouldNotReachHere(); + } + switch (type) { case ShenandoahAllocRequest::_alloc_shared: case ShenandoahAllocRequest::_alloc_shared_gc: diff -r 8e73bb107e36 src/share/vm/gc_implementation/shenandoah/shenandoahVerifier.cpp --- a/src/share/vm/gc_implementation/shenandoah/shenandoahVerifier.cpp Mon Nov 04 16:44:31 2019 +0100 +++ b/src/share/vm/gc_implementation/shenandoah/shenandoahVerifier.cpp Mon Nov 04 16:46:21 2019 +0100 @@ -388,6 +388,27 @@ verify(r, r->is_cset() == _heap->collection_set()->is_in(r), "Transitional: region flags and collection set agree"); + + verify(r, r->is_empty() || r->seqnum_first_alloc() != 0, + "Non-empty regions should have first seqnum set"); + + verify(r, r->is_empty() || (r->seqnum_first_alloc_mutator() != 0 || r->seqnum_first_alloc_gc() != 0), + "Non-empty regions should have first seqnum set to either GC or mutator"); + + verify(r, r->is_empty() || r->seqnum_last_alloc() != 0, + "Non-empty regions should have last seqnum set"); + + verify(r, r->is_empty() || (r->seqnum_last_alloc_mutator() != 0 || r->seqnum_last_alloc_gc() != 0), + "Non-empty regions should have last seqnum set to either GC or mutator"); + + verify(r, r->seqnum_first_alloc() <= r->seqnum_last_alloc(), + "First seqnum should not be greater than last timestamp"); + + verify(r, r->seqnum_first_alloc_mutator() <= r->seqnum_last_alloc_mutator(), + "First mutator seqnum should not be greater than last seqnum"); + + verify(r, r->seqnum_first_alloc_gc() <= r->seqnum_last_alloc_gc(), + "First GC seqnum should not be greater than last seqnum"); } };