1 /* 2 * Copyright (c) 2017, 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.valuetypes; 25 26 import jdk.test.lib.Asserts; 27 28 /* 29 * @test 30 * @summary Test value type arrays 31 * @library /testlibrary /test/lib /compiler/whitebox / 32 * @requires os.simpleArch == "x64" 33 * @modules java.base/jdk.experimental.bytecode 34 * java.base/jdk.experimental.value 35 * java.base/jdk.internal.misc:+open 36 * jdk.incubator.mvt 37 * @compile -XDenableValueTypes TestArrays.java 38 * @run main ClassFileInstaller sun.hotspot.WhiteBox 39 * @run main ClassFileInstaller jdk.test.lib.Platform 40 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 41 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline 42 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 43 * -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 44 * compiler.valhalla.valuetypes.TestArrays 45 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 46 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops 47 * -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 48 * -XX:ValueFieldMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 49 * compiler.valhalla.valuetypes.TestArrays 50 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 51 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:-UseCompressedOops 52 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:-ValueArrayFlatten 53 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0 54 * -DVerifyIR=false compiler.valhalla.valuetypes.TestArrays 55 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 56 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+AlwaysIncrementalInline 57 * -XX:+EnableValhalla -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:-ValueArrayFlatten 58 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=0 -XX:ValueArrayElemMaxFlatOops=0 59 * -DVerifyIR=false compiler.valhalla.valuetypes.TestArrays 60 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -ea -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 61 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI 62 * -XX:+EnableValhalla -XX:+ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:+ValueArrayFlatten 63 * -XX:ValueFieldMaxFlatSize=0 -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueArrayElemMaxFlatOops=-1 64 * -DVerifyIR=false compiler.valhalla.valuetypes.TestArrays 65 */ 66 public class TestArrays extends ValueTypeTest { 67 68 public static void main(String[] args) throws Throwable { 69 TestArrays test = new TestArrays(); 70 test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class); 71 } 72 73 // Helper methods 74 75 protected long hash() { 76 return hash(rI, rL); 77 } 78 79 protected long hash(int x, long y) { 80 return MyValue1.createWithFieldsInline(x, y).hash(); 81 } 82 83 // Test value type array creation and initialization 84 @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD)) 85 @Test(valid = ValueTypeArrayFlattenOn) 86 public MyValue1[] test1(int len) { 87 MyValue1[] va = new MyValue1[len]; 88 for (int i = 0; i < len; ++i) { 89 va[i] = MyValue1.createWithFieldsDontInline(rI, rL); 90 } 91 return va; 92 } 93 94 @DontCompile 95 public void test1_verifier(boolean warmup) { 96 int len = Math.abs(rI % 10); 97 MyValue1[] va = test1(len); 98 for (int i = 0; i < len; ++i) { 99 Asserts.assertEQ(va[i].hash(), hash()); 100 } 101 } 102 103 // Test creation of a value type array and element access 104 @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOOP + TRAP)) 105 @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOC + ALLOCA + LOOP + LOAD + LOADP + STORE + TRAP)) 106 public long test2() { 107 MyValue1[] va = new MyValue1[1]; 108 va[0] = MyValue1.createWithFieldsInline(rI, rL); 109 return va[0].hash(); 110 } 111 112 @DontCompile 113 public void test2_verifier(boolean warmup) { 114 long result = test2(); 115 Asserts.assertEQ(result, hash()); 116 } 117 118 // Test receiving a value type array from the interpreter, 119 // updating its elements in a loop and computing a hash. 120 @Test(failOn = (ALLOCA)) 121 public long test3(MyValue1[] va) { 122 long result = 0; 123 for (int i = 0; i < 10; ++i) { 124 result += va[i].hash(); 125 va[i] = MyValue1.createWithFieldsInline(rI + 1, rL + 1); 126 } 127 return result; 128 } 129 130 @DontCompile 131 public void test3_verifier(boolean warmup) { 132 MyValue1[] va = new MyValue1[10]; 133 long expected = 0; 134 for (int i = 0; i < 10; ++i) { 135 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i); 136 expected += va[i].hash(); 137 } 138 long result = test3(va); 139 Asserts.assertEQ(expected, result); 140 for (int i = 0; i < 10; ++i) { 141 if (va[i].hash() != hash(rI + 1, rL + 1)) { 142 Asserts.assertEQ(va[i].hash(), hash(rI + 1, rL + 1)); 143 } 144 } 145 } 146 147 // Test returning a value type array received from the interpreter 148 @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP) 149 public MyValue1[] test4(MyValue1[] va) { 150 return va; 151 } 152 153 @DontCompile 154 public void test4_verifier(boolean warmup) { 155 MyValue1[] va = new MyValue1[10]; 156 for (int i = 0; i < 10; ++i) { 157 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i); 158 } 159 va = test4(va); 160 for (int i = 0; i < 10; ++i) { 161 Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i)); 162 } 163 } 164 165 // Merge value type arrays created from two branches 166 @Test 167 public MyValue1[] test5(boolean b) { 168 MyValue1[] va; 169 if (b) { 170 va = new MyValue1[5]; 171 for (int i = 0; i < 5; ++i) { 172 va[i] = MyValue1.createWithFieldsInline(rI, rL); 173 } 174 } else { 175 va = new MyValue1[10]; 176 for (int i = 0; i < 10; ++i) { 177 va[i] = MyValue1.createWithFieldsInline(rI + i, rL + i); 178 } 179 } 180 long sum = va[0].hashInterpreted(); 181 if (b) { 182 va[0] = MyValue1.createWithFieldsDontInline(rI, sum); 183 } else { 184 va[0] = MyValue1.createWithFieldsDontInline(rI + 1, sum + 1); 185 } 186 return va; 187 } 188 189 @DontCompile 190 public void test5_verifier(boolean warmup) { 191 MyValue1[] va = test5(true); 192 Asserts.assertEQ(va.length, 5); 193 Asserts.assertEQ(va[0].hash(), hash(rI, hash())); 194 for (int i = 1; i < 5; ++i) { 195 Asserts.assertEQ(va[i].hash(), hash()); 196 } 197 va = test5(false); 198 Asserts.assertEQ(va.length, 10); 199 Asserts.assertEQ(va[0].hash(), hash(rI + 1, hash(rI, rL) + 1)); 200 for (int i = 1; i < 10; ++i) { 201 Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i)); 202 } 203 } 204 205 // Test creation of value type array with single element 206 @Test(valid = ValueTypeArrayFlattenOff, failOn = (LOAD + LOOP + TRAP)) 207 @Test(valid = ValueTypeArrayFlattenOn, failOn = (ALLOCA + LOAD + LOOP + TRAP)) 208 public MyValue1 test6() { 209 MyValue1[] va = new MyValue1[1]; 210 return va[0]; 211 } 212 213 @DontCompile 214 public void test6_verifier(boolean warmup) { 215 MyValue1[] va = new MyValue1[1]; 216 MyValue1 v = test6(); 217 Asserts.assertEQ(v.hashPrimitive(), va[0].hashPrimitive()); 218 } 219 220 // Test default initialization of value type arrays 221 @Test(failOn = LOAD) 222 public MyValue1[] test7(int len) { 223 return new MyValue1[len]; 224 } 225 226 @DontCompile 227 public void test7_verifier(boolean warmup) { 228 int len = Math.abs(rI % 10); 229 MyValue1[] va = new MyValue1[len]; 230 MyValue1[] var = test7(len); 231 for (int i = 0; i < len; ++i) { 232 Asserts.assertEQ(va[i].hashPrimitive(), var[i].hashPrimitive()); 233 } 234 } 235 236 // Test creation of value type array with zero length 237 @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP) 238 public MyValue1[] test8() { 239 return new MyValue1[0]; 240 } 241 242 @DontCompile 243 public void test8_verifier(boolean warmup) { 244 MyValue1[] va = test8(); 245 Asserts.assertEQ(va.length, 0); 246 } 247 248 static MyValue1[] test9_va; 249 250 // Test that value type array loaded from field has correct type 251 @Test(failOn = (LOOP)) 252 public long test9() { 253 return test9_va[0].hash(); 254 } 255 256 @DontCompile 257 public void test9_verifier(boolean warmup) { 258 test9_va = new MyValue1[1]; 259 test9_va[0] = MyValue1.createWithFieldsInline(rI, rL); 260 long result = test9(); 261 Asserts.assertEQ(result, hash()); 262 } 263 264 // Multi-dimensional arrays 265 @Test 266 public MyValue1[][][] test10(int len1, int len2, int len3) { 267 MyValue1[][][] arr = new MyValue1[len1][len2][len3]; 268 for (int i = 0; i < len1; i++) { 269 for (int j = 0; j < len2; j++) { 270 for (int k = 0; k < len3; k++) { 271 arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i , rL + j + k); 272 } 273 } 274 } 275 return arr; 276 } 277 278 @DontCompile 279 public void test10_verifier(boolean warmup) { 280 MyValue1[][][] arr = test10(2, 3, 4); 281 for (int i = 0; i < 2; i++) { 282 for (int j = 0; j < 3; j++) { 283 for (int k = 0; k < 4; k++) { 284 Asserts.assertEQ(arr[i][j][k].hash(), MyValue1.createWithFieldsDontInline(rI + i , rL + j + k).hash()); 285 } 286 } 287 } 288 } 289 290 @Test 291 public void test11(MyValue1[][][] arr, long[] res) { 292 int l = 0; 293 for (int i = 0; i < arr.length; i++) { 294 for (int j = 0; j < arr[i].length; j++) { 295 for (int k = 0; k < arr[i][j].length; k++) { 296 res[l] = arr[i][j][k].hash(); 297 l++; 298 } 299 } 300 } 301 } 302 303 @DontCompile 304 public void test11_verifier(boolean warmup) { 305 MyValue1[][][] arr = new MyValue1[2][3][4]; 306 long[] res = new long[2*3*4]; 307 long[] verif = new long[2*3*4]; 308 int l = 0; 309 for (int i = 0; i < 2; i++) { 310 for (int j = 0; j < 3; j++) { 311 for (int k = 0; k < 4; k++) { 312 arr[i][j][k] = MyValue1.createWithFieldsDontInline(rI + i, rL + j + k); 313 verif[l] = arr[i][j][k].hash(); 314 l++; 315 } 316 } 317 } 318 test11(arr, res); 319 for (int i = 0; i < verif.length; i++) { 320 Asserts.assertEQ(res[i], verif[i]); 321 } 322 } 323 324 // Array load out of bounds (upper bound) at compile time 325 @Test 326 public int test12() { 327 int arraySize = Math.abs(rI) % 10;; 328 MyValue1[] va = new MyValue1[arraySize]; 329 330 for (int i = 0; i < arraySize; i++) { 331 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); 332 } 333 334 try { 335 return va[arraySize + 1].x; 336 } catch (ArrayIndexOutOfBoundsException e) { 337 return rI; 338 } 339 } 340 341 public void test12_verifier(boolean warmup) { 342 Asserts.assertEQ(test12(), rI); 343 } 344 345 // Array load out of bounds (lower bound) at compile time 346 @Test 347 public int test13() { 348 int arraySize = Math.abs(rI) % 10;; 349 MyValue1[] va = new MyValue1[arraySize]; 350 351 for (int i = 0; i < arraySize; i++) { 352 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL); 353 } 354 355 try { 356 return va[-arraySize].x; 357 } catch (ArrayIndexOutOfBoundsException e) { 358 return rI; 359 } 360 } 361 362 public void test13_verifier(boolean warmup) { 363 Asserts.assertEQ(test13(), rI); 364 } 365 366 // Array load out of bound not known to compiler (both lower and upper bound) 367 @Test 368 public int test14(MyValue1[] va, int index) { 369 return va[index].x; 370 } 371 372 public void test14_verifier(boolean warmup) { 373 int arraySize = Math.abs(rI) % 10; 374 MyValue1[] va = new MyValue1[arraySize]; 375 376 for (int i = 0; i < arraySize; i++) { 377 va[i] = MyValue1.createWithFieldsDontInline(rI, rL); 378 } 379 380 int result; 381 for (int i = -20; i < 20; i++) { 382 try { 383 result = test14(va, i); 384 } catch (ArrayIndexOutOfBoundsException e) { 385 result = rI; 386 } 387 Asserts.assertEQ(result, rI); 388 } 389 } 390 391 // Array store out of bounds (upper bound) at compile time 392 @Test 393 public int test15() { 394 int arraySize = Math.abs(rI) % 10;; 395 MyValue1[] va = new MyValue1[arraySize]; 396 397 try { 398 for (int i = 0; i <= arraySize; i++) { 399 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); 400 } 401 return rI - 1; 402 } catch (ArrayIndexOutOfBoundsException e) { 403 return rI; 404 } 405 } 406 407 public void test15_verifier(boolean warmup) { 408 Asserts.assertEQ(test15(), rI); 409 } 410 411 // Array store out of bounds (lower bound) at compile time 412 @Test 413 public int test16() { 414 int arraySize = Math.abs(rI) % 10;; 415 MyValue1[] va = new MyValue1[arraySize]; 416 417 try { 418 for (int i = -1; i <= arraySize; i++) { 419 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL); 420 } 421 return rI - 1; 422 } catch (ArrayIndexOutOfBoundsException e) { 423 return rI; 424 } 425 } 426 427 public void test16_verifier(boolean warmup) { 428 Asserts.assertEQ(test16(), rI); 429 } 430 431 // Array store out of bound not known to compiler (both lower and upper bound) 432 @Test 433 public int test17(MyValue1[] va, int index, MyValue1 vt) { 434 va[index] = vt; 435 return va[index].x; 436 } 437 438 @DontCompile 439 public void test17_verifier(boolean warmup) { 440 int arraySize = Math.abs(rI) % 10; 441 MyValue1[] va = new MyValue1[arraySize]; 442 443 for (int i = 0; i < arraySize; i++) { 444 va[i] = MyValue1.createWithFieldsDontInline(rI, rL); 445 } 446 447 MyValue1 vt = MyValue1.createWithFieldsDontInline(rI + 1, rL); 448 int result; 449 for (int i = -20; i < 20; i++) { 450 try { 451 result = test17(va, i, vt); 452 } catch (ArrayIndexOutOfBoundsException e) { 453 result = rI + 1; 454 } 455 Asserts.assertEQ(result, rI + 1); 456 } 457 458 for (int i = 0; i < arraySize; i++) { 459 Asserts.assertEQ(va[i].x, rI + 1); 460 } 461 } 462 }