549 // Print ideal graph after execution of each test
550 private static final boolean PRINT_GRAPH = true;
551
552 // Random test values
553 public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
554 public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
555
556 public ValueTypeTestBench() {
557 val3 = MyValue1.createWithFieldsInline(rI, rL);
558 }
559
560 // MethodHandles and value-capable class instance needed for testing vbox/vunbox
561 private static final MethodHandle vccUnboxLoadLongMH = generateVCCUnboxLoadLongMH();
562 private static final MethodHandle vccUnboxLoadIntMH = generateVCCUnboxLoadIntMH();
563 private static final MethodHandle vccUnboxBoxMH = generateVCCUnboxBoxMH();
564 private static final MethodHandle vccUnboxBoxLoadIntMH = generateVCCUnboxBoxLoadIntMH();
565 private static final MethodHandle nullvccUnboxLoadLongMH = generateNullVCCUnboxLoadLongMH();
566 private static final MethodHandle objectUnboxLoadLongMH = generateObjectUnboxLoadLongMH();
567 private static final MethodHandle objectBoxMH = generateObjectBoxMH();
568 private static final MethodHandle checkedvccUnboxLoadLongMH = generateCheckedVCCUnboxLoadLongMH();
569
570 private static final ValueCapableClass1 vcc = ValueCapableClass1.create(rL, rI, (short)rI, (short)rI);
571 private static final ValueCapableClass2 vcc2 = ValueCapableClass2.create(rL + 1);
572
573 // ========== Helper methods ==========
574
575 public long hash() {
576 return hash(rI, rL);
577 }
578
579 public long hash(int x, long y) {
580 return MyValue1.createWithFieldsInline(x, y).hash();
581 }
582
583 // ========== Test definitions ==========
584
585 // Receive value type through call to interpreter
586 @Test(failOn = ALLOC + STORE + TRAP)
587 public long test1() {
588 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
752 Asserts.assertEQ(result, hash(rI + 10, rL + 10));
753 }
754
755 // Merge value types created in a loop (inlined)
756 @Test(failOn = ALLOC + LOAD + STORE + TRAP)
757 public long test11(int x, long y) {
758 MyValue1 v = MyValue1.createWithFieldsInline(x, y);
759 for (int i = 0; i < 10; ++i) {
760 v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
761 }
762 return v.hash();
763 }
764
765 @DontCompile
766 public void test11_verifier(boolean warmup) {
767 long result = test11(rI, rL);
768 Asserts.assertEQ(result, hash(rI + 10, rL + 10));
769 }
770
771 // Test loop with uncommon trap referencing a value type
772 @Test(match = {TRAP, SCOBJ}, matchCount = {1, -1 /* at least 1 */}, failOn = LOAD)
773 public long test12(boolean b) {
774 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
775 MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
776 for (int i = 0; i < va.length; ++i) {
777 va[i] = MyValue1.createWithFieldsInline(rI, rL);
778 }
779 long result = rL;
780 for (int i = 0; i < 1000; ++i) {
781 if (b) {
782 result += v.x;
783 } else {
784 // Uncommon trap referencing v. We delegate allocation to the
785 // interpreter by adding a SafePointScalarObjectNode.
786 result = v.hashInterpreted();
787 for (int j = 0; j < va.length; ++j) {
788 result += va[j].hash();
789 }
790 }
791 }
792 return result;
793 }
794
795 @DontCompile
796 public void test12_verifier(boolean warmup) {
797 long result = test12(warmup);
798 Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
799 }
800
801 // Test loop with uncommon trap referencing a value type
802 @Test(match = {TRAP}, matchCount = {1})
803 public long test13(boolean b) {
804 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
805 MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
806 for (int i = 0; i < va.length; ++i) {
807 va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
808 }
809 long result = rL;
810 for (int i = 0; i < 1000; ++i) {
811 if (b) {
812 result += v.x;
813 } else {
814 // Uncommon trap referencing v. Should not allocate
815 // but just pass the existing oop to the uncommon trap.
816 result = v.hashInterpreted();
817 for (int j = 0; j < va.length; ++j) {
818 result += va[j].hashInterpreted();
819 }
820 }
821 }
822 return result;
1420
1421 // Test returning a value type array received from the interpreter
1422 @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP)
1423 public MyValue1[] test44(MyValue1[] va) {
1424 return va;
1425 }
1426
1427 @DontCompile
1428 public void test44_verifier(boolean warmup) {
1429 MyValue1[] va = new MyValue1[10];
1430 for (int i = 0; i < 10; ++i) {
1431 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1432 }
1433 va = test44(va);
1434 for (int i = 0; i < 10; ++i) {
1435 Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1436 }
1437 }
1438
1439 // Merge value type arrays created from two branches
1440 @Test(failOn = (TRAP))
1441 public MyValue1[] test45(boolean b) {
1442 MyValue1[] va;
1443 if (b) {
1444 va = new MyValue1[5];
1445 for (int i = 0; i < 5; ++i) {
1446 va[i] = MyValue1.createWithFieldsInline(rI, rL);
1447 }
1448 } else {
1449 va = new MyValue1[10];
1450 for (int i = 0; i < 10; ++i) {
1451 va[i] = MyValue1.createWithFieldsInline(rI + i, rL + i);
1452 }
1453 }
1454 long sum = va[0].hashInterpreted();
1455 if (b) {
1456 va[0] = MyValue1.createWithFieldsDontInline(rI, sum);
1457 } else {
1458 va[0] = MyValue1.createWithFieldsDontInline(rI + 1, sum + 1);
1459 }
1460 return va;
2144 }
2145
2146 @DontCompile
2147 public void test76_verifier(boolean warmup) throws Exception {
2148 MyValue3 vt = test76();
2149 test76_vt.verify(vt);
2150 }
2151
2152 static {
2153 try {
2154 MethodHandles.Lookup lookup = MethodHandles.lookup();
2155 MethodType mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2156 test73_mh = lookup.findVirtual(ValueTypeTestBench.class, "test73_target", mt);
2157 test74_mh = lookup.findVirtual(ValueTypeTestBench.class, "test74_target", mt);
2158 test75_mh = lookup.findVirtual(ValueTypeTestBench.class, "test75_target", mt);
2159 } catch (NoSuchMethodException|IllegalAccessException e) {
2160 throw new RuntimeException("method handle lookup fails");
2161 }
2162 }
2163
2164 // ========== Test infrastructure ==========
2165
2166 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
2167 private static final int ValueTypePassFieldsAsArgsOn = 0x1;
2168 private static final int ValueTypePassFieldsAsArgsOff = 0x2;
2169 private static final int ValueTypeArrayFlattenOn = 0x4;
2170 private static final int ValueTypeArrayFlattenOff = 0x8;
2171 private static final int ValueTypeReturnedAsFieldsOn = 0x10;
2172 private static final int ValueTypeReturnedAsFieldsOff = 0x20;
2173 static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff | ValueTypeReturnedAsFieldsOn;
2174 private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
2175 private static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten");
2176 private static final boolean ValueTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("ValueTypeReturnedAsFields");
2177 private static final int COMP_LEVEL_ANY = -1;
2178 private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
2179 private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
2180 private static final int WARMUP = 251;
2181 private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
2182 private static boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
2183 private static boolean XCOMP = Platform.isComp();
2218 all_args.add(ValueTypeTestBench.class.getName());
2219 all_args.add("run");
2220 // Spawn process with default JVM options from the test's run command
2221 String[] vmInputArgs = InputArguments.getVmInputArgs();
2222 String[] cmds = Arrays.copyOf(vmInputArgs, vmInputArgs.length + all_args.size());
2223 System.arraycopy(all_args.toArray(), 0, cmds, vmInputArgs.length, all_args.size());
2224 OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);
2225 // If ideal graph printing is enabled/supported, verify output
2226 String output = oa.getOutput();
2227 oa.shouldHaveExitValue(0);
2228 boolean verifyIR = output.contains("PrintIdeal enabled") &&
2229 !output.contains("ValueTypePassFieldsAsArgs is not supported on this platform");
2230 if (verifyIR) {
2231 parseOutput(output);
2232 } else {
2233 System.out.println("WARNING: IR verification disabled! Running with -Xint, -Xcomp or release build?");
2234 }
2235 }
2236
2237 public static void main(String[] args) throws Throwable {
2238 //tests.values().removeIf(p -> !p.getName().equals("test74")); // Run single test
2239 if (args.length == 0) {
2240 execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation",
2241 "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
2242 "-XX:CICompilerCount=1",
2243 "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
2244 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*",
2245 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*",
2246 "-XX:CompileCommand=compileonly,java.lang.Object::<init>",
2247 "-XX:CompileCommand=inline,java.lang.__Value::hashCode",
2248 "-XX:CompileCommand=compileonly,java.lang.invoke.*::*");
2249 } else {
2250 // Execute tests
2251 ValueTypeTestBench bench = new ValueTypeTestBench();
2252 bench.run();
2253 }
2254 }
2255
2256 public static void parseOutput(String output) throws Exception {
2257 Pattern comp_re = Pattern.compile("\\n\\s+\\d+\\s+\\d+\\s+(%| )(s| )(!| )b(n| )\\s+\\S+\\.(?<name>[^.]+::\\S+)\\s+(?<osr>@ \\d+\\s+)?[(]\\d+ bytes[)]\\n");
2258 Matcher m = comp_re.matcher(output);
|
549 // Print ideal graph after execution of each test
550 private static final boolean PRINT_GRAPH = true;
551
552 // Random test values
553 public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
554 public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
555
556 public ValueTypeTestBench() {
557 val3 = MyValue1.createWithFieldsInline(rI, rL);
558 }
559
560 // MethodHandles and value-capable class instance needed for testing vbox/vunbox
561 private static final MethodHandle vccUnboxLoadLongMH = generateVCCUnboxLoadLongMH();
562 private static final MethodHandle vccUnboxLoadIntMH = generateVCCUnboxLoadIntMH();
563 private static final MethodHandle vccUnboxBoxMH = generateVCCUnboxBoxMH();
564 private static final MethodHandle vccUnboxBoxLoadIntMH = generateVCCUnboxBoxLoadIntMH();
565 private static final MethodHandle nullvccUnboxLoadLongMH = generateNullVCCUnboxLoadLongMH();
566 private static final MethodHandle objectUnboxLoadLongMH = generateObjectUnboxLoadLongMH();
567 private static final MethodHandle objectBoxMH = generateObjectBoxMH();
568 private static final MethodHandle checkedvccUnboxLoadLongMH = generateCheckedVCCUnboxLoadLongMH();
569 private static final MethodHandle vastoreMH = generateVastore();
570 private static final MethodHandle invalidVastoreMH = generateInvalidVastore();
571
572 private static final ValueCapableClass1 vcc = ValueCapableClass1.create(rL, rI, (short)rI, (short)rI);
573 private static final ValueCapableClass2 vcc2 = ValueCapableClass2.create(rL + 1);
574
575 // ========== Helper methods ==========
576
577 public long hash() {
578 return hash(rI, rL);
579 }
580
581 public long hash(int x, long y) {
582 return MyValue1.createWithFieldsInline(x, y).hash();
583 }
584
585 // ========== Test definitions ==========
586
587 // Receive value type through call to interpreter
588 @Test(failOn = ALLOC + STORE + TRAP)
589 public long test1() {
590 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
754 Asserts.assertEQ(result, hash(rI + 10, rL + 10));
755 }
756
757 // Merge value types created in a loop (inlined)
758 @Test(failOn = ALLOC + LOAD + STORE + TRAP)
759 public long test11(int x, long y) {
760 MyValue1 v = MyValue1.createWithFieldsInline(x, y);
761 for (int i = 0; i < 10; ++i) {
762 v = MyValue1.createWithFieldsInline(v.x + 1, v.y + 1);
763 }
764 return v.hash();
765 }
766
767 @DontCompile
768 public void test11_verifier(boolean warmup) {
769 long result = test11(rI, rL);
770 Asserts.assertEQ(result, hash(rI + 10, rL + 10));
771 }
772
773 // Test loop with uncommon trap referencing a value type
774 @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD)
775 public long test12(boolean b) {
776 MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
777 MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
778 for (int i = 0; i < va.length; ++i) {
779 va[i] = MyValue1.createWithFieldsInline(rI, rL);
780 }
781 long result = rL;
782 for (int i = 0; i < 1000; ++i) {
783 if (b) {
784 result += v.x;
785 } else {
786 // Uncommon trap referencing v. We delegate allocation to the
787 // interpreter by adding a SafePointScalarObjectNode.
788 result = v.hashInterpreted();
789 for (int j = 0; j < va.length; ++j) {
790 result += va[j].hash();
791 }
792 }
793 }
794 return result;
795 }
796
797 @DontCompile
798 public void test12_verifier(boolean warmup) {
799 long result = test12(warmup);
800 Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
801 }
802
803 // Test loop with uncommon trap referencing a value type
804 @Test
805 public long test13(boolean b) {
806 MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
807 MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
808 for (int i = 0; i < va.length; ++i) {
809 va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
810 }
811 long result = rL;
812 for (int i = 0; i < 1000; ++i) {
813 if (b) {
814 result += v.x;
815 } else {
816 // Uncommon trap referencing v. Should not allocate
817 // but just pass the existing oop to the uncommon trap.
818 result = v.hashInterpreted();
819 for (int j = 0; j < va.length; ++j) {
820 result += va[j].hashInterpreted();
821 }
822 }
823 }
824 return result;
1422
1423 // Test returning a value type array received from the interpreter
1424 @Test(failOn = ALLOC + ALLOCA + LOAD + LOADP + STORE + LOOP + TRAP)
1425 public MyValue1[] test44(MyValue1[] va) {
1426 return va;
1427 }
1428
1429 @DontCompile
1430 public void test44_verifier(boolean warmup) {
1431 MyValue1[] va = new MyValue1[10];
1432 for (int i = 0; i < 10; ++i) {
1433 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
1434 }
1435 va = test44(va);
1436 for (int i = 0; i < 10; ++i) {
1437 Asserts.assertEQ(va[i].hash(), hash(rI + i, rL + i));
1438 }
1439 }
1440
1441 // Merge value type arrays created from two branches
1442 @Test
1443 public MyValue1[] test45(boolean b) {
1444 MyValue1[] va;
1445 if (b) {
1446 va = new MyValue1[5];
1447 for (int i = 0; i < 5; ++i) {
1448 va[i] = MyValue1.createWithFieldsInline(rI, rL);
1449 }
1450 } else {
1451 va = new MyValue1[10];
1452 for (int i = 0; i < 10; ++i) {
1453 va[i] = MyValue1.createWithFieldsInline(rI + i, rL + i);
1454 }
1455 }
1456 long sum = va[0].hashInterpreted();
1457 if (b) {
1458 va[0] = MyValue1.createWithFieldsDontInline(rI, sum);
1459 } else {
1460 va[0] = MyValue1.createWithFieldsDontInline(rI + 1, sum + 1);
1461 }
1462 return va;
2146 }
2147
2148 @DontCompile
2149 public void test76_verifier(boolean warmup) throws Exception {
2150 MyValue3 vt = test76();
2151 test76_vt.verify(vt);
2152 }
2153
2154 static {
2155 try {
2156 MethodHandles.Lookup lookup = MethodHandles.lookup();
2157 MethodType mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader());
2158 test73_mh = lookup.findVirtual(ValueTypeTestBench.class, "test73_target", mt);
2159 test74_mh = lookup.findVirtual(ValueTypeTestBench.class, "test74_target", mt);
2160 test75_mh = lookup.findVirtual(ValueTypeTestBench.class, "test75_target", mt);
2161 } catch (NoSuchMethodException|IllegalAccessException e) {
2162 throw new RuntimeException("method handle lookup fails");
2163 }
2164 }
2165
2166 /* Array load out of bounds (upper bound) at compile time.*/
2167 @Test
2168 public int test77() {
2169 int arraySize = Math.abs(rI) % 10;;
2170 MyValue1[] va = new MyValue1[arraySize];
2171
2172 for (int i = 0; i < arraySize; i++) {
2173 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2174 }
2175
2176 try {
2177 return va[arraySize + 1].x;
2178 } catch (ArrayIndexOutOfBoundsException e) {
2179 return rI;
2180 }
2181 }
2182
2183 public void test77_verifier(boolean warmup) {
2184 Asserts.assertEQ(test77(), rI);
2185 }
2186
2187 /* Array load out of bounds (lower bound) at compile time.*/
2188 @Test
2189 public int test78() {
2190 int arraySize = Math.abs(rI) % 10;;
2191 MyValue1[] va = new MyValue1[arraySize];
2192
2193 for (int i = 0; i < arraySize; i++) {
2194 va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL);
2195 }
2196
2197 try {
2198 return va[-arraySize].x;
2199 } catch (ArrayIndexOutOfBoundsException e) {
2200 return rI;
2201 }
2202 }
2203
2204 public void test78_verifier(boolean warmup) {
2205 Asserts.assertEQ(test78(), rI);
2206 }
2207
2208 /* Array load out of bound not known to compiler (both lower and upper bound). */
2209 @Test
2210 public int test79(MyValue1[] va, int index) {
2211 return va[index].x;
2212 }
2213
2214 public void test79_verifier(boolean warmup) {
2215 int arraySize = Math.abs(rI) % 10;
2216 MyValue1[] va = new MyValue1[arraySize];
2217
2218 for (int i = 0; i < arraySize; i++) {
2219 va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
2220 }
2221
2222 int result;
2223 for (int i = -20; i < 20; i++) {
2224 try {
2225 result = test79(va, i);
2226 } catch (ArrayIndexOutOfBoundsException e) {
2227 result = rI;
2228 }
2229 Asserts.assertEQ(result, rI);
2230 }
2231 }
2232
2233 /* Array store out of bounds (upper bound) at compile time.*/
2234 @Test
2235 public int test80() {
2236 int arraySize = Math.abs(rI) % 10;;
2237 MyValue1[] va = new MyValue1[arraySize];
2238
2239 try {
2240 for (int i = 0; i <= arraySize; i++) {
2241 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2242 }
2243 return rI - 1;
2244 } catch (ArrayIndexOutOfBoundsException e) {
2245 return rI;
2246 }
2247 }
2248
2249 public void test80_verifier(boolean warmup) {
2250 Asserts.assertEQ(test80(), rI);
2251 }
2252
2253 /* Array store out of bounds (lower bound) at compile time.*/
2254 @Test
2255 public int test81() {
2256 int arraySize = Math.abs(rI) % 10;;
2257 MyValue1[] va = new MyValue1[arraySize];
2258
2259 try {
2260 for (int i = -1; i <= arraySize; i++) {
2261 va[i] = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2262 }
2263 return rI - 1;
2264 } catch (ArrayIndexOutOfBoundsException e) {
2265 return rI;
2266 }
2267 }
2268
2269 public void test81_verifier(boolean warmup) {
2270 Asserts.assertEQ(test81(), rI);
2271 }
2272
2273 /* Array store out of bound not known to compiler (both lower and upper bound). */
2274 @Test
2275 public int test82(MyValue1[] va, int index, MyValue1 vt) {
2276 va[index] = vt;
2277 return va[index].x;
2278 }
2279
2280 @DontCompile
2281 public void test82_verifier(boolean warmup) {
2282 int arraySize = Math.abs(rI) % 10;
2283 MyValue1[] va = new MyValue1[arraySize];
2284
2285 for (int i = 0; i < arraySize; i++) {
2286 va[i] = MyValue1.createWithFieldsDontInline(rI, rL);
2287 }
2288
2289 MyValue1 vt = MyValue1.createWithFieldsDontInline(rI + 1, rL);
2290 int result;
2291 for (int i = -20; i < 20; i++) {
2292 try {
2293 result = test82(va, i, vt);
2294 } catch (ArrayIndexOutOfBoundsException e) {
2295 result = rI + 1;
2296 }
2297 Asserts.assertEQ(result, rI + 1);
2298 }
2299
2300 for (int i = 0; i < arraySize; i++) {
2301 Asserts.assertEQ(va[i].x, rI + 1);
2302 }
2303 }
2304
2305 /* Create a new value type array and store a value type into
2306 * it. The test should pass without throwing an exception. */
2307 @Test
2308 public void test83() throws Throwable {
2309 vastoreMH.invokeExact(vcc);
2310 }
2311
2312 public void test83_verifier(boolean warmup) throws Throwable {
2313 test83();
2314 }
2315
2316 private static MethodHandle generateVastore() {
2317 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
2318 "Vastore",
2319 MethodType.methodType(void.class, ValueCapableClass1.class),
2320 CODE -> {
2321 CODE.
2322 iconst_1().
2323 anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2324 iconst_0().
2325 aload_0().
2326 vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2327 vastore().
2328 return_();
2329 }
2330 );
2331 }
2332
2333 /* Create a new value type array with element type
2334 * ValueCapableClass1 and attempt to store a value type of type
2335 * ValueCapableClass2 into it. */
2336 @Test
2337 public void test84() throws Throwable {
2338 invalidVastoreMH.invokeExact(vcc2);
2339 }
2340
2341 public void test84_verifier(boolean warmup) throws Throwable {
2342 boolean exceptionThrown = false;
2343 try {
2344 test84();
2345 } catch (ArrayStoreException e) {
2346 exceptionThrown = true;
2347 }
2348 Asserts.assertTrue(exceptionThrown, "ArrayStoreException must be thrown");
2349 }
2350
2351 private static MethodHandle generateInvalidVastore() {
2352 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
2353 "Vastore",
2354 MethodType.methodType(void.class, ValueCapableClass2.class),
2355 CODE -> {
2356 CODE.
2357 iconst_1().
2358 anewarray(ValueType.forClass(ValueCapableClass1.class).valueClass()).
2359 iconst_0().
2360 aload_0().
2361 vunbox(ValueType.forClass(ValueCapableClass2.class).valueClass()).
2362 vastore().
2363 return_();
2364 }
2365 );
2366 }
2367
2368 // ========== Test infrastructure ==========
2369
2370 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
2371 private static final int ValueTypePassFieldsAsArgsOn = 0x1;
2372 private static final int ValueTypePassFieldsAsArgsOff = 0x2;
2373 private static final int ValueTypeArrayFlattenOn = 0x4;
2374 private static final int ValueTypeArrayFlattenOff = 0x8;
2375 private static final int ValueTypeReturnedAsFieldsOn = 0x10;
2376 private static final int ValueTypeReturnedAsFieldsOff = 0x20;
2377 static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff | ValueTypeArrayFlattenOn | ValueTypeArrayFlattenOff | ValueTypeReturnedAsFieldsOn;
2378 private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
2379 private static final boolean ValueTypeArrayFlatten = (Boolean)WHITE_BOX.getVMFlag("ValueArrayFlatten");
2380 private static final boolean ValueTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("ValueTypeReturnedAsFields");
2381 private static final int COMP_LEVEL_ANY = -1;
2382 private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
2383 private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
2384 private static final int WARMUP = 251;
2385 private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
2386 private static boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
2387 private static boolean XCOMP = Platform.isComp();
2422 all_args.add(ValueTypeTestBench.class.getName());
2423 all_args.add("run");
2424 // Spawn process with default JVM options from the test's run command
2425 String[] vmInputArgs = InputArguments.getVmInputArgs();
2426 String[] cmds = Arrays.copyOf(vmInputArgs, vmInputArgs.length + all_args.size());
2427 System.arraycopy(all_args.toArray(), 0, cmds, vmInputArgs.length, all_args.size());
2428 OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);
2429 // If ideal graph printing is enabled/supported, verify output
2430 String output = oa.getOutput();
2431 oa.shouldHaveExitValue(0);
2432 boolean verifyIR = output.contains("PrintIdeal enabled") &&
2433 !output.contains("ValueTypePassFieldsAsArgs is not supported on this platform");
2434 if (verifyIR) {
2435 parseOutput(output);
2436 } else {
2437 System.out.println("WARNING: IR verification disabled! Running with -Xint, -Xcomp or release build?");
2438 }
2439 }
2440
2441 public static void main(String[] args) throws Throwable {
2442 //tests.values().removeIf(p -> !p.getName().equals("test85")); // Run single test
2443 if (args.length == 0) {
2444 execute_vm("-XX:+IgnoreUnrecognizedVMOptions", "-XX:-BackgroundCompilation",
2445 "-XX:+PrintCompilation", "-XX:+PrintInlining", "-XX:+PrintIdeal", "-XX:+PrintOptoAssembly",
2446 "-XX:CICompilerCount=1",
2447 "-XX:CompileCommand=quiet", "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueTypeTestBench::*",
2448 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue1::*",
2449 "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue2::*",
2450 "-XX:CompileCommand=compileonly,java.lang.Object::<init>",
2451 "-XX:CompileCommand=inline,java.lang.__Value::hashCode",
2452 "-XX:CompileCommand=compileonly,java.lang.invoke.*::*");
2453 } else {
2454 // Execute tests
2455 ValueTypeTestBench bench = new ValueTypeTestBench();
2456 bench.run();
2457 }
2458 }
2459
2460 public static void parseOutput(String output) throws Exception {
2461 Pattern comp_re = Pattern.compile("\\n\\s+\\d+\\s+\\d+\\s+(%| )(s| )(!| )b(n| )\\s+\\S+\\.(?<name>[^.]+::\\S+)\\s+(?<osr>@ \\d+\\s+)?[(]\\d+ bytes[)]\\n");
2462 Matcher m = comp_re.matcher(output);
|