Blob Blame History Raw

# HG changeset patch
# User zgu
# Date 1541803086 18000
# Node ID 9c4bf4a86cd89f33bee1e372fd8f6071636b0953
# Parent  1e4229c1a99bdbe79e202a41a046c13b9b4bd0b6
[backport] Always copy forward for disjoint arrays

diff -r 1e4229c1a99b -r 9c4bf4a86cd8 src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Fri Nov 09 12:49:43 2018 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Fri Nov 09 17:38:06 2018 -0500
@@ -120,18 +120,18 @@
 
   template <typename T>
   bool arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound,
-                        bool checkcast, bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
+                        bool checkcast, bool satb, bool disjoint, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
 
   template <typename T, bool CHECKCAST>
   bool arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound,
-                        bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
+                        bool satb, bool disjoint, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
 
   template <typename T, bool CHECKCAST, bool SATB>
   bool arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound,
-                        ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
+                        bool disjoint, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode);
 
   template <typename T, bool CHECKCAST, bool SATB, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
-  bool arraycopy_loop(T* src, T* dst, size_t length, Klass* bound);
+  bool arraycopy_loop(T* src, T* dst, size_t length, Klass* bound, bool disjoint);
 
   template <typename T, bool CHECKCAST, bool SATB, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
   bool arraycopy_element(T* cur_src, T* cur_dst, Klass* bound, Thread* thread);
diff -r 1e4229c1a99b -r 9c4bf4a86cd8 src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Fri Nov 09 12:49:43 2018 +0100
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Fri Nov 09 17:38:06 2018 -0500
@@ -93,34 +93,36 @@
 
 template <typename T>
 bool ShenandoahBarrierSet::arraycopy_loop_1(T* src, T* dst, size_t length, Klass* bound,
-                                            bool checkcast, bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
+                                            bool checkcast, bool satb, bool disjoint,
+                                            ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
   if (checkcast) {
-    return arraycopy_loop_2<T, true>(src, dst, length, bound, satb, storeval_mode);
+    return arraycopy_loop_2<T, true>(src, dst, length, bound, satb, disjoint, storeval_mode);
   } else {
-    return arraycopy_loop_2<T, false>(src, dst, length, bound, satb, storeval_mode);
+    return arraycopy_loop_2<T, false>(src, dst, length, bound, satb, disjoint, storeval_mode);
   }
 }
 
 template <typename T, bool CHECKCAST>
 bool ShenandoahBarrierSet::arraycopy_loop_2(T* src, T* dst, size_t length, Klass* bound,
-                                            bool satb, ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
+                                            bool satb, bool disjoint,
+                                            ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
   if (satb) {
-    return arraycopy_loop_3<T, CHECKCAST, true>(src, dst, length, bound, storeval_mode);
+    return arraycopy_loop_3<T, CHECKCAST, true>(src, dst, length, bound, disjoint, storeval_mode);
   } else {
-    return arraycopy_loop_3<T, CHECKCAST, false>(src, dst, length, bound, storeval_mode);
+    return arraycopy_loop_3<T, CHECKCAST, false>(src, dst, length, bound, disjoint, storeval_mode);
   }
 }
 
 template <typename T, bool CHECKCAST, bool SATB>
-bool ShenandoahBarrierSet::arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound,
+bool ShenandoahBarrierSet::arraycopy_loop_3(T* src, T* dst, size_t length, Klass* bound, bool disjoint,
                                             ShenandoahBarrierSet::ArrayCopyStoreValMode storeval_mode) {
   switch (storeval_mode) {
     case NONE:
-      return arraycopy_loop<T, CHECKCAST, SATB, NONE>(src, dst, length, bound);
+      return arraycopy_loop<T, CHECKCAST, SATB, NONE>(src, dst, length, bound, disjoint);
     case READ_BARRIER:
-      return arraycopy_loop<T, CHECKCAST, SATB, READ_BARRIER>(src, dst, length, bound);
+      return arraycopy_loop<T, CHECKCAST, SATB, READ_BARRIER>(src, dst, length, bound, disjoint);
     case WRITE_BARRIER:
-      return arraycopy_loop<T, CHECKCAST, SATB, WRITE_BARRIER>(src, dst, length, bound);
+      return arraycopy_loop<T, CHECKCAST, SATB, WRITE_BARRIER>(src, dst, length, bound, disjoint);
     default:
       ShouldNotReachHere();
       return true; // happy compiler
@@ -128,30 +130,30 @@
 }
 
 template <typename T, bool CHECKCAST, bool SATB, ShenandoahBarrierSet::ArrayCopyStoreValMode STOREVAL_MODE>
-bool ShenandoahBarrierSet::arraycopy_loop(T* src, T* dst, size_t length, Klass* bound) {
+bool ShenandoahBarrierSet::arraycopy_loop(T* src, T* dst, size_t length, Klass* bound, bool disjoint) {
   Thread* thread = Thread::current();
 
   ShenandoahEvacOOMScope oom_evac_scope;
 
   // We need to handle four cases:
   //
-  // a) src < dst, intersecting, can only copy backward only
+  // a) src < dst, conjoint, can only copy backward only
   //   [...src...]
   //         [...dst...]
   //
-  // b) src < dst, non-intersecting, can copy forward/backward
+  // b) src < dst, disjoint, can only copy forward, because types may mismatch
   //   [...src...]
   //              [...dst...]
   //
-  // c) src > dst, intersecting, can copy forward only
+  // c) src > dst, conjoint, can copy forward only
   //         [...src...]
   //   [...dst...]
   //
-  // d) src > dst, non-intersecting, can copy forward/backward
+  // d) src > dst, disjoint, can only copy forward, because types may mismatch
   //              [...src...]
   //   [...dst...]
   //
-  if (src > dst) {
+  if (src > dst || disjoint) {
     // copy forward:
     T* cur_src = src;
     T* cur_dst = dst;
@@ -248,6 +250,7 @@
 
   bool satb = ShenandoahSATBBarrier && heap->is_concurrent_mark_in_progress();
   bool checkcast = HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value;
+  bool disjoint = HasDecorator<decorators, ARRAYCOPY_DISJOINT>::value;
   ArrayCopyStoreValMode storeval_mode;
   if (heap->has_forwarded_objects()) {
     if (heap->is_concurrent_traversal_in_progress()) {
@@ -273,7 +276,7 @@
 
   Klass* bound = objArrayOop(dst_obj)->element_klass();
   ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
-  return bs->arraycopy_loop_1(src_raw, dst_raw, length, bound, checkcast, satb, storeval_mode);
+  return bs->arraycopy_loop_1(src_raw, dst_raw, length, bound, checkcast, satb, disjoint, storeval_mode);
 }
 
 #endif //SHARE_VM_GC_SHENANDOAH_SHENANDOAHBARRIERSET_INLINE_HPP
diff -r 1e4229c1a99b -r 9c4bf4a86cd8 test/hotspot/jtreg/gc/shenandoah/WrongArrayMember.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/shenandoah/WrongArrayMember.java	Fri Nov 09 17:38:06 2018 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. and/or its affiliates.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test WrongArrayMember
+ *
+ * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC                                      WrongArrayMember
+ * @run main/othervm -Xmx128m -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=traversal WrongArrayMember
+ */
+
+public class WrongArrayMember {
+    public static void main(String... args) throws Exception {
+        Object[] src = new Object[3];
+        src[0] = new Integer(0);
+        src[1] = new Object();
+        src[2] = new Object();
+        Object[] dst = new Integer[3];
+        dst[0] = new Integer(1);
+        dst[1] = new Integer(2);
+        dst[2] = new Integer(3);
+        try {
+            System.arraycopy(src, 0, dst, 0, 3);
+            throw new RuntimeException("Expected ArrayStoreException");
+        } catch (ArrayStoreException e) {
+            if (src[0] != dst[0]) {
+                throw new RuntimeException("First element not copied");
+            } else if (src[1] == dst[1] || src[2] == dst[2]) {
+                throw new RuntimeException("Second and third elements are affected");
+            } else {
+                return; // Passed!
+            }
+        }
+    }
+}
+