1 /* 2 * Copyright (c) 2018, 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.invoke.*; 26 27 import jdk.experimental.value.MethodHandleBuilder; 28 29 /* 30 * @test ObjectMethods 31 * @summary Check object method implemented by the VM behave with value types 32 * @modules java.base/jdk.experimental.bytecode 33 * java.base/jdk.experimental.value 34 * @library /test/lib 35 * @compile -XDenableValueTypes ObjectMethods.java 36 * @run main/othervm -Xint -XX:+EnableValhalla -XX:+UseBiasedLocking -XX:+UseCompressedClassPointers runtime.valhalla.valuetypes.ObjectMethods 37 * @run main/othervm -Xint -XX:+EnableValhalla -XX:-UseBiasedLocking -XX:-UseCompressedClassPointers runtime.valhalla.valuetypes.ObjectMethods 38 * @run main/othervm -Xint -XX:+EnableValhalla -noverify runtime.valhalla.valuetypes.ObjectMethods noverify 39 */ 40 41 public class ObjectMethods { 42 43 public static void main(String[] args) { 44 testObjectMethods((args.length > 0 && args[0].equals("noverify"))); 45 } 46 47 public static void testObjectMethods(boolean verifierDisabled) { 48 MyInt val = MyInt.create(7); 49 MyInt sameVal = MyInt.create(7); 50 51 // Exercise all the Object native/VM methods... 52 53 if (verifierDisabled) { // Just noverifier... 54 checkMonitorExit(val); 55 return; 56 } 57 58 // getClass() 59 checkGetClass(val, MyInt.class); 60 61 //hashCode()/identityHashCode() 62 checkHashCodes(val, sameVal.hashCode()); 63 64 // clone() 65 checkNotCloneable(val); 66 67 // synchronized 68 checkSynchronized(val); 69 70 // wait/notify() 71 checkWait(val); 72 checkNotify(val); 73 74 System.gc(); 75 } 76 77 78 static void checkGetClass(Object val, Class<?> expectedClass) { 79 Class<?> clazz = val.getClass(); 80 if (clazz == null) { 81 throw new RuntimeException("getClass return null"); 82 } else if (clazz != expectedClass) { 83 throw new RuntimeException("getClass (" + clazz + ") doesn't match " + expectedClass); 84 } 85 } 86 87 // Just check we don't crash the VM 88 static void checkHashCodes(Object val, int expectedHashCode) { 89 if (val.hashCode() != expectedHashCode) { 90 throw new RuntimeException("Hash code mismatch value: " + val.hashCode() + 91 " expected: " + expectedHashCode); 92 } 93 } 94 95 static void checkNotCloneable(MyInt val) { 96 boolean sawCnse = false; 97 try { 98 val.attemptClone(); 99 } catch (CloneNotSupportedException cnse) { 100 sawCnse = true; 101 } 102 if (!sawCnse) { 103 throw new RuntimeException("clone() did not fail"); 104 } 105 // Cloneable value type checked by "BadValueTypes" CFP tests 106 } 107 108 static void checkSynchronized(Object val) { 109 boolean sawImse = false; 110 try { 111 synchronized (val) { 112 throw new IllegalStateException("Unreachable code, reached"); 113 } 114 } catch (IllegalMonitorStateException imse) { 115 sawImse = true; 116 } 117 if (!sawImse) { 118 throw new RuntimeException("monitorenter did not fail"); 119 } 120 // synchronized method modifiers tested by "BadValueTypes" CFP tests 121 // jni monitor ops tested by "ValueWithJni" 122 } 123 124 // Check we haven't broken the mismatched monitor block check... 125 static void checkMonitorExit(Object val) { 126 boolean sawImse = false; 127 try { 128 MethodHandleBuilder.loadCode(MethodHandles.lookup(), 129 "mismatchedMonitorExit", 130 MethodType.methodType(Void.TYPE, Object.class), 131 CODE->{ 132 CODE 133 .aload(0) 134 .monitorexit() 135 .return_(); 136 }).invokeExact(val); 137 throw new IllegalStateException("Unreachable code, reached"); 138 } catch (Throwable t) { 139 if (t instanceof IllegalMonitorStateException) { 140 sawImse = true; 141 } 142 else { 143 throw new RuntimeException(t); 144 } 145 } 146 if (!sawImse) { 147 throw new RuntimeException("monitorexit did not fail"); 148 } 149 } 150 151 static void checkWait(Object val) { 152 boolean sawImse = false; 153 try { 154 val.wait(); 155 } catch (IllegalMonitorStateException imse) { 156 sawImse = true; 157 } catch (InterruptedException intExc) { 158 throw new RuntimeException(intExc); 159 } 160 if (!sawImse) { 161 throw new RuntimeException("wait() did not fail"); 162 } 163 164 sawImse = false; 165 try { 166 val.wait(1l); 167 } catch (IllegalMonitorStateException imse) { 168 sawImse = true; 169 } catch (InterruptedException intExc) { 170 throw new RuntimeException(intExc); 171 } 172 if (!sawImse) { 173 throw new RuntimeException("wait() did not fail"); 174 } 175 176 sawImse = false; 177 try { 178 val.wait(0l, 100); 179 } catch (IllegalMonitorStateException imse) { 180 sawImse = true; 181 } catch (InterruptedException intExc) { 182 throw new RuntimeException(intExc); 183 } 184 if (!sawImse) { 185 throw new RuntimeException("wait() did not fail"); 186 } 187 } 188 189 static void checkNotify(Object val) { 190 boolean sawImse = false; 191 try { 192 val.notify(); 193 } catch (IllegalMonitorStateException imse) { 194 sawImse = true; 195 } 196 if (!sawImse) { 197 throw new RuntimeException("notify() did not fail"); 198 } 199 200 sawImse = false; 201 try { 202 val.notifyAll(); 203 } catch (IllegalMonitorStateException imse) { 204 sawImse = true; 205 } 206 if (!sawImse) { 207 throw new RuntimeException("notifyAll() did not fail"); 208 } 209 } 210 211 static final __ByValue class MyInt { 212 final int value; 213 private MyInt() { value = 0; } 214 public static MyInt create(int v) { 215 MyInt mi = __MakeDefault MyInt(); 216 mi = __WithField(mi.value, v); 217 return mi; 218 } 219 public Object attemptClone() throws CloneNotSupportedException { 220 try { // Check it is not possible to clone... 221 MethodHandles.Lookup lookup = MethodHandles.lookup(); 222 MethodHandle mh = lookup.findVirtual(getClass(), 223 "clone", 224 MethodType.methodType(Object.class)); 225 return mh.invokeExact(this); 226 } catch (Throwable t) { 227 if (t instanceof CloneNotSupportedException) { 228 throw (CloneNotSupportedException) t; 229 } 230 throw new RuntimeException(t); 231 } 232 } 233 } 234 235 }