8221848: Shenandoah: ArrayCopy post-barrier improvements
authorrkennke
Thu, 04 Apr 2019 21:29:46 +0200
changeset 54425 13c02cc7a6e5
parent 54424 b354ffb03ae4
child 54426 2da3b1a3942f
8221848: Shenandoah: ArrayCopy post-barrier improvements Reviewed-by: zgu
src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp
src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp
src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp
src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp
src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Thu Apr 04 21:29:46 2019 +0200
@@ -87,6 +87,16 @@
 void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                                        Register start, Register count, Register scratch, RegSet saved_regs) {
   if (is_oop) {
+      Label done;
+
+      // Avoid calling runtime if count == 0
+      __ cbz(count, done);
+
+      // Is updating references?
+      Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+      __ ldrb(rscratch1, gc_state);
+      __ tbz(rscratch1, ShenandoahHeap::UPDATEREFS_BITPOS, done);
+
     __ push(saved_regs, sp);
     assert_different_registers(start, count, scratch);
     assert_different_registers(c_rarg0, count);
@@ -94,6 +104,8 @@
     __ mov(c_rarg1, count);
     __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_post_entry), 2);
     __ pop(saved_regs, sp);
+
+    __ bind(done);
   }
 }
 
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp	Thu Apr 04 21:29:46 2019 +0200
@@ -138,6 +138,22 @@
     }
 #endif
 
+    Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+#ifndef _LP64
+    __ push(thread);
+    __ get_thread(thread);
+#endif
+
+    // Short-circuit if count == 0.
+    Label done;
+    __ testptr(count, count);
+    __ jcc(Assembler::zero, done);
+
+    // Skip runtime call if no forwarded objects.
+    Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
+    __ testb(gc_state, ShenandoahHeap::UPDATEREFS);
+    __ jcc(Assembler::zero, done);
+
     __ pusha();             // push registers (overkill)
 #ifdef _LP64
     if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
@@ -155,6 +171,9 @@
                     dst, count);
 #endif
     __ popa();
+
+    __ bind(done);
+    NOT_LP64(__ pop(thread);)
   }
 }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp	Thu Apr 04 21:29:46 2019 +0200
@@ -107,11 +107,8 @@
 }
 
 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
-  assert(UseShenandoahGC, "should be enabled");
-  if (count == 0) return;
-  if (!ShenandoahCloneBarrier) return;
-
-  if (!need_update_refs_barrier()) return;
+  assert(_heap->is_update_refs_in_progress(), "should not be here otherwise");
+  assert(count > 0, "Should have been filtered before");
 
   if (_heap->is_concurrent_traversal_in_progress()) {
     ShenandoahEvacOOMScope oom_evac_scope;
@@ -197,9 +194,8 @@
 }
 
 void ShenandoahBarrierSet::write_region(MemRegion mr) {
-  assert(UseShenandoahGC, "should be enabled");
   if (!ShenandoahCloneBarrier) return;
-  if (! need_update_refs_barrier()) return;
+  if (!_heap->is_update_refs_in_progress()) return;
 
   // This is called for cloning an object (see jvm.cpp) after the clone
   // has been made. We are not interested in any 'previous value' because
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Thu Apr 04 21:29:46 2019 +0200
@@ -100,8 +100,6 @@
   void enqueue(oop obj);
 
 private:
-  inline bool need_update_refs_barrier();
-
   template <class T, bool STOREVAL_WRITE_BARRIER>
   void write_ref_array_loop(HeapWord* start, size_t count);
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Thu Apr 04 21:29:46 2019 +0200
@@ -32,12 +32,6 @@
 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
 
-bool ShenandoahBarrierSet::need_update_refs_barrier() {
-  return _heap->is_update_refs_in_progress() ||
-         _heap->is_concurrent_traversal_in_progress() ||
-         (_heap->is_concurrent_mark_in_progress() && _heap->has_forwarded_objects());
-}
-
 inline oop ShenandoahBarrierSet::resolve_forwarded_not_null(oop p) {
   return ShenandoahBrooksPointer::forwardee(p);
 }
@@ -344,7 +338,7 @@
   if (heap->has_forwarded_objects()) {
     if (heap->is_concurrent_traversal_in_progress()) {
       storeval_mode = WRITE_BARRIER;
-    } else if (heap->is_concurrent_mark_in_progress() || heap->is_update_refs_in_progress()) {
+    } else if (heap->is_update_refs_in_progress()) {
       storeval_mode = READ_BARRIER;
     } else {
       assert(heap->is_idle() || heap->is_evacuation_in_progress(), "must not have anything in progress");
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Thu Apr 04 12:29:43 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Thu Apr 04 21:29:46 2019 +0200
@@ -1795,13 +1795,13 @@
 
 void ShenandoahHeap::stop_concurrent_marking() {
   assert(is_concurrent_mark_in_progress(), "How else could we get here?");
+  set_concurrent_mark_in_progress(false);
   if (!cancelled_gc()) {
     // If we needed to update refs, and concurrent marking has been cancelled,
     // we need to finish updating references.
     set_has_forwarded_objects(false);
     mark_complete_marking_context();
   }
-  set_concurrent_mark_in_progress(false);
 }
 
 void ShenandoahHeap::force_satb_flush_all_threads() {
@@ -1831,12 +1831,16 @@
 }
 
 void ShenandoahHeap::set_concurrent_mark_in_progress(bool in_progress) {
-  set_gc_state_mask(MARKING, in_progress);
+  if (has_forwarded_objects()) {
+    set_gc_state_mask(MARKING | UPDATEREFS, in_progress);
+  } else {
+    set_gc_state_mask(MARKING, in_progress);
+  }
   ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
 }
 
 void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
-   set_gc_state_mask(TRAVERSAL | HAS_FORWARDED, in_progress);
+   set_gc_state_mask(TRAVERSAL | HAS_FORWARDED | UPDATEREFS, in_progress);
    ShenandoahBarrierSet::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
 }