1 /* 2 * Copyright (c) 2018, 2022, 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 /* 26 * @test 27 * @summary test VarHandle on primitive class array 28 * @run testng/othervm -XX:FlatArrayElementMaxSize=-1 ArrayElementVarHandleTest 29 * @run testng/othervm -XX:FlatArrayElementMaxSize=0 ArrayElementVarHandleTest 30 */ 31 32 import java.lang.invoke.*; 33 34 import org.testng.annotations.DataProvider; 35 import org.testng.annotations.Test; 36 import static org.testng.Assert.*; 37 38 public class ArrayElementVarHandleTest { 39 private static final Point P = Point.makePoint(10, 20); 40 private static final Line L = Line.makeLine(10, 20, 30, 40); 41 private static final MutablePath PATH = MutablePath.makePath(10, 20, 30, 40); 42 43 private static final Point[] POINTS = new Point[]{ 44 Point.makePoint(1, 2), 45 Point.makePoint(10, 20), 46 Point.makePoint(100, 200) 47 }; 48 49 private static final Point.ref[] NULL_POINTS = new Point.ref[]{ 50 Point.makePoint(11, 22), 51 Point.makePoint(110, 220), 52 null 53 }; 54 55 private static final Line[] LINES = new Line[]{ 56 Line.makeLine(1, 2, 3, 4), 57 Line.makeLine(10, 20, 30, 40), 58 Line.makeLine(15, 25, 35, 45), 59 Line.makeLine(20, 30, 40, 50) 60 }; 61 62 private static final Line.ref[] NULL_LINES = new Line.ref[] { null, null }; 63 64 private static final NonFlattenValue[] NFV_ARRAY = new NonFlattenValue[]{ 65 NonFlattenValue.make(1, 2), 66 NonFlattenValue.make(10, 20), 67 NonFlattenValue.make(100, 200) 68 }; 69 70 private static final ValueOptional[] VALUES = new ValueOptional[]{ 71 new ValueOptional(null), 72 new ValueOptional(P), 73 null 74 }; 75 76 @DataProvider(name="data") 77 static Object[][] data() throws Throwable { 78 int plen = POINTS.length; 79 int llen = LINES.length; 80 int vlen = VALUES.length; 81 return new Object[][]{ 82 // Point[] <: Point.ref[] <: Object[] 83 new Object[] { newArray(Object[].class, plen), POINTS }, 84 new Object[] { newArray(Object[].class, plen), NULL_POINTS }, 85 new Object[] { newArray(Object[].class, plen), new Object[] { "abc", Point.makePoint(1, 2) } }, 86 new Object[] { newArray(Point.ref[].class, plen), NULL_POINTS }, 87 new Object[] { newArray(Point[].class, plen), POINTS }, 88 new Object[] { new Point.ref[plen], POINTS }, 89 new Object[] { new Point.ref[plen], NULL_POINTS }, 90 new Object[] { new Point[plen], POINTS }, 91 92 // Line[] <: Line.ref[] 93 new Object[] { newArray(Object[].class, llen), LINES }, 94 new Object[] { newArray(Object[].class, llen), NULL_LINES }, 95 new Object[] { newArray(Object[].class, llen), LINES }, 96 new Object[] { newArray(Line.ref[].class, llen), NULL_LINES }, 97 new Object[] { newArray(Line[].class, llen), LINES }, 98 new Object[] { new Line.ref[llen], LINES }, 99 new Object[] { new Line.ref[llen], NULL_LINES }, 100 new Object[] { new Line[llen], LINES }, 101 102 // value class 103 new Object[] { newArray(Object[].class, vlen), VALUES }, 104 new Object[] { newArray(ValueOptional[].class, vlen), VALUES }, 105 new Object[] { new ValueOptional[vlen], VALUES }, 106 107 // non flattened values 108 new Object[] { newArray(NonFlattenValue[].class, NFV_ARRAY.length), NFV_ARRAY }, 109 new Object[] { new NonFlattenValue[NFV_ARRAY.length], NFV_ARRAY } 110 }; 111 } 112 113 /* 114 * Test VarHandle to set elements of the given array with 115 * various access mode. 116 */ 117 @Test(dataProvider = "data") 118 public void testSetArrayElements(Object[] array, Object[] data) throws Throwable { 119 setElements(array, data); 120 } 121 122 /* 123 * Constructs a new array of the specified type and size using 124 * MethodHandle. 125 */ 126 static Object[] newArray(Class<?> arrayType, int size) throws Throwable { 127 MethodHandle ctor = MethodHandles.arrayConstructor(arrayType); 128 return (Object[]) ctor.invoke(size); 129 } 130 131 /* 132 * Sets the given array with the given elements. 133 * This tests several VarHandle access mode. 134 */ 135 void setElements(Object[] array, Object[] elements) { 136 Class<?> arrayType = array.getClass(); 137 assertTrue(array.length >= elements.length); 138 139 VarHandle vh = MethodHandles.arrayElementVarHandle(arrayType); 140 set(vh, array.clone(), elements); 141 setVolatile(vh, array.clone(), elements); 142 setOpaque(vh, array.clone(), elements); 143 setRelease(vh, array.clone(), elements); 144 getAndSet(vh, array.clone(), elements); 145 compareAndSet(vh, array.clone(), elements); 146 compareAndExchange(vh, array.clone(), elements); 147 } 148 149 // VarHandle::set 150 void set(VarHandle vh, Object[] array, Object[] elements) { 151 for (int i = 0; i < elements.length; i++) { 152 vh.set(array, i, elements[i]); 153 } 154 for (int i = 0; i < elements.length; i++) { 155 Object v = (Object) vh.get(array, i); 156 assertEquals(v, elements[i]); 157 } 158 } 159 160 // VarHandle::setVolatile 161 void setVolatile(VarHandle vh, Object[] array, Object[] elements) { 162 for (int i = 0; i < elements.length; i++) { 163 vh.setVolatile(array, i, elements[i]); 164 } 165 for (int i = 0; i < elements.length; i++) { 166 Object v = (Object) vh.getVolatile(array, i); 167 assertEquals(v, elements[i]); 168 } 169 } 170 171 // VarHandle::setOpaque 172 void setOpaque(VarHandle vh, Object[] array, Object[] elements) { 173 for (int i = 0; i < elements.length; i++) { 174 vh.setOpaque(array, i, elements[i]); 175 } 176 for (int i = 0; i < elements.length; i++) { 177 Object v = (Object) vh.getOpaque(array, i); 178 assertEquals(v, elements[i]); 179 } 180 } 181 182 // VarHandle::setRelease 183 void setRelease(VarHandle vh, Object[] array, Object[] elements) { 184 for (int i = 0; i < elements.length; i++) { 185 vh.setRelease(array, i, elements[i]); 186 } 187 for (int i = 0; i < elements.length; i++) { 188 Object v = (Object) vh.getAcquire(array, i); 189 assertEquals(v, elements[i]); 190 } 191 } 192 193 void getAndSet(VarHandle vh, Object[] array, Object[] elements) { 194 for (int i = 0; i < elements.length; i++) { 195 Object o = vh.getAndSet(array, i, elements[i]); 196 } 197 for (int i = 0; i < elements.length; i++) { 198 Object v = (Object) vh.get(array, i); 199 assertEquals(v, elements[i]); 200 } 201 } 202 203 // sanity CAS test 204 // see test/jdk/java/lang/invoke/VarHandles tests 205 void compareAndSet(VarHandle vh, Object[] array, Object[] elements) { 206 // initialize to some values 207 for (int i = 0; i < elements.length; i++) { 208 vh.set(array, i, elements[i]); 209 } 210 // shift to the right element 211 for (int i = 0; i < elements.length; i++) { 212 Object v = elements[i + 1 < elements.length ? i + 1 : 0]; 213 boolean cas = vh.compareAndSet(array, i, elements[i], v); 214 if (!cas) 215 System.out.format("cas = %s array[%d] = %s vs old = %s new = %s%n", cas, i, array[i], elements[i], v); 216 assertTrue(cas); 217 } 218 } 219 220 void compareAndExchange(VarHandle vh, Object[] array, Object[] elements) { 221 // initialize to some values 222 for (int i = 0; i < elements.length; i++) { 223 vh.set(array, i, elements[i]); 224 } 225 // shift to the right element 226 for (int i = 0; i < elements.length; i++) { 227 Object v = elements[i + 1 < elements.length ? i + 1 : 0]; 228 assertEquals(vh.compareAndExchange(array, i, elements[i], v), elements[i]); 229 } 230 } 231 }