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.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 }