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