34 * -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
35 * @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
36 * -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs
37 * -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
38 */
39
40 package compiler.valhalla.valuetypes;
41
42 import compiler.whitebox.CompilerWhiteBoxTest;
43 import jdk.internal.misc.Unsafe;
44 import jdk.test.lib.Asserts;
45 import jdk.test.lib.Platform;
46 import jdk.test.lib.ProcessTools;
47 import jdk.test.lib.OutputAnalyzer;
48 import jdk.test.lib.Utils;
49 import sun.hotspot.WhiteBox;
50
51 import java.lang.annotation.Retention;
52 import java.lang.annotation.RetentionPolicy;
53 import java.lang.annotation.Repeatable;
54 import java.lang.reflect.Method;
55 import java.util.ArrayList;
56 import java.util.Arrays;
57 import java.util.Hashtable;
58 import java.util.List;
59 import java.util.regex.Matcher;
60 import java.util.regex.Pattern;
61
62 // Test value types
63 __ByValue final class MyValue1 {
64 static int s;
65 static final long sf = ValueTypeTestBench.rL;
66 final int x;
67 final long y;
68 final MyValue2 v1;
69 final MyValue2 v2;
70 static final MyValue2 v3 = MyValue2.createInline(ValueTypeTestBench.rI, true);
71 final int c;
72
73 private MyValue1(int x, long y, MyValue2 v1, MyValue2 v2, int c) {
74 s = x;
75 this.x = x;
76 this.y = y;
77 this.v1 = v1;
78 this.v2 = v2;
79 this.c = c;
80 }
81
82 @DontInline
83 public static MyValue1 createDontInline(int x, long y) {
84 return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
85 }
86
87 @ForceInline
88 public static MyValue1 createInline(int x, long y) {
89 return __Make MyValue1(x, y, MyValue2.createInline(x, x < y), MyValue2.createInline(x, x > y), ValueTypeTestBench.rI);
90 }
91
92 @ForceInline
93 public long hash() {
94 return s + sf + x + y + c + v1.hash() + v2.hash() + v3.hash();
95 }
96
97 @DontCompile
98 public long hashInterpreted() {
99 return s + sf + x + y + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
100 }
101 }
102
103 __ByValue final class MyValue2 {
104 final int x;
105 final boolean b;
106 final long c;
107
108 private MyValue2(int x, boolean b, long c) {
109 this.x = x;
122 }
123
124 @DontInline
125 public long hashInterpreted() {
126 return x + (b ? 0 : 1) + c;
127 }
128 }
129
130 public class ValueTypeTestBench {
131 // Print ideal graph after execution of each test
132 private static final boolean PRINT_GRAPH = true;
133
134 // Random test values
135 public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
136 public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
137
138 public ValueTypeTestBench() {
139 val3 = MyValue1.createInline(rI, rL);
140 }
141
142 // ========== Helper methods ==========
143
144 public long hash() {
145 return hash(rI, rL);
146 }
147
148 public long hash(int x, long y) {
149 return MyValue1.createInline(x, y).hash();
150 }
151
152 // ========== Test definitions ==========
153
154 // Receive value type through call to interpreter
155 @Test(failOn = ALLOC + STORE + TRAP)
156 public long test1() {
157 MyValue1 v = MyValue1.createDontInline(rI, rL);
158 return v.hash();
159 }
160
161 @DontCompile
759 }
760 return v.hash();
761 }
762
763 @Test(failOn = ALLOC + STORE + TRAP)
764 public long test36(MyValue2 v, boolean flag, long l) {
765 return test36_interp(v, flag) + l;
766 }
767
768 @DontCompile
769 public void test36_verifier(boolean warmup) {
770 MyValue2 v = MyValue2.createInline(rI, true);
771 long result = test36(v, false, rL);
772 Asserts.assertEQ(result, v.hashInterpreted() + rL);
773 if (!warmup) {
774 result = test36(v, true, rL);
775 Asserts.assertEQ(result, v.hashInterpreted() + rL);
776 }
777 }
778
779 // ========== Test infrastructure ==========
780
781 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
782 private static final int ValueTypePassFieldsAsArgsOn = 0x1;
783 private static final int ValueTypePassFieldsAsArgsOff = 0x2;
784 static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff;
785 private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
786 private static final int COMP_LEVEL_ANY = -1;
787 private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
788 private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
789 private static final int WARMUP = 10;
790 private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
791 private static boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
792 // TODO use Platform.isComp() after merge with JDK 9
793 private static boolean XCOMP = System.getProperty("java.vm.info").startsWith("compiled ");
794
795 // Regular expressions used to match nodes in the PrintIdeal output
796 private static final String START = "(\\d+\\t(.*";
797 private static final String MID = ".*)+\\t===.*";
798 private static final String END = ")|";
799 private static final String ALLOC = START + "CallStaticJava" + MID + "_new_instance_Java" + END;
800 private static final String LOAD = START + "Load" + MID + "valuetype\\*" + END;
801 private static final String STORE = START + "Store" + MID + "valuetype\\*" + END;
802 private static final String LOOP = START + "Loop" + MID + "" + END;
803 private static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap" + END;
804 // TODO: match field values of scalar replaced object
805 private static final String SCOBJ = "(.*# ScObj.*" + END;
806
807 static {
808 // Gather all test methods and put them in Hashtable
809 for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
|
34 * -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
35 * @run main/othervm -ea -noverify -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
36 * -XX:+UnlockExperimentalVMOptions -XX:-ValueTypePassFieldsAsArgs
37 * -XX:-TieredCompilation compiler.valhalla.valuetypes.ValueTypeTestBench
38 */
39
40 package compiler.valhalla.valuetypes;
41
42 import compiler.whitebox.CompilerWhiteBoxTest;
43 import jdk.internal.misc.Unsafe;
44 import jdk.test.lib.Asserts;
45 import jdk.test.lib.Platform;
46 import jdk.test.lib.ProcessTools;
47 import jdk.test.lib.OutputAnalyzer;
48 import jdk.test.lib.Utils;
49 import sun.hotspot.WhiteBox;
50
51 import java.lang.annotation.Retention;
52 import java.lang.annotation.RetentionPolicy;
53 import java.lang.annotation.Repeatable;
54 import java.lang.invoke.*;
55 import java.lang.reflect.Method;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.regex.Matcher;
61 import java.util.regex.Pattern;
62 import jdk.experimental.value.*;
63
64 // Test value types
65 __ByValue final class MyValue1 {
66 static int s;
67 static final long sf = ValueTypeTestBench.rL;
68 final int x;
69 final long y;
70 final MyValue2 v1;
71 final MyValue2 v2;
72 static final MyValue2 v3 = MyValue2.createInline(ValueTypeTestBench.rI, true);
73 final int c;
74
75 private MyValue1(int x, long y, MyValue2 v1, MyValue2 v2, int c) {
76 s = x;
77 this.x = x;
78 this.y = y;
79 this.v1 = v1;
80 this.v2 = v2;
81 this.c = c;
82 }
83
84 @DontInline
85 public static MyValue1 createDontInline(int x, long y) {
86 return __Make MyValue1(x, y, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
87 }
88
89 @ForceInline
90 public static MyValue1 createInline(int x, long y) {
91 return __Make MyValue1(x, y, MyValue2.createInline(x, true), MyValue2.createInline(x, false), ValueTypeTestBench.rI);
92 }
93
94 @ForceInline
95 public long hash() {
96 return s + sf + x + y + c + v1.hash() + v2.hash() + v3.hash();
97 }
98
99 @DontCompile
100 public long hashInterpreted() {
101 return s + sf + x + y + c + v1.hashInterpreted() + v2.hashInterpreted() + v3.hashInterpreted();
102 }
103 }
104
105 __ByValue final class MyValue2 {
106 final int x;
107 final boolean b;
108 final long c;
109
110 private MyValue2(int x, boolean b, long c) {
111 this.x = x;
124 }
125
126 @DontInline
127 public long hashInterpreted() {
128 return x + (b ? 0 : 1) + c;
129 }
130 }
131
132 public class ValueTypeTestBench {
133 // Print ideal graph after execution of each test
134 private static final boolean PRINT_GRAPH = true;
135
136 // Random test values
137 public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
138 public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
139
140 public ValueTypeTestBench() {
141 val3 = MyValue1.createInline(rI, rL);
142 }
143
144 // MethodHandles and value-capable class instance needed for testing vbox/vunbox
145 private static final MethodHandle vccUnboxLoadLongMH = generateVCCUnboxLoadLongMH();
146 private static final MethodHandle vccUnboxLoadIntMH = generateVCCUnboxLoadIntMH();
147 private static final MethodHandle vccUnboxBoxMH = generateVCCUnboxBoxMH();
148 private static final MethodHandle vccUnboxBoxLoadIntMH = generateVCCUnboxBoxLoadIntMH();
149
150 private static final ValueCapableClass1 vcc = ValueCapableClass1.create(15L, 31, (short)63, (short)127);
151
152 // ========== Helper methods ==========
153
154 public long hash() {
155 return hash(rI, rL);
156 }
157
158 public long hash(int x, long y) {
159 return MyValue1.createInline(x, y).hash();
160 }
161
162 // ========== Test definitions ==========
163
164 // Receive value type through call to interpreter
165 @Test(failOn = ALLOC + STORE + TRAP)
166 public long test1() {
167 MyValue1 v = MyValue1.createDontInline(rI, rL);
168 return v.hash();
169 }
170
171 @DontCompile
769 }
770 return v.hash();
771 }
772
773 @Test(failOn = ALLOC + STORE + TRAP)
774 public long test36(MyValue2 v, boolean flag, long l) {
775 return test36_interp(v, flag) + l;
776 }
777
778 @DontCompile
779 public void test36_verifier(boolean warmup) {
780 MyValue2 v = MyValue2.createInline(rI, true);
781 long result = test36(v, false, rL);
782 Asserts.assertEQ(result, v.hashInterpreted() + rL);
783 if (!warmup) {
784 result = test36(v, true, rL);
785 Asserts.assertEQ(result, v.hashInterpreted() + rL);
786 }
787 }
788
789 // Test vbox and vunbox
790 @Test
791 public long test37() throws Throwable {
792 return (long)vccUnboxLoadLongMH.invokeExact(vcc);
793 }
794
795 @DontCompile
796 public void test37_verifier(boolean warmup) {
797 try {
798 long result = test37();
799 Asserts.assertEQ(vcc.t, result, "Field t of input and result must be equal.");
800 } catch (Throwable t) {
801 throw new RuntimeException("test 37 failed", t);
802 }
803 }
804
805 // Generate a MethodHandle that obtains field t of the
806 // derived value type
807 private static MethodHandle generateVCCUnboxLoadLongMH() {
808 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
809 "vccUnboxLoadLong",
810 MethodType.methodType(long.class, ValueCapableClass1.class),
811 CODE -> {
812 CODE.
813 aload_0().
814 vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
815 vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "t", "J").
816 lreturn();
817 }
818 );
819 }
820
821
822 @Test
823 public int test38() throws Throwable {
824 return (int)vccUnboxLoadIntMH.invokeExact(vcc);
825 }
826
827 @DontCompile
828 public void test38_verifier(boolean warmup) {
829 try {
830 int result = test38();
831 Asserts.assertEQ(vcc.x, result, "Field x of input and result must be equal.");
832 } catch (Throwable t) {
833 throw new RuntimeException("test 38 failed", t);
834 }
835 }
836
837 // Generate a MethodHandle that obtains field x of the
838 // derived value type
839 private static MethodHandle generateVCCUnboxLoadIntMH() {
840 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
841 "vccUnboxLoadInt",
842 MethodType.methodType(int.class, ValueCapableClass1.class),
843 CODE -> {
844 CODE.
845 aload_0().
846 vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
847 vgetfield(ValueType.forClass(ValueCapableClass1.class).valueClass(), "x", "I").
848 ireturn();
849 }
850 );
851 }
852
853 @Test
854 public ValueCapableClass1 test39() throws Throwable {
855 return (ValueCapableClass1)vccUnboxBoxMH.invokeExact(vcc);
856 }
857
858 @DontCompile
859 public void test39_verifier(boolean warmup) {
860 try {
861 ValueCapableClass1 result = test39();
862 Asserts.assertEQ(vcc.value(), result.value(), "Value of VCC and returned VCC must be equal");
863 } catch (Throwable t) {
864 throw new RuntimeException("test 39 failed", t);
865 }
866 }
867
868 // Generate a MethodHandle that takes a value-capable class,
869 // unboxes it, then boxes it again and returns it.
870 private static MethodHandle generateVCCUnboxBoxMH() {
871 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
872 "vccUnboxBox",
873 MethodType.methodType(ValueCapableClass1.class, ValueCapableClass1.class),
874 CODE -> {
875 CODE.
876 aload_0().
877 vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
878 vbox(ValueCapableClass1.class).
879 areturn();
880 }
881 );
882 }
883
884 @Test
885 public int test40() throws Throwable {
886 return (int)vccUnboxBoxLoadIntMH.invokeExact(vcc);
887 }
888
889 @DontCompile
890 public void test40_verifier(boolean warmup) {
891 try {
892 int result = test40();
893 Asserts.assertEQ(vcc.x, result, "Field x of VCC and result must be equal");
894 } catch (Throwable t) {
895 throw new RuntimeException("Test failed in the interpeter", t);
896 }
897 }
898
899 // Generate a MethodHandle that takes a value-capable class,
900 // unboxes it, boxes it, reads a field from it, and returns the
901 // field.
902 private static MethodHandle generateVCCUnboxBoxLoadIntMH() {
903 return MethodHandleBuilder.loadCode(MethodHandles.lookup(),
904 "vccUnboxBoxLoadInt",
905 MethodType.methodType(int.class, ValueCapableClass1.class),
906 CODE -> {
907 CODE.
908 aload_0().
909 vunbox(ValueType.forClass(ValueCapableClass1.class).valueClass()).
910 vbox(ValueCapableClass1.class).
911 getfield(ValueCapableClass1.class, "x", "I").
912 ireturn();
913 }
914 );
915 }
916
917 // ========== Test infrastructure ==========
918
919 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
920 private static final int ValueTypePassFieldsAsArgsOn = 0x1;
921 private static final int ValueTypePassFieldsAsArgsOff = 0x2;
922 static final int AllFlags = ValueTypePassFieldsAsArgsOn | ValueTypePassFieldsAsArgsOff;
923 private static final boolean ValueTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("ValueTypePassFieldsAsArgs");
924 private static final int COMP_LEVEL_ANY = -1;
925 private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
926 private static final Hashtable<String, Method> tests = new Hashtable<String, Method>();
927 private static final int WARMUP = 250;
928 private static boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
929 private static boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
930 // TODO use Platform.isComp() after merge with JDK 9
931 private static boolean XCOMP = System.getProperty("java.vm.info").startsWith("compiled ");
932
933 // Regular expressions used to match nodes in the PrintIdeal output
934 private static final String START = "(\\d+\\t(.*";
935 private static final String MID = ".*)+\\t===.*";
936 private static final String END = ")|";
937 private static final String ALLOC = START + "CallStaticJava" + MID + "_new_instance_Java" + END;
938 private static final String LOAD = START + "Load" + MID + "valuetype\\*" + END;
939 private static final String STORE = START + "Store" + MID + "valuetype\\*" + END;
940 private static final String LOOP = START + "Loop" + MID + "" + END;
941 private static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap" + END;
942 // TODO: match field values of scalar replaced object
943 private static final String SCOBJ = "(.*# ScObj.*" + END;
944
945 static {
946 // Gather all test methods and put them in Hashtable
947 for (Method m : ValueTypeTestBench.class.getDeclaredMethods()) {
|