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:+UseCompressedClassPointers runtime.valhalla.valuetypes.ObjectMethods 37 * @run main/othervm -Xint -XX:+EnableValhalla -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 75 76 static void checkGetClass(Object val, Class<?> expectedClass) { 77 Class<?> clazz = val.getClass(); 78 if (clazz == null) { 79 throw new RuntimeException("getClass return null"); 80 } else if (clazz != expectedClass) { 81 throw new RuntimeException("getClass (" + clazz + ") doesn't match " + expectedClass); 82 } 83 } 84 85 // Just check we don't crash the VM 86 static void checkHashCodes(Object val, int expectedHashCode) { 87 if (val.hashCode() != expectedHashCode) { 88 throw new RuntimeException("Hash code mismatch value: " + val.hashCode() + 89 " expected: " + expectedHashCode); 90 } 91 } 92 93 static void checkNotCloneable(MyInt val) { 94 boolean sawCnse = false; 95 try { 96 val.attemptClone(); 97 } catch (CloneNotSupportedException cnse) { 98 sawCnse = true; 99 } 100 if (!sawCnse) { 101 throw new RuntimeException("clone() did not fail"); 102 } 103 // Cloneable value type checked by "BadValueTypes" CFP tests 104 } 105 106 static void checkSynchronized(Object val) { 107 boolean sawImse = false; 108 try { 109 synchronized (val) { 110 throw new IllegalStateException("Unreachable code, reached"); 111 } 112 } catch (IllegalMonitorStateException imse) { 113 sawImse = true; 114 } 115 if (!sawImse) { 116 throw new RuntimeException("monitorenter did not fail"); 117 } 118 // synchronized method modifiers tested by "BadValueTypes" CFP tests 119 // jni monitor ops tested by "ValueWithJni" 120 } 121 122 // Check we haven't broken the mismatched monitor block check... 123 static void checkMonitorExit(Object val) { 124 boolean sawImse = false; 125 try { 126 MethodHandleBuilder.loadCode(MethodHandles.lookup(), 127 "mismatchedMonitorExit", 128 MethodType.methodType(Void.TYPE, Object.class), 129 CODE->{ 130 CODE 131 .aload(0) 132 .monitorexit() 133 .return_(); 134 }).invokeExact(val); 135 throw new IllegalStateException("Unreachable code, reached"); 136 } catch (Throwable t) { 137 if (t instanceof IllegalMonitorStateException) { 138 sawImse = true; 139 } 140 else { 141 throw new RuntimeException(t); 142 } 143 } 144 if (!sawImse) { 145 throw new RuntimeException("monitorexit did not fail"); 146 } 147 } 148 149 static void checkWait(Object val) { 150 boolean sawImse = false; 151 try { 152 val.wait(); 153 } catch (IllegalMonitorStateException imse) { 154 sawImse = true; 155 } catch (InterruptedException intExc) { 156 throw new RuntimeException(intExc); 157 } 158 if (!sawImse) { 159 throw new RuntimeException("wait() did not fail"); 160 } 161 162 sawImse = false; 163 try { 164 val.wait(1l); 165 } catch (IllegalMonitorStateException imse) { 166 sawImse = true; 167 } catch (InterruptedException intExc) { 168 throw new RuntimeException(intExc); 169 } 170 if (!sawImse) { 171 throw new RuntimeException("wait() did not fail"); 172 } 173 174 sawImse = false; 175 try { 176 val.wait(0l, 100); 177 } catch (IllegalMonitorStateException imse) { 178 sawImse = true; 179 } catch (InterruptedException intExc) { 180 throw new RuntimeException(intExc); 181 } 182 if (!sawImse) { 183 throw new RuntimeException("wait() did not fail"); 184 } 185 } 186 187 static void checkNotify(Object val) { 188 boolean sawImse = false; 189 try { 190 val.notify(); 191 } catch (IllegalMonitorStateException imse) { 192 sawImse = true; 193 } 194 if (!sawImse) { 195 throw new RuntimeException("notify() did not fail"); 196 } 197 198 sawImse = false; 199 try { 200 val.notifyAll(); 201 } catch (IllegalMonitorStateException imse) { 202 sawImse = true; 203 } 204 if (!sawImse) { 205 throw new RuntimeException("notifyAll() did not fail"); 206 } 207 } 208 209 static final __ByValue class MyInt { 210 final int value; 211 private MyInt() { value = 0; } 212 public static MyInt create(int v) { 213 MyInt mi = __MakeDefault MyInt(); 214 mi = __WithField(mi.value, v); 215 return mi; 216 } 217 public Object attemptClone() throws CloneNotSupportedException { 218 try { // Check it is not possible to clone... 219 MethodHandles.Lookup lookup = MethodHandles.lookup(); 220 MethodHandle mh = lookup.findVirtual(getClass(), 221 "clone", 222 MethodType.methodType(Object.class)); 223 return mh.invokeExact(this); 224 } catch (Throwable t) { 225 if (t instanceof CloneNotSupportedException) { 226 throw (CloneNotSupportedException) t; 227 } 228 throw new RuntimeException(t); 229 } 230 } 231 } 232 233 }