1 /* 2 * Copyright (c) 2012, 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 25 package org.graalvm.compiler.hotspot.test; 26 27 import java.lang.invoke.ConstantCallSite; 28 import java.lang.invoke.MethodHandles; 29 import java.lang.invoke.MethodType; 30 31 import org.graalvm.compiler.api.directives.GraalDirectives; 32 import org.graalvm.compiler.api.replacements.MethodSubstitution; 33 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 34 import org.graalvm.compiler.hotspot.HotSpotBackend; 35 import org.graalvm.compiler.nodes.IfNode; 36 import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; 37 import org.junit.Test; 38 39 /** 40 * Tests HotSpot specific {@link MethodSubstitution}s. 41 */ 42 public class HotSpotMethodSubstitutionTest extends MethodSubstitutionTest { 43 44 @Test 45 public void testObjectSubstitutions() { 46 TestClassA obj = new TestClassA(); 47 48 testGraph("getClass0"); 49 testGraph("objectHashCode"); 50 51 test("getClass0", "a string"); 52 test("objectHashCode", obj); 53 54 testGraph("objectNotify", "Object.notify"); 55 testGraph("objectNotifyAll", "Object.notifyAll"); 56 57 synchronized (obj) { 58 test("objectNotify", obj); 59 test("objectNotifyAll", obj); 60 } 61 // Test with IllegalMonitorStateException (no synchronized block) 62 test("objectNotify", obj); 63 test("objectNotifyAll", obj); 64 } 65 66 @SuppressWarnings("all") 67 public static Class<?> getClass0(Object obj) { 68 return obj.getClass(); 69 } 70 71 @SuppressWarnings("all") 72 public static int objectHashCode(TestClassA obj) { 73 return obj.hashCode(); 74 } 75 76 @SuppressWarnings("all") 77 public static void objectNotify(Object obj) { 78 obj.notify(); 79 } 80 81 @SuppressWarnings("all") 82 public static void objectNotifyAll(Object obj) { 83 obj.notifyAll(); 84 } 85 86 @Test 87 public void testClassSubstitutions() { 88 testGraph("getModifiers"); 89 testGraph("isInterface"); 90 testGraph("isArray"); 91 testGraph("isPrimitive"); 92 testGraph("getSuperClass"); 93 testGraph("getComponentType"); 94 95 for (Class<?> c : new Class<?>[]{getClass(), Cloneable.class, int[].class, String[][].class}) { 96 test("getModifiers", c); 97 test("isInterface", c); 98 test("isArray", c); 99 test("isPrimitive", c); 100 test("getSuperClass", c); 101 test("getComponentType", c); 102 } 103 } 104 105 @SuppressWarnings("all") 106 public static int getModifiers(Class<?> clazz) { 107 return clazz.getModifiers(); 108 } 109 110 @SuppressWarnings("all") 111 public static boolean isInterface(Class<?> clazz) { 112 return clazz.isInterface(); 113 } 114 115 @SuppressWarnings("all") 116 public static boolean isArray(Class<?> clazz) { 117 return clazz.isArray(); 118 } 119 120 @SuppressWarnings("all") 121 public static boolean isPrimitive(Class<?> clazz) { 122 return clazz.isPrimitive(); 123 } 124 125 @SuppressWarnings("all") 126 public static Class<?> getSuperClass(Class<?> clazz) { 127 return clazz.getSuperclass(); 128 } 129 130 @SuppressWarnings("all") 131 public static Class<?> getComponentType(Class<?> clazz) { 132 return clazz.getComponentType(); 133 } 134 135 @Test 136 public void testThreadSubstitutions() { 137 GraalHotSpotVMConfig config = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig(); 138 testGraph("currentThread"); 139 if (config.osThreadInterruptedOffset != Integer.MAX_VALUE) { 140 assertInGraph(testGraph("threadIsInterrupted", "isInterrupted", true), IfNode.class); 141 assertInGraph(testGraph("threadInterrupted", "isInterrupted", true), IfNode.class); 142 } 143 144 Thread currentThread = Thread.currentThread(); 145 test("currentThread", currentThread); 146 if (config.osThreadInterruptedOffset != Integer.MAX_VALUE) { 147 test("threadIsInterrupted", currentThread); 148 } 149 } 150 151 @SuppressWarnings("all") 152 public static boolean currentThread(Thread other) { 153 return Thread.currentThread() == other; 154 } 155 156 @SuppressWarnings("all") 157 public static boolean threadIsInterrupted(Thread thread) { 158 return thread.isInterrupted(); 159 } 160 161 @SuppressWarnings("all") 162 public static boolean threadInterrupted() { 163 return Thread.interrupted(); 164 } 165 166 @Test 167 public void testSystemSubstitutions() { 168 testGraph("systemTime"); 169 testGraph("systemIdentityHashCode"); 170 171 for (Object o : new Object[]{this, new int[5], new String[2][], new Object()}) { 172 test("systemIdentityHashCode", o); 173 } 174 } 175 176 @SuppressWarnings("all") 177 public static long systemTime() { 178 return System.currentTimeMillis() + System.nanoTime(); 179 } 180 181 @SuppressWarnings("all") 182 public static int systemIdentityHashCode(Object obj) { 183 return System.identityHashCode(obj); 184 } 185 186 private static class TestClassA { 187 } 188 189 public static String testCallSiteGetTargetSnippet(int i) throws Exception { 190 ConstantCallSite site; 191 MethodHandles.Lookup lookup = MethodHandles.lookup(); 192 switch (i) { 193 case 1: 194 site = GraalDirectives.opaque(new ConstantCallSite(lookup.findVirtual(String.class, "replace", MethodType.methodType(String.class, char.class, char.class)))); 195 break; 196 default: 197 site = GraalDirectives.opaque(new ConstantCallSite(lookup.findStatic(java.util.Arrays.class, "asList", MethodType.methodType(java.util.List.class, Object[].class)))); 198 } 199 return site.getTarget().toString(); 200 } 201 202 public static String testCastSnippet(int i, Object obj) throws Exception { 203 Class<?> c; 204 switch (i) { 205 case 1: 206 c = GraalDirectives.opaque(Number.class); 207 break; 208 default: 209 c = GraalDirectives.opaque(Integer.class); 210 break; 211 } 212 return c.cast(obj).toString(); 213 } 214 215 public static String testGetClassSnippet(int i) { 216 Object c; 217 switch (i) { 218 case 1: 219 c = GraalDirectives.opaque(new Object()); 220 break; 221 default: 222 c = GraalDirectives.opaque("TEST"); 223 break; 224 } 225 return c.getClass().toString(); 226 } 227 228 /** 229 * Tests ambiguous receiver of CallSite.getTarget. 230 */ 231 @Test 232 public void testCallSiteGetTarget() { 233 test("testCallSiteGetTargetSnippet", 1); 234 } 235 236 /** 237 * Tests ambiguous receiver of Class.cast. 238 */ 239 @Test 240 public void testCast() { 241 test("testCastSnippet", 1, Integer.valueOf(1)); 242 } 243 244 /** 245 * Tests ambiguous receiver of Object.getClass. 246 */ 247 @Test 248 public void testGetClass() { 249 test("testGetClassSnippet", 1); 250 } 251 }