--- old/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-07-10 18:12:19.819328841 +0200 +++ new/test/compiler/valhalla/valuetypes/ValueTypeTestBench.java 2017-07-10 18:12:15.614347676 +0200 @@ -2605,6 +2605,178 @@ Asserts.assertEQ(result, 0L); } + // method handle combinators + static { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + + MethodType test94_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue3;", ValueTypeTestBench.class.getClassLoader()); + MethodHandle test94_mh1 = lookup.findVirtual(ValueTypeTestBench.class, "test94_target1", test94_mt); + MethodHandle test94_mh2 = lookup.findVirtual(ValueTypeTestBench.class, "test94_target2", test94_mt); + MethodType test94_mt2 = MethodType.methodType(boolean.class); + MethodHandle test94_mh_test = lookup.findVirtual(ValueTypeTestBench.class, "test94_test", test94_mt2); + test94_mh = MethodHandles.guardWithTest(test94_mh_test, test94_mh1, test94_mh2); + + MethodType test95_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue1;", ValueTypeTestBench.class.getClassLoader()); + test95_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test95_target1", test95_mt); + MethodHandle test95_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test95_target2", test95_mt); + MethodType test95_mt2 = MethodType.methodType(boolean.class); + MethodType test95_mt3 = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue1;", ValueTypeTestBench.class.getClassLoader()); + MethodHandle test95_mh_test = lookup.findStatic(ValueTypeTestBench.class, "test95_test", test95_mt2); + test95_mh = MethodHandles.guardWithTest(test95_mh_test, + MethodHandles.invoker(test95_mt3), + MethodHandles.dropArguments(test95_mh2, 0, MethodHandle.class)); + + MethodType test96_mt = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue1;", ValueTypeTestBench.class.getClassLoader()); + MethodHandle test96_mh1 = lookup.findStatic(ValueTypeTestBench.class, "test96_target1", test96_mt); + test96_mh2 = lookup.findStatic(ValueTypeTestBench.class, "test96_target2", test96_mt); + MethodType test96_mt2 = MethodType.methodType(boolean.class); + MethodType test96_mt3 = MethodType.fromMethodDescriptorString("()Qcompiler/valhalla/valuetypes/MyValue1;", ValueTypeTestBench.class.getClassLoader()); + MethodHandle test96_mh_test = lookup.findStatic(ValueTypeTestBench.class, "test96_test", test96_mt2); + test96_mh = MethodHandles.guardWithTest(test96_mh_test, + MethodHandles.dropArguments(test96_mh1, 0, MethodHandle.class), + MethodHandles.invoker(test96_mt3)); + + MethodHandle test97_count = MethodHandles.constant(int.class, 100); + ValueType test97_VT = ValueType.forClass(ValueCapableClass2.class); + MethodHandle test97_init = test97_VT.defaultValueConstant(); + MethodHandle test97_getfield = test97_VT.findGetter(lookup, "u", long.class); + MethodHandle test97_add = lookup.findStatic(Long.class, "sum", MethodType.methodType(long.class, long.class, long.class)); + MethodHandle test97_body = MethodHandles.collectArguments(ValueCapableClass2.FACTORY, + 0, + MethodHandles.dropArguments(MethodHandles.collectArguments(MethodHandles.insertArguments(test97_add, + 0, + 1L), + 0, + test97_getfield), + 1, + int.class)); + test97_mh = MethodHandles.collectArguments(test97_getfield, + 0, + MethodHandles.countedLoop(test97_count, test97_init, test97_body)); + + } catch (NoSuchMethodException|IllegalAccessException|NoSuchFieldException e) { + e.printStackTrace(); + throw new RuntimeException("method handle lookup fails"); + } + } + + // Return of target1 and target2 merges in a Lambda Form as an + // __Value. Shouldn't cause any allocation + final MyValue3 test94_vt1 = MyValue3.create(); + @ForceInline + MyValue3 test94_target1() { + return test94_vt1; + } + + final MyValue3 test94_vt2 = MyValue3.create(); + @ForceInline + MyValue3 test94_target2() { + return test94_vt2; + } + + boolean test94_bool = true; + @ForceInline + boolean test94_test() { + return test94_bool; + } + + static final MethodHandle test94_mh; + + @Test(valid = ValueTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE) + @Test(valid = ValueTypeReturnedAsFieldsOff) + MyValue3 test94() throws Throwable { + return (MyValue3)test94_mh.invokeExact(this); + } + + @DontCompile + public void test94_verifier(boolean warmup) throws Throwable { + test94_bool = !test94_bool; + MyValue3 vt = test94(); + vt.verify(test94_bool ? test94_vt1 : test94_vt2); + } + + // Similar as above but with the method handle for target1 not + // static. Shouldn't cause any allocation but currently does. + @ForceInline + static MyValue1 test95_target1() { + return MyValue1.createWithFieldsInline(rI, rL); + } + + @ForceInline + static MyValue1 test95_target2() { + return MyValue1.createWithFieldsInline(rI+1, rL+1); + } + + static boolean test95_bool = true; + @ForceInline + static boolean test95_test() { + return test95_bool; + } + + static final MethodHandle test95_mh; + static final MethodHandle test95_mh1; + + @Test + long test95() throws Throwable { + return ((MyValue1)test95_mh.invokeExact(test95_mh1)).hash(); + } + + @DontCompile + public void test95_verifier(boolean warmup) throws Throwable { + test95_bool = !test95_bool; + long hash = test95(); + Asserts.assertEQ(hash, MyValue1.createWithFieldsInline(rI+(test95_bool ? 0 : 1), rL+(test95_bool ? 0 : 1)).hash()); + } + + // Same as above but with the method handle for target2 not + // static. Shouldn't cause any allocation but currently does. + @ForceInline + static MyValue1 test96_target1() { + return MyValue1.createWithFieldsInline(rI, rL); + } + + @ForceInline + static MyValue1 test96_target2() { + return MyValue1.createWithFieldsInline(rI+1, rL+1); + } + + static boolean test96_bool = true; + @ForceInline + static boolean test96_test() { + return test96_bool; + } + + static final MethodHandle test96_mh; + static final MethodHandle test96_mh2; + + @Test + long test96() throws Throwable { + return ((MyValue1)test96_mh.invokeExact(test96_mh2)).hash(); + } + + @DontCompile + public void test96_verifier(boolean warmup) throws Throwable { + test96_bool = !test96_bool; + long hash = test96(); + Asserts.assertEQ(hash, MyValue1.createWithFieldsInline(rI+(test96_bool ? 0 : 1), rL+(test96_bool ? 0 : 1)).hash()); + } + + // Simple reduction with intermediate result merged in a Lambda + // Form as an __Value. Shouldn't cause any allocations. The entire + // loop should go away as the result is a constant. + static final MethodHandle test97_mh; + + @Test(failOn = ALLOC + STORE + LOOP) + long test97() throws Throwable { + return (long)test97_mh.invokeExact(); + } + + @DontCompile + public void test97_verifier(boolean warmup) throws Throwable { + long v = test97(); + Asserts.assertEQ(v, 100L); + } // ========== Test infrastructure ========== private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); @@ -2691,7 +2863,9 @@ "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.MyValue4::*", "-XX:CompileCommand=compileonly,java.lang.Object::", "-XX:CompileCommand=inline,java.lang.__Value::hashCode", - "-XX:CompileCommand=compileonly,java.lang.invoke.*::*"); + "-XX:CompileCommand=compileonly,java.lang.invoke.*::*", + "-XX:CompileCommand=compileonly,compiler.valhalla.valuetypes.ValueCapableClass2_*::*", + "-XX:CompileCommand=compileonly,java.lang.Long::sum"); } else { // Execute tests ValueTypeTestBench bench = new ValueTypeTestBench();