1 /*
   2  * Copyright (c) 2017, 2017, 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.core.test;
  26 
  27 import static org.hamcrest.CoreMatchers.instanceOf;
  28 import static org.hamcrest.CoreMatchers.is;
  29 
  30 import jdk.vm.ci.meta.ResolvedJavaType;
  31 import org.graalvm.compiler.api.directives.GraalDirectives;
  32 import org.graalvm.compiler.core.common.type.Stamp;
  33 import org.graalvm.compiler.nodeinfo.Verbosity;
  34 import org.graalvm.compiler.nodes.StructuredGraph;
  35 import org.graalvm.compiler.nodes.ValueNode;
  36 import org.graalvm.compiler.nodes.debug.BlackholeNode;
  37 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
  38 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
  39 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
  40 import org.graalvm.compiler.nodes.type.StampTool;
  41 import org.junit.Assert;
  42 import org.junit.BeforeClass;
  43 import org.junit.Test;
  44 
  45 import jdk.vm.ci.meta.ResolvedJavaMethod;
  46 
  47 public class UncheckedInterfaceProviderTest extends GraalCompilerTest {
  48     private Runnable interfaceField;
  49     private Runnable[] interfaceArrayField;
  50 
  51     public void snippet(Runnable interfaceParameter, Runnable[] interfaceArrayParameter) {
  52         GraalDirectives.blackhole(interfaceParameter);
  53         GraalDirectives.blackhole(interfaceArrayParameter);
  54         GraalDirectives.blackhole(interfaceField);
  55         GraalDirectives.blackhole(interfaceArrayField);
  56         GraalDirectives.blackhole(interfaceReturn());
  57         GraalDirectives.blackhole(interfaceArrayReturn());
  58         GraalDirectives.blackhole(interfaceReturnException());
  59         GraalDirectives.blackhole(interfaceArrayReturnException());
  60     }
  61 
  62     public static Runnable interfaceReturn() {
  63         return new A();
  64     }
  65 
  66     public static Runnable[] interfaceArrayReturn() {
  67         return new Runnable[]{new A(), new B(), new C(), new D()};
  68     }
  69 
  70     public static Runnable interfaceReturnException() {
  71         return new A();
  72     }
  73 
  74     public static Runnable[] interfaceArrayReturnException() {
  75         return new Runnable[]{new A(), new B(), new C(), new D()};
  76     }
  77 
  78     @Override
  79     protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
  80         if (method.getName().startsWith("interfaceReturn") || method.getName().startsWith("interfaceArrayReturn")) {
  81             if (method.getName().equals("Exception")) {
  82                 return InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
  83             }
  84             return InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
  85         }
  86         return super.bytecodeParserShouldInlineInvoke(b, method, args);
  87     }
  88 
  89     @BeforeClass
  90     public static void setup() {
  91         interfaceArrayReturn();
  92     }
  93 
  94     @Test
  95     public void test() {
  96         StructuredGraph graph = parseEager("snippet", StructuredGraph.AllowAssumptions.YES);
  97         for (BlackholeNode b : graph.getNodes().filter(BlackholeNode.class)) {
  98             Assert.assertThat(b.getValue(), is(instanceOf(UncheckedInterfaceProvider.class)));
  99             Stamp uncheckedStamp = ((UncheckedInterfaceProvider) b.getValue()).uncheckedStamp();
 100             String context = b.getValue().toString(Verbosity.Debugger);
 101             Assert.assertNotNull(context, uncheckedStamp);
 102             ResolvedJavaType uncheckedType = StampTool.typeOrNull(uncheckedStamp);
 103             ResolvedJavaType type = StampTool.typeOrNull(b.getValue());
 104             Assert.assertEquals(context, arrayDepth(type), arrayDepth(uncheckedType));
 105             Assert.assertTrue(context + ": " + type, type == null || type.getElementalType().isJavaLangObject());
 106             Assert.assertNotNull(context, uncheckedType);
 107             Assert.assertTrue(context, uncheckedType.getElementalType().isInterface());
 108         }
 109     }
 110 
 111     private static int arrayDepth(ResolvedJavaType type) {
 112         int depth = 0;
 113         ResolvedJavaType t = type;
 114         while (t != null && t.isArray()) {
 115             depth += 1;
 116             t = t.getComponentType();
 117         }
 118         return depth;
 119     }
 120 
 121     public static class A implements Runnable {
 122         @Override
 123         public void run() {
 124             // nop
 125         }
 126     }
 127 
 128     public static class B implements Runnable {
 129         @Override
 130         public void run() {
 131             // nop
 132         }
 133     }
 134 
 135     public static class C implements Runnable {
 136         @Override
 137         public void run() {
 138             // nop
 139         }
 140     }
 141 
 142     public static class D implements Runnable {
 143         @Override
 144         public void run() {
 145             // nop
 146         }
 147     }
 148 }