1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8252506 27 * @summary Verify that arraycopy intrinsics properly handle flat inline type arrays with oop fields. 28 * @library /test/lib 29 * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* 30 * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* 31 * -Xbatch 32 * compiler.valhalla.inlinetypes.TestArrayCopyWithOops 33 * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* 34 * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* 35 * -Xbatch -XX:FlatArrayElementMaxSize=0 36 * compiler.valhalla.inlinetypes.TestArrayCopyWithOops 37 */ 38 39 package compiler.valhalla.inlinetypes; 40 41 import java.util.Arrays; 42 43 import jdk.test.lib.Asserts; 44 45 public class TestArrayCopyWithOops { 46 static final int LEN = 200; 47 48 static class MyObject { 49 long val = Integer.MAX_VALUE; 50 } 51 52 static primitive class ManyOops { 53 MyObject o1 = new MyObject(); 54 MyObject o2 = new MyObject(); 55 MyObject o3 = new MyObject(); 56 MyObject o4 = new MyObject(); 57 58 long hash() { 59 return o1.val + o2.val + o3.val + o4.val; 60 } 61 } 62 63 static ManyOops[] createArrayInline() { 64 ManyOops[] array = new ManyOops[LEN]; 65 for (int i = 0; i < LEN; ++i) { 66 array[i] = new ManyOops(); 67 } 68 return array; 69 } 70 71 static Object[] createArrayObject() { 72 return createArrayInline(); 73 } 74 75 static Object createObject() { 76 return createArrayInline(); 77 } 78 79 // System.arraycopy tests 80 81 static void test1(ManyOops[] dst) { 82 System.arraycopy(createArrayInline(), 0, dst, 0, LEN); 83 } 84 85 static void test2(Object[] dst) { 86 System.arraycopy(createArrayObject(), 0, dst, 0, LEN); 87 } 88 89 static void test3(ManyOops[] dst) { 90 System.arraycopy(createArrayObject(), 0, dst, 0, LEN); 91 } 92 93 static void test4(Object[] dst) { 94 System.arraycopy(createArrayInline(), 0, dst, 0, LEN); 95 } 96 97 // System.arraycopy tests (tightly coupled with allocation of dst array) 98 99 static Object[] test5() { 100 ManyOops[] dst = new ManyOops[LEN]; 101 System.arraycopy(createArrayInline(), 0, dst, 0, LEN); 102 return dst; 103 } 104 105 static Object[] test6() { 106 Object[] dst = new Object[LEN]; 107 System.arraycopy(createArrayObject(), 0, dst, 0, LEN); 108 return dst; 109 } 110 111 static Object[] test7() { 112 ManyOops[] dst = new ManyOops[LEN]; 113 System.arraycopy(createArrayObject(), 0, dst, 0, LEN); 114 return dst; 115 } 116 117 static Object[] test8() { 118 Object[] dst = new Object[LEN]; 119 System.arraycopy(createArrayInline(), 0, dst, 0, LEN); 120 return dst; 121 } 122 123 // Arrays.copyOf tests 124 125 static Object[] test9() { 126 return Arrays.copyOf(createArrayInline(), LEN, ManyOops[].class); 127 } 128 129 static Object[] test10() { 130 return Arrays.copyOf(createArrayObject(), LEN, Object[].class); 131 } 132 133 static Object[] test11() { 134 return Arrays.copyOf(createArrayInline(), LEN, ManyOops[].class); 135 } 136 137 static Object[] test12() { 138 return Arrays.copyOf(createArrayObject(), LEN, Object[].class); 139 } 140 141 // System.arraycopy test using generic_copy stub 142 143 static void test13(Object dst) { 144 System.arraycopy(createObject(), 0, dst, 0, LEN); 145 } 146 147 static void produceGarbage() { 148 for (int i = 0; i < 100; ++i) { 149 Object[] arrays = new Object[1024]; 150 for (int j = 0; j < arrays.length; j++) { 151 arrays[i] = new int[1024]; 152 } 153 } 154 System.gc(); 155 } 156 157 public static void main(String[] args) { 158 ManyOops[] dst1 = createArrayInline(); 159 ManyOops[] dst2 = createArrayInline(); 160 ManyOops[] dst3 = createArrayInline(); 161 ManyOops[] dst4 = createArrayInline(); 162 ManyOops[] dst13 = createArrayInline(); 163 164 // Warmup runs to trigger compilation 165 for (int i = 0; i < 50_000; ++i) { 166 test1(dst1); 167 test2(dst2); 168 test3(dst3); 169 test4(dst4); 170 test5(); 171 test6(); 172 test7(); 173 test8(); 174 test9(); 175 test10(); 176 test11(); 177 test12(); 178 test13(dst13); 179 } 180 181 // Trigger GC to make sure dst arrays are moved to old gen 182 produceGarbage(); 183 184 // Move data from flat src to flat dest 185 test1(dst1); 186 test2(dst2); 187 test3(dst3); 188 test4(dst4); 189 Object[] dst5 = test5(); 190 Object[] dst6 = test6(); 191 Object[] dst7 = test7(); 192 Object[] dst8 = test8(); 193 Object[] dst9 = test9(); 194 Object[] dst10 = test10(); 195 Object[] dst11 = test11(); 196 Object[] dst12 = test12(); 197 test13(dst13); 198 199 // Trigger GC again to make sure that the now dead src arrays are collected. 200 // MyObjects should be kept alive via oop references from the dst array. 201 produceGarbage(); 202 203 // Verify content 204 long expected = 4L*Integer.MAX_VALUE; 205 for (int i = 0; i < LEN; ++i) { 206 Asserts.assertEquals(dst1[i].hash(), expected); 207 Asserts.assertEquals(dst2[i].hash(), expected); 208 Asserts.assertEquals(dst3[i].hash(), expected); 209 Asserts.assertEquals(dst4[i].hash(), expected); 210 Asserts.assertEquals(((ManyOops)dst5[i]).hash(), expected); 211 Asserts.assertEquals(((ManyOops)dst7[i]).hash(), expected); 212 Asserts.assertEquals(((ManyOops)dst8[i]).hash(), expected); 213 Asserts.assertEquals(((ManyOops)dst8[i]).hash(), expected); 214 Asserts.assertEquals(((ManyOops)dst9[i]).hash(), expected); 215 Asserts.assertEquals(((ManyOops)dst10[i]).hash(), expected); 216 Asserts.assertEquals(((ManyOops)dst11[i]).hash(), expected); 217 Asserts.assertEquals(((ManyOops)dst12[i]).hash(), expected); 218 Asserts.assertEquals(dst13[i].hash(), expected); 219 } 220 } 221 }