--- old/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp 2020-04-22 11:59:01.640924735 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp 2020-04-22 11:59:01.432924655 +0200 @@ -123,6 +123,7 @@ template oop load_reference_barrier_native_impl(oop obj, T* load_addr); + inline bool skip_bulk_update(HeapWord* dst); public: // Callbacks for runtime accesses. template --- old/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp 2020-04-22 11:59:02.304924989 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp 2020-04-22 11:59:02.100924913 +0200 @@ -293,11 +293,14 @@ template void ShenandoahBarrierSet::arraycopy_pre_work(T* src, T* dst, size_t count) { - if (_heap->is_concurrent_mark_in_progress()) { + if (_heap->is_concurrent_mark_in_progress() && + !_heap->marking_context()->allocated_after_mark_start(reinterpret_cast(dst))) { arraycopy_work(dst, count); } - arraycopy_update_impl(src, count); + if (_heap->has_forwarded_objects()) { + arraycopy_update_impl(src, count); + } } void ShenandoahBarrierSet::arraycopy_pre(oop* src, oop* dst, size_t count) { @@ -308,8 +311,13 @@ arraycopy_pre_work(src, dst, count); } +inline bool ShenandoahBarrierSet::skip_bulk_update(HeapWord* dst) { + return dst >= _heap->heap_region_containing(dst)->get_update_watermark(); +} + template void ShenandoahBarrierSet::arraycopy_update_impl(T* src, size_t count) { + if (skip_bulk_update(reinterpret_cast(src))) return; if (_heap->is_evacuation_in_progress()) { ShenandoahEvacOOMScope oom_evac; arraycopy_work(src, count); --- old/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp 2020-04-22 11:59:02.972925241 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp 2020-04-22 11:59:02.764925162 +0200 @@ -81,6 +81,7 @@ // that potentially need to be updated. shenandoah_assert_correct(NULL, obj); + if (skip_bulk_update(cast_from_oop(obj))) return; if (_heap->is_evacuation_in_progress()) { ShenandoahEvacOOMScope evac_scope; ShenandoahUpdateRefsForOopClosure cl; --- old/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2020-04-22 11:59:03.632925483 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp 2020-04-22 11:59:03.424925406 +0200 @@ -2294,6 +2294,7 @@ if (r->is_active() && !r->is_cset()) { _heap->marked_object_oop_iterate(r, &cl, update_watermark); } + r->set_update_watermark(r->bottom()); if (ShenandoahPacing) { _heap->pacer()->report_updaterefs(pointer_delta(update_watermark, r->bottom())); } --- old/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp 2020-04-22 11:59:04.324925735 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp 2020-04-22 11:59:04.120925660 +0200 @@ -260,7 +260,7 @@ volatile size_t _live_data; volatile size_t _critical_pins; - HeapWord* _update_watermark; + HeapWord* volatile _update_watermark; // Claim some space at the end to protect next region DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); @@ -431,12 +431,12 @@ HeapWord* get_update_watermark() const { assert(bottom() <= _update_watermark && _update_watermark <= top(), "within bounds"); - return _update_watermark; + return Atomic::load_acquire(&_update_watermark); } void set_update_watermark(HeapWord* w) { assert(bottom() <= w && w <= top(), "within bounds"); - _update_watermark = w; + Atomic::release_store(&_update_watermark, w); } private: --- old/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp 2020-04-22 11:59:04.992925973 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.hpp 2020-04-22 11:59:04.784925897 +0200 @@ -54,6 +54,7 @@ inline bool is_marked(oop obj) const; + inline bool allocated_after_mark_start(oop obj) const; inline bool allocated_after_mark_start(HeapWord* addr) const; inline MarkBitMap* mark_bit_map(); --- old/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp 2020-04-22 11:59:05.660926204 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp 2020-04-22 11:59:05.452926131 +0200 @@ -41,6 +41,11 @@ return allocated_after_mark_start(addr) || _mark_bit_map.is_marked(addr); } +inline bool ShenandoahMarkingContext::allocated_after_mark_start(oop obj) const { + HeapWord* addr = cast_from_oop(obj); + return allocated_after_mark_start(addr); +} + inline bool ShenandoahMarkingContext::allocated_after_mark_start(HeapWord* addr) const { uintx index = ((uintx) addr) >> ShenandoahHeapRegion::region_size_bytes_shift(); HeapWord* top_at_mark_start = _top_at_mark_starts[index]; --- old/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2020-04-22 11:59:06.308926426 +0200 +++ new/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp 2020-04-22 11:59:06.112926360 +0200 @@ -314,6 +314,7 @@ ShenandoahMarkingContext* const ctx = _heap->marking_context(); for (size_t i = 0; i < num_regions; i++) { ShenandoahHeapRegion* region = _heap->get_region(i); + region->set_update_watermark(region->top()); if (_heap->is_bitmap_slice_committed(region)) { if (_traversal_set.is_in(i)) { ctx->capture_top_at_mark_start(region);