1 /* 2 * Copyright (c) 2019, 2024, 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 package compiler.valhalla.inlinetypes; 25 26 import compiler.lib.ir_framework.CompLevel; 27 import compiler.lib.ir_framework.Run; 28 import compiler.lib.ir_framework.Scenario; 29 import compiler.lib.ir_framework.Test; 30 import jdk.test.lib.Asserts; 31 32 import jdk.internal.value.ValueClass; 33 import jdk.internal.vm.annotation.ImplicitlyConstructible; 34 import jdk.internal.vm.annotation.LooselyConsistentValue; 35 import jdk.internal.vm.annotation.NullRestricted; 36 37 import static compiler.valhalla.inlinetypes.InlineTypes.rI; 38 import static compiler.valhalla.inlinetypes.InlineTypes.rL; 39 40 /* 41 * @test 42 * @key randomness 43 * @summary Various tests that are specific to C1. 44 * @library /test/lib / 45 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") 46 * @enablePreview 47 * @modules java.base/jdk.internal.value 48 * java.base/jdk.internal.vm.annotation 49 * @run main/othervm/timeout=300 compiler.valhalla.inlinetypes.TestC1 50 */ 51 52 public class TestC1 { 53 public static void main(String[] args) { 54 final Scenario[] scenarios = { 55 // C1 only 56 new Scenario(0, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"), 57 // C2 only. (Make sure the tests are correctly written) 58 new Scenario(1, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation"), 59 // interpreter only 60 new Scenario(2, "-Xint"), 61 // Xcomp Only C1. 62 new Scenario(3, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"), 63 // Xcomp Only C2. 64 new Scenario(4, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp") 65 }; 66 67 InlineTypes.getFramework() 68 .addScenarios(scenarios) 69 .addFlags("--enable-preview", 70 "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED", 71 "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED") 72 .addHelperClasses(MyValue1.class, 73 MyValue2.class, 74 MyValue2Inline.class, 75 MyValue3.class, 76 MyValue3Inline.class) 77 .start(); 78 } 79 80 // JDK-8229799 81 @Test(compLevel = CompLevel.C1_SIMPLE) 82 public long test1(Object a, Object b, long n) { 83 long r; 84 n += (a == b) ? 0x5678123456781234L : 0x1234567812345678L; 85 n -= 1; 86 return n; 87 } 88 89 @Run(test = "test1") 90 public void test1_verifier() { 91 MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL); 92 MyValue1 v2 = MyValue1.createWithFieldsInline(rI, rL+1); 93 long r1 = test1(v1, v1, 1); 94 long r2 = test1(v1, v2, 1); 95 Asserts.assertEQ(r1, 0x5678123456781234L); 96 Asserts.assertEQ(r2, 0x1234567812345678L); 97 } 98 99 @ImplicitlyConstructible 100 @LooselyConsistentValue 101 static value class SimpleValue2 { 102 int value; 103 104 SimpleValue2(int value) { 105 this.value = value; 106 } 107 } 108 109 // JDK-8231961 110 // Test that the value numbering optimization does not remove 111 // the second load from the buffered array element. 112 @Test(compLevel = CompLevel.C1_SIMPLE) 113 public int test2(SimpleValue2[] array) { 114 return array[0].value + array[0].value; 115 } 116 117 @Run(test = "test2") 118 public void test2_verifier() { 119 SimpleValue2[] array = (SimpleValue2[])ValueClass.newNullRestrictedArray(SimpleValue2.class, 1); 120 array[0] = new SimpleValue2(rI); 121 int result = test2(array); 122 Asserts.assertEQ(result, 2*rI); 123 } 124 125 126 // Tests below (3 to 8) check the behavior of the C1 optimization to access 127 // sub-elements of a flattened array without copying the element first 128 129 // Test access to a null array 130 @Test(compLevel = CompLevel.C1_SIMPLE) 131 public int test3(MyValue2[] array, int index) { 132 return array[index].x; 133 } 134 135 @Run(test = "test3") 136 public void test3_verifier() { 137 NullPointerException npe = null; 138 try { 139 test3(null, 0); 140 } catch(NullPointerException e) { 141 npe = e; 142 } 143 Asserts.assertNE(npe, null); 144 } 145 146 // Test out of bound accesses 147 @Test(compLevel = CompLevel.C1_SIMPLE) 148 public int test4(MyValue2[] array, int index) { 149 return array[index].x; 150 } 151 152 @Run(test = "test4") 153 public void test4_verifier() { 154 MyValue2[] array = new MyValue2[2]; 155 ArrayIndexOutOfBoundsException aioob = null; 156 try { 157 test3(array, -1); 158 } catch(ArrayIndexOutOfBoundsException e) { 159 aioob = e; 160 } 161 Asserts.assertNE(aioob, null); 162 aioob = null; 163 try { 164 test3(array, 2); 165 } catch(ArrayIndexOutOfBoundsException e) { 166 aioob = e; 167 } 168 Asserts.assertNE(aioob, null); 169 } 170 171 // Test 1st level sub-element access to primitive field 172 @Test(compLevel = CompLevel.C1_SIMPLE) 173 public int test5(MyValue2[] array, int index) { 174 return array[index].x; 175 } 176 177 @Run(test = "test5") 178 public void test5_verifier() { 179 MyValue2[] array = new MyValue2[2]; 180 MyValue2 v = new MyValue2(1,(byte)2, new MyValue2Inline(5.0d, 345L)); 181 array[1] = v; 182 int x = test5(array, 1); 183 Asserts.assertEQ(x, 1); 184 } 185 186 // Test 1st level sub-element access to flattened field 187 @Test(compLevel = CompLevel.C1_SIMPLE) 188 public MyValue2Inline test6(MyValue2[] array, int index) { 189 return array[index].v; 190 } 191 192 @Run(test = "test6") 193 public void test6_verifier() { 194 MyValue2[] array = new MyValue2[2]; 195 MyValue2Inline vi = new MyValue2Inline(3.5d, 678L); 196 MyValue2 v = new MyValue2(1,(byte)2, vi); 197 array[0] = v; 198 MyValue2Inline vi2 = test6(array, 0); 199 Asserts.assertEQ(vi, vi2); 200 } 201 202 // Test 1st level sub-element access to non-flattened field 203 @ImplicitlyConstructible 204 @LooselyConsistentValue 205 static value class Big { 206 long l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19 ; 207 208 Big(long n) { 209 l0 = n++; l1 = n++; l2 = n++; l3 = n++; l4 = n++; l5 = n++; l6 = n++; l7 = n++; l8 = n++; 210 l9 = n++; l10 = n++; l11 = n++; l12 = n++; l13 = n++; l14 = n++; l15 = n++; l16= n++; 211 l17 = n++; l18 = n++; l19 = n++; 212 } 213 214 void check(long n, int i) { 215 Asserts.assertEQ(l0, n); n += i; 216 Asserts.assertEQ(l1, n); n += i; 217 Asserts.assertEQ(l2, n); n += i; 218 Asserts.assertEQ(l3, n); n += i; 219 Asserts.assertEQ(l4, n); n += i; 220 Asserts.assertEQ(l5, n); n += i; 221 Asserts.assertEQ(l6, n); n += i; 222 Asserts.assertEQ(l7, n); n += i; 223 Asserts.assertEQ(l8, n); n += i; 224 Asserts.assertEQ(l9, n); n += i; 225 Asserts.assertEQ(l10, n); n += i; 226 Asserts.assertEQ(l11, n); n += i; 227 Asserts.assertEQ(l12, n); n += i; 228 Asserts.assertEQ(l13, n); n += i; 229 Asserts.assertEQ(l14, n); n += i; 230 Asserts.assertEQ(l15, n); n += i; 231 Asserts.assertEQ(l16, n); n += i; 232 Asserts.assertEQ(l17, n); n += i; 233 Asserts.assertEQ(l18, n); n += i; 234 Asserts.assertEQ(l19, n); 235 } 236 } 237 238 @ImplicitlyConstructible 239 @LooselyConsistentValue 240 static value class TestValue { 241 int i; 242 @NullRestricted 243 Big big; 244 245 TestValue(int n) { 246 i = n; 247 big = new Big(n); 248 } 249 } 250 251 @Test(compLevel = CompLevel.C1_SIMPLE) 252 public Big test7(TestValue[] array, int index) { 253 return array[index].big; 254 } 255 256 @Run(test = "test7") 257 public void test7_verifier() { 258 TestValue[] array = (TestValue[])ValueClass.newNullRestrictedArray(TestValue.class, 7); 259 Big b0 = test7(array, 3); 260 b0.check(0, 0); 261 TestValue tv = new TestValue(9); 262 array[5] = tv; 263 Big b1 = test7(array, 5); 264 b1.check(9, 1); 265 } 266 267 // Test 2nd level sub-element access to primitive field 268 @Test(compLevel = CompLevel.C1_SIMPLE) 269 public byte test8(MyValue1[] array, int index) { 270 return array[index].v2.y; 271 } 272 273 @Run(test = "test8") 274 public void test8_verifier() { 275 MyValue1[] array = new MyValue1[23]; 276 MyValue2 mv2a = MyValue2.createWithFieldsInline(7, 63L, 8.9d); 277 MyValue2 mv2b = MyValue2.createWithFieldsInline(11, 69L, 17.3d); 278 MyValue1 mv1 = new MyValue1(1, 2L, (short)3, 4, null, mv2a, mv2b, mv2a, mv2b, 'z'); 279 array[19] = mv1; 280 byte b = test8(array, 19); 281 Asserts.assertEQ(b, (byte)11); 282 } 283 284 285 // Test optimizations for arrays of empty types 286 // (read/write are not performed, pre-allocated instance is used for reads) 287 // Most tests check that error conditions are still correctly handled 288 // (OOB, null pointer) 289 @ImplicitlyConstructible 290 @LooselyConsistentValue 291 static value class EmptyType {} 292 293 @Test(compLevel = CompLevel.C1_SIMPLE) 294 public EmptyType test9() { 295 EmptyType[] array = (EmptyType[])ValueClass.newNullRestrictedArray(EmptyType.class, 10); 296 return array[4]; 297 } 298 299 @Run(test = "test9") 300 public void test9_verifier() { 301 EmptyType et = test9(); 302 Asserts.assertEQ(et, new EmptyType()); 303 } 304 305 @Test(compLevel = CompLevel.C1_SIMPLE) 306 public EmptyType test10(EmptyType[] array) { 307 return array[0]; 308 } 309 310 @Run(test = "test10") 311 public void test10_verifier() { 312 EmptyType[] array = (EmptyType[])ValueClass.newNullRestrictedArray(EmptyType.class, 16); 313 EmptyType et = test10(array); 314 Asserts.assertEQ(et, new EmptyType()); 315 } 316 317 @Test(compLevel = CompLevel.C1_SIMPLE) 318 public EmptyType test11(EmptyType[] array, int index) { 319 return array[index]; 320 } 321 322 @Run(test = "test11") 323 public void test11_verifier() { 324 Exception e = null; 325 EmptyType[] array = (EmptyType[])ValueClass.newNullRestrictedArray(EmptyType.class, 10); 326 try { 327 EmptyType et = test11(array, 11); 328 } catch (ArrayIndexOutOfBoundsException ex) { 329 e = ex; 330 } 331 Asserts.assertNotNull(e); 332 e = null; 333 try { 334 EmptyType et = test11(array, -1); 335 } catch (ArrayIndexOutOfBoundsException ex) { 336 e = ex; 337 } 338 Asserts.assertNotNull(e); 339 e = null; 340 try { 341 EmptyType et = test11(null, 1); 342 } catch (NullPointerException ex) { 343 e = ex; 344 } 345 Asserts.assertNotNull(e); 346 } 347 348 @Test(compLevel = CompLevel.C1_SIMPLE) 349 public void test12(EmptyType[] array, int index, EmptyType value) { 350 array[index] = value; 351 } 352 353 @Run(test = "test12") 354 public void test12_verifier() { 355 EmptyType empty = new EmptyType(); 356 EmptyType[] array = (EmptyType[])ValueClass.newNullRestrictedArray(EmptyType.class, 16); 357 test12(array, 2, empty); 358 Exception e = null; 359 try { 360 test12(null, 2, empty); 361 } catch(NullPointerException ex) { 362 e = ex; 363 } 364 Asserts.assertNotNull(e); 365 e = null; 366 try { 367 test12(array, 17, empty); 368 } catch(ArrayIndexOutOfBoundsException ex) { 369 e = ex; 370 } 371 Asserts.assertNotNull(e); 372 e = null; 373 try { 374 test12(array, -8, empty); 375 } catch(ArrayIndexOutOfBoundsException ex) { 376 e = ex; 377 } 378 Asserts.assertNotNull(e); 379 } 380 }