1 /*
   2  * Copyright (c) 2014, 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 package org.graalvm.compiler.hotspot.test;
  25 
  26 import org.graalvm.compiler.core.test.GraalCompilerTest;
  27 import org.graalvm.compiler.debug.DebugContext;
  28 import org.graalvm.compiler.graph.Node;
  29 import org.graalvm.compiler.nodes.Invoke;
  30 import org.graalvm.compiler.nodes.ReturnNode;
  31 import org.graalvm.compiler.nodes.StructuredGraph;
  32 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  33 import org.junit.Test;
  34 
  35 public class ClassSubstitutionsTests extends GraalCompilerTest {
  36 
  37     public Number instanceField;
  38 
  39     public Object[] arrayField;
  40 
  41     public String[] stringArrayField;
  42 
  43     @SuppressWarnings("try")
  44     protected StructuredGraph test(final String snippet) {
  45         DebugContext debug = getDebugContext();
  46         try (DebugContext.Scope s = debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
  47             StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
  48             compile(graph.method(), graph);
  49             assertNotInGraph(graph, Invoke.class);
  50             debug.dump(DebugContext.BASIC_LEVEL, graph, snippet);
  51             return graph;
  52         } catch (Throwable e) {
  53             throw debug.handle(e);
  54         }
  55     }
  56 
  57     protected static StructuredGraph assertNotInGraph(StructuredGraph graph, Class<?> clazz) {
  58         for (Node node : graph.getNodes()) {
  59             if (clazz.isInstance(node)) {
  60                 fail(node.toString());
  61             }
  62         }
  63         return graph;
  64     }
  65 
  66     public boolean constantIsArray() {
  67         return "".getClass().isArray();
  68     }
  69 
  70     public boolean constantIsInterface() {
  71         return "".getClass().isInterface();
  72     }
  73 
  74     public boolean constantIsPrimitive() {
  75         return "".getClass().isPrimitive();
  76     }
  77 
  78     @Test
  79     public void testIsArray() {
  80         testConstantReturn("constantIsArray", 0);
  81     }
  82 
  83     @Test
  84     public void testIsInterface() {
  85         testConstantReturn("constantIsInterface", 0);
  86     }
  87 
  88     @Test
  89     public void testIsPrimitive() {
  90         testConstantReturn("constantIsPrimitive", 0);
  91     }
  92 
  93     public boolean fieldIsNotArray() {
  94         if (instanceField != null) {
  95             // The base type of instanceField is not Object or an Interface, so it's provably an
  96             // instance type, so isArray will always return false.
  97             return instanceField.getClass().isArray();
  98         }
  99         return false;
 100     }
 101 
 102     @Test
 103     public void testFieldIsNotArray() {
 104         testConstantReturn("fieldIsNotArray", 0);
 105     }
 106 
 107     public boolean foldComponentType() {
 108         return stringArrayField.getClass().getComponentType() == String.class;
 109     }
 110 
 111     @Test
 112     public void testFoldComponentType() {
 113         testConstantReturn("foldComponentType", 1);
 114     }
 115 
 116     @Test
 117     public void testFieldIsArray() {
 118         testConstantReturn("fieldIsArray", 1);
 119     }
 120 
 121     public boolean fieldIsArray() {
 122         if (arrayField != null) {
 123             // The base type of arrayField is an array of some sort so isArray will always return
 124             // true.
 125             return arrayField.getClass().isArray();
 126         }
 127         return true;
 128     }
 129 
 130     private static class A {
 131     }
 132 
 133     private static class B extends A {
 134     }
 135 
 136     private static class C {
 137     }
 138 
 139     private static final A a = new A();
 140     private static final B b = new B();
 141     private static final C c = new C();
 142 
 143     public boolean classIsAssignable1() {
 144         return a.getClass().isAssignableFrom(a.getClass());
 145     }
 146 
 147     public boolean classIsAssignable2() {
 148         return a.getClass().isAssignableFrom(b.getClass());
 149     }
 150 
 151     public boolean classIsAssignable3() {
 152         return a.getClass().isAssignableFrom(c.getClass());
 153     }
 154 
 155     public boolean classIsAssignable4() {
 156         return b.getClass().isAssignableFrom(a.getClass());
 157     }
 158 
 159     public boolean classIsAssignable5() {
 160         return c.getClass().isAssignableFrom(b.getClass());
 161     }
 162 
 163     public boolean classIsAssignable6() {
 164         return int.class.isAssignableFrom(b.getClass());
 165     }
 166 
 167     public boolean classIsAssignable7() {
 168         return int.class.isAssignableFrom(int.class);
 169     }
 170 
 171     @Test
 172     public void testClassIsAssignable() {
 173         testConstantReturn("classIsAssignable1", 1);
 174         testConstantReturn("classIsAssignable2", 1);
 175         testConstantReturn("classIsAssignable3", 0);
 176         testConstantReturn("classIsAssignable4", 0);
 177         testConstantReturn("classIsAssignable5", 0);
 178         testConstantReturn("classIsAssignable6", 0);
 179         testConstantReturn("classIsAssignable7", 1);
 180     }
 181 
 182     private void testConstantReturn(String name, Object value) {
 183         StructuredGraph result = test(name);
 184         ReturnNode ret = result.getNodes(ReturnNode.TYPE).first();
 185         assertDeepEquals(1, result.getNodes(ReturnNode.TYPE).count());
 186 
 187         assertDeepEquals(true, ret.result().isConstant());
 188         assertDeepEquals(value, ret.result().asJavaConstant().asBoxedPrimitive());
 189     }
 190 }