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 package runtime.valhalla.valuetypes; 24 25 import java.lang.ref.*; 26 27 28 /* 29 * @test Ifacmp 30 * @requires vm.gc == null 31 * @summary if_acmpeq/ne bytecode test 32 * @compile Ifacmp.java 33 * @run main/othervm -Xint -Xms16m -Xmx16m -XX:+UseSerialGC 34 * -XX:+UnlockExperimentalVMOptions -XX:ACmpOnValues=2 35 * runtime.valhalla.valuetypes.Ifacmp alwaysFalse 36 * @run main/othervm -Xint -Xms16m -Xmx16m -XX:+UseSerialGC 37 * -XX:+UnlockExperimentalVMOptions -XX:ACmpOnValues=3 38 * runtime.valhalla.valuetypes.Ifacmp 39 * @run main/othervm -Xcomp -Xms16m -Xmx16m -XX:+UseSerialGC 40 * -XX:+UnlockExperimentalVMOptions -XX:ACmpOnValues=3 41 * runtime.valhalla.valuetypes.Ifacmp 42 */ 43 public class Ifacmp { 44 45 static inline class MyValue { 46 int value; 47 public MyValue(int v) { this.value = v; } 48 }; 49 static inline class MyValue2 { 50 int value; 51 public MyValue2(int v) { this.value = v; } 52 }; 53 54 boolean acmpModeInlineAlwaysFalse = false; 55 56 Object aNull = null; 57 Object bNull = null; 58 59 Object aObject = new String("Hi"); 60 Object bObject = new String("Hi"); 61 62 Object aValue = new MyValue(1); 63 Object bValue = new MyValue(1); 64 Object cValue = new MyValue(0); 65 Object aValue2 = new MyValue2(4711); 66 67 Object[][] equalUseCases = { 68 { aNull, bNull }, 69 { aObject, aObject }, 70 { aValue, bValue }, 71 { cValue, cValue }, 72 { aValue2, aValue2 } 73 }; 74 75 int objectEqualsUseCases = 2; // Nof object equals use cases 76 77 // Would just generate these fail case from the "equal set" above, 78 // but to do so needs ==, so write out by hand it is... 79 Object[][] notEqualUseCases = { 80 { aNull, aObject }, 81 { aNull, bObject }, 82 { aNull, aValue }, 83 { aNull, bValue }, 84 { aNull, cValue }, 85 { aNull, aValue2 }, 86 { aObject, bObject }, 87 { aObject, aValue }, 88 { aObject, bValue }, 89 { aObject, cValue }, 90 { aObject, aValue2 }, 91 { bObject, cValue }, 92 { bObject, aValue2 }, 93 { aValue, cValue }, 94 { aValue, aValue2 }, 95 }; 96 97 public Ifacmp() { this(false); } 98 public Ifacmp(boolean acmpModeInlineAlwaysFalse) { 99 this.acmpModeInlineAlwaysFalse = acmpModeInlineAlwaysFalse; 100 if (acmpModeInlineAlwaysFalse) { 101 System.out.println("ifacmp always false for inline types"); 102 } else { 103 System.out.println("ifacmp substitutability inline types"); 104 } 105 } 106 107 public void test() { 108 testAllUseCases(); 109 } 110 111 public void testUntilGc(int nofGc) { 112 for (int i = 0; i < nofGc; i++) { 113 System.out.println("GC num " + (i + 1)); 114 testUntilGc(); 115 } 116 } 117 118 public void testUntilGc() { 119 Reference ref = new WeakReference<Object>(new Object(), new ReferenceQueue<>()); 120 do { 121 test(); 122 } while (ref.get() != null); 123 } 124 125 public void testAllUseCases() { 126 int useCase = 0; 127 for (Object[] pair : equalUseCases) { 128 useCase++; 129 boolean equal = acmpModeInlineAlwaysFalse ? (useCase <= objectEqualsUseCases) : true; 130 checkEqual(pair[0], pair[1], equal); 131 } 132 for (Object[] pair : notEqualUseCases) { 133 checkEqual(pair[0], pair[1], false); 134 } 135 testLocalValues(); 136 } 137 138 public void testValues() { 139 checkEqual(aValue, bValue, true); 140 141 checkEqual(aValue, cValue, false); 142 checkEqual(aValue, aValue2, false); 143 checkEqual(aValue2, bValue, false); 144 checkEqual(aValue2, cValue, false); 145 testLocalValues(); 146 } 147 148 public void testLocalValues() { 149 // "aload + ifacmp" should be same as "aaload + ifamcp" 150 // but let's be paranoid... 151 MyValue a = new MyValue(11); 152 MyValue b = new MyValue(11); 153 MyValue c = a; 154 MyValue a1 = new MyValue(7); 155 MyValue2 a2 = new MyValue2(13); 156 157 if (acmpModeInlineAlwaysFalse) { 158 if (a == b) throw new RuntimeException("Always false fail " + a + " == " + b); 159 if (a == c) throw new RuntimeException("Always false fail " + a + " == " + c); 160 } else { 161 if (a != b) throw new RuntimeException("Substitutability test failed" + a + " != " + b); 162 if (a != c) throw new RuntimeException("Substitutability test failed"); 163 } 164 if (a == a1) throw new RuntimeException(); 165 checkEqual(a, a2, false); 166 } 167 168 boolean shouldEqualSelf(Object a) { 169 return acmpModeInlineAlwaysFalse ? (!(a != null && a.getClass().isInlineClass())) : true; 170 } 171 172 void checkEqual(Object a, Object b, boolean isEqual) { 173 testEquals(a, a, shouldEqualSelf(a)); 174 testEquals(b, b, shouldEqualSelf(b)); 175 testEquals(a, b, isEqual); 176 testNotEquals(a, b, !isEqual); 177 } 178 179 public static void testEquals(Object a, Object b, boolean expected) { 180 boolean isEqual = (a == b); 181 if (isEqual != expected) { 182 throw new RuntimeException("Expected " + expected + " : " 183 + a + " == " + b); 184 } 185 } 186 187 public static void testNotEquals(Object a, Object b, boolean expected) { 188 boolean isNotEqual = (a != b); 189 if (isNotEqual != expected) { 190 throw new RuntimeException("Expected " + expected + " : " 191 + a + " != " + b); 192 } 193 } 194 195 public static void main(String[] args) { 196 boolean inlineTypesAlwaysFalse = (args.length > 0) && args[0].equals("alwaysFalse"); 197 new Ifacmp(inlineTypesAlwaysFalse).test(); 198 new Ifacmp(inlineTypesAlwaysFalse).testUntilGc(3); 199 } 200 }