1 /* 2 * Copyright (c) 2019, 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 java.lang.invoke.*; 27 import java.lang.reflect.Method; 28 29 import jdk.test.lib.Asserts; 30 31 /** 32 * @test TestDeoptimizationWhenBuffering 33 * @summary Test correct execution after deoptimizing from inline type specific runtime calls. 34 * @library /testlibrary /test/lib /compiler/whitebox / 35 * @compile -XDallowWithFieldOperator TestDeoptimizationWhenBuffering.java 36 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch 37 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 38 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline 39 * -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=1 40 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 41 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 42 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline 43 * -XX:-ValueTypePassFieldsAsArgs -XX:-ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=1 44 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 45 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 46 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline 47 * -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=-1 48 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 49 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 50 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline 51 * -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=-1 52 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 53 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 54 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline 55 * -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueFieldMaxFlatSize=0 56 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 57 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 58 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline 59 * -XX:+ValueTypePassFieldsAsArgs -XX:+ValueTypeReturnedAsFields -XX:ValueArrayElemMaxFlatSize=-1 -XX:ValueFieldMaxFlatSize=0 60 * -XX:CompileCommand=dontinline,compiler.valhalla.valuetypes.*::test* 61 * compiler.valhalla.valuetypes.TestDeoptimizationWhenBuffering 62 */ 63 64 final inline class MyValue1 { 65 static int cnt = 0; 66 final int x; 67 final MyValue2 vtField1; 68 final MyValue2? vtField2; 69 70 public MyValue1() { 71 this.x = ++cnt; 72 this.vtField1 = new MyValue2(); 73 this.vtField2 = new MyValue2(); 74 } 75 76 public int hash() { 77 return x + vtField1.x + vtField2.x; 78 } 79 80 public MyValue1 testWithField(int x) { 81 return __WithField(this.x, x); 82 } 83 } 84 85 final inline class MyValue2 { 86 static int cnt = 0; 87 final int x; 88 public MyValue2() { 89 this.x = ++cnt; 90 } 91 } 92 93 public class TestDeoptimizationWhenBuffering { 94 static { 95 try { 96 Class<?> clazz = TestDeoptimizationWhenBuffering.class; 97 ClassLoader loader = clazz.getClassLoader(); 98 MethodHandles.Lookup lookup = MethodHandles.lookup(); 99 100 MethodType mt = MethodType.methodType(MyValue1.class); 101 test9_mh = lookup.findStatic(clazz, "test9Callee", mt); 102 test10_mh = lookup.findStatic(clazz, "test10Callee", mt); 103 } catch (NoSuchMethodException | IllegalAccessException e) { 104 e.printStackTrace(); 105 throw new RuntimeException("Method handle lookup failed"); 106 } 107 } 108 109 MyValue1 test1() { 110 return new MyValue1(); 111 } 112 113 static MyValue1 vtField1; 114 115 MyValue1 test2() { 116 vtField1 = new MyValue1(); 117 return vtField1; 118 } 119 120 int test3Callee(MyValue1 vt) { 121 return vt.hash(); 122 } 123 124 int test3() { 125 MyValue1 vt = new MyValue1(); 126 return test3Callee(vt); 127 } 128 129 static MyValue1[] vtArray = new MyValue1[1]; 130 131 MyValue1 test4() { 132 vtArray[0] = new MyValue1(); 133 return vtArray[0]; 134 } 135 136 Object test5(Object[] array) { 137 array[0] = new MyValue1(); 138 return array[0]; 139 } 140 141 boolean test6(Object obj) { 142 MyValue1 vt = new MyValue1(); 143 return vt == obj; 144 } 145 146 Object test7(Object[] obj) { 147 return obj[0]; 148 } 149 150 MyValue1? test8(MyValue1?[] obj) { 151 return obj[0]; 152 } 153 154 static final MethodHandle test9_mh; 155 156 static MyValue1 test9Callee() { 157 return new MyValue1(); 158 } 159 160 MyValue1 test9() throws Throwable { 161 return (MyValue1)test9_mh.invokeExact(); 162 } 163 164 static final MethodHandle test10_mh; 165 static final MyValue1 test10Field = new MyValue1(); 166 static int test10Counter = 0; 167 168 static MyValue1 test10Callee() { 169 test10Counter++; 170 return test10Field; 171 } 172 173 Object test10() throws Throwable { 174 return test10_mh.invoke(); 175 } 176 177 MyValue1 test11(MyValue1 vt) { 178 return vt.testWithField(42); 179 } 180 181 MyValue1 vtField2; 182 183 MyValue1 test12() { 184 vtField2 = new MyValue1(); 185 return vtField2; 186 } 187 188 public static void main(String[] args) throws Throwable { 189 MyValue1[] va = new MyValue1[3]; 190 va[0] = new MyValue1(); 191 Object[] oa = new Object[3]; 192 oa[0] = va[0]; 193 TestDeoptimizationWhenBuffering t = new TestDeoptimizationWhenBuffering(); 194 for (int i = 0; i < 100_000; ++i) { 195 // Check counters to make sure that we don't accidentially reexecute calls when deoptimizing 196 int expected = MyValue1.cnt + MyValue2.cnt + MyValue2.cnt; 197 Asserts.assertEQ(t.test1().hash(), expected + 4); 198 vtField1 = MyValue1.default; 199 Asserts.assertEQ(t.test2().hash(), expected + 9); 200 Asserts.assertEQ(vtField1.hash(), expected + 9); 201 Asserts.assertEQ(t.test3(), expected + 14); 202 Asserts.assertEQ(t.test4().hash(), expected + 19); 203 Asserts.assertEQ(((MyValue1)t.test5(vtArray)).hash(), expected + 24); 204 Asserts.assertEQ(t.test6(vtField1), false); 205 Asserts.assertEQ(t.test7(((i % 2) == 0) ? va : oa), va[0]); 206 Asserts.assertEQ(t.test8(va), va[0]); 207 Asserts.assertEQ(t.test8(va), va[0]); 208 Asserts.assertEQ(t.test9().hash(), expected + 34); 209 int count = test10Counter; 210 Asserts.assertEQ(((MyValue1)t.test10()).hash(), test10Field.hash()); 211 Asserts.assertEQ(t.test10Counter, count + 1); 212 Asserts.assertEQ(t.test11(va[0]).hash(), va[0].testWithField(42).hash()); 213 t.vtField2 = MyValue1.default; 214 Asserts.assertEQ(t.test12().hash(), expected + 39); 215 Asserts.assertEQ(t.vtField2.hash(), expected + 39); 216 } 217 } 218 }