1 /*
   2  * Copyright (c) 2015, 2016, 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 package org.graalvm.compiler.core.test;
  24 
  25 import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions;
  26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
  27 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
  28 
  29 import java.lang.reflect.Method;
  30 import java.lang.reflect.Modifier;
  31 
  32 import org.junit.Test;
  33 
  34 import org.graalvm.compiler.api.test.Graal;
  35 import org.graalvm.compiler.core.common.type.StampFactory;
  36 import org.graalvm.compiler.debug.Debug;
  37 import org.graalvm.compiler.debug.DebugConfigScope;
  38 import org.graalvm.compiler.graph.NodeClass;
  39 import org.graalvm.compiler.java.GraphBuilderPhase;
  40 import org.graalvm.compiler.nodeinfo.NodeInfo;
  41 import org.graalvm.compiler.nodes.ConstantNode;
  42 import org.graalvm.compiler.nodes.StructuredGraph;
  43 import org.graalvm.compiler.nodes.ValueNode;
  44 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  45 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  46 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  47 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
  48 import org.graalvm.compiler.nodes.spi.Virtualizable;
  49 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
  50 import org.graalvm.compiler.phases.OptimisticOptimizations;
  51 import org.graalvm.compiler.phases.PhaseSuite;
  52 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
  53 import org.graalvm.compiler.phases.tiers.HighTierContext;
  54 import org.graalvm.compiler.phases.util.Providers;
  55 import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage;
  56 import org.graalvm.compiler.runtime.RuntimeProvider;
  57 
  58 import jdk.vm.ci.meta.MetaAccessProvider;
  59 import jdk.vm.ci.meta.ResolvedJavaMethod;
  60 
  61 public class VerifyVirtualizableTest {
  62 
  63     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
  64     static class InvalidEffectNodeAdd extends ValueNode implements Virtualizable {
  65 
  66         public static final NodeClass<InvalidEffectNodeAdd> TYPE = NodeClass.create(InvalidEffectNodeAdd.class);
  67 
  68         protected InvalidEffectNodeAdd() {
  69             super(TYPE, StampFactory.forVoid());
  70         }
  71 
  72         @Override
  73         public void virtualize(VirtualizerTool tool) {
  74             graph().add(new ArrayLengthNode(null));
  75         }
  76     }
  77 
  78     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
  79     static class InvalidEffectNodeAddWithoutUnique extends ValueNode implements Virtualizable {
  80 
  81         public static final NodeClass<InvalidEffectNodeAddWithoutUnique> TYPE = NodeClass.create(InvalidEffectNodeAddWithoutUnique.class);
  82 
  83         protected InvalidEffectNodeAddWithoutUnique() {
  84             super(TYPE, StampFactory.forVoid());
  85         }
  86 
  87         @Override
  88         public void virtualize(VirtualizerTool tool) {
  89             graph().addWithoutUnique(new ArrayLengthNode(null));
  90         }
  91     }
  92 
  93     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
  94     static class InvalidEffectNodeAddOrUnique extends ValueNode implements Virtualizable {
  95 
  96         public static final NodeClass<InvalidEffectNodeAddOrUnique> TYPE = NodeClass.create(InvalidEffectNodeAddOrUnique.class);
  97 
  98         protected InvalidEffectNodeAddOrUnique() {
  99             super(TYPE, StampFactory.forVoid());
 100         }
 101 
 102         @Override
 103         public void virtualize(VirtualizerTool tool) {
 104             graph().addOrUnique(new ArrayLengthNode(null));
 105         }
 106     }
 107 
 108     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 109     static class InvalidEffectNodeAddWithoutUniqueWithInputs extends ValueNode implements Virtualizable {
 110 
 111         public static final NodeClass<InvalidEffectNodeAddWithoutUniqueWithInputs> TYPE = NodeClass.create(InvalidEffectNodeAddWithoutUniqueWithInputs.class);
 112 
 113         protected InvalidEffectNodeAddWithoutUniqueWithInputs() {
 114             super(TYPE, StampFactory.forVoid());
 115         }
 116 
 117         @Override
 118         public void virtualize(VirtualizerTool tool) {
 119             graph().addOrUnique(new ArrayLengthNode(null));
 120         }
 121     }
 122 
 123     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 124     static class InvalidEffectNodeAddOrUniqueWithInputs extends ValueNode implements Virtualizable {
 125 
 126         public static final NodeClass<InvalidEffectNodeAddOrUniqueWithInputs> TYPE = NodeClass.create(InvalidEffectNodeAddOrUniqueWithInputs.class);
 127 
 128         protected InvalidEffectNodeAddOrUniqueWithInputs() {
 129             super(TYPE, StampFactory.forVoid());
 130         }
 131 
 132         @Override
 133         public void virtualize(VirtualizerTool tool) {
 134             graph().addOrUnique(new ArrayLengthNode(null));
 135         }
 136     }
 137 
 138     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 139     static class ValidEffectNodeAdd extends ValueNode implements Virtualizable {
 140 
 141         public static final NodeClass<ValidEffectNodeAdd> TYPE = NodeClass.create(ValidEffectNodeAdd.class);
 142 
 143         protected ValidEffectNodeAdd() {
 144             super(TYPE, StampFactory.forVoid());
 145         }
 146 
 147         @Override
 148         public void virtualize(VirtualizerTool tool) {
 149             graph().add(ConstantNode.forBoolean(false));
 150         }
 151     }
 152 
 153     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 154     static class ValidEffectNodeAddWithoutUnique extends ValueNode implements Virtualizable {
 155 
 156         public static final NodeClass<ValidEffectNodeAddWithoutUnique> TYPE = NodeClass.create(ValidEffectNodeAddWithoutUnique.class);
 157 
 158         protected ValidEffectNodeAddWithoutUnique() {
 159             super(TYPE, StampFactory.forVoid());
 160         }
 161 
 162         @Override
 163         public void virtualize(VirtualizerTool tool) {
 164             graph().addWithoutUnique(ConstantNode.forBoolean(false));
 165         }
 166     }
 167 
 168     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 169     static class ValidEffectNodeAddOrUnique extends ValueNode implements Virtualizable {
 170 
 171         public static final NodeClass<ValidEffectNodeAddOrUnique> TYPE = NodeClass.create(ValidEffectNodeAddOrUnique.class);
 172 
 173         protected ValidEffectNodeAddOrUnique() {
 174             super(TYPE, StampFactory.forVoid());
 175         }
 176 
 177         @Override
 178         public void virtualize(VirtualizerTool tool) {
 179             graph().addOrUnique(ConstantNode.forBoolean(false));
 180         }
 181     }
 182 
 183     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 184     static class ValidEffectNodeAddWithoutUniqueWithInputs extends ValueNode implements Virtualizable {
 185 
 186         public static final NodeClass<ValidEffectNodeAddWithoutUniqueWithInputs> TYPE = NodeClass.create(ValidEffectNodeAddWithoutUniqueWithInputs.class);
 187 
 188         protected ValidEffectNodeAddWithoutUniqueWithInputs() {
 189             super(TYPE, StampFactory.forVoid());
 190         }
 191 
 192         @Override
 193         public void virtualize(VirtualizerTool tool) {
 194             graph().addOrUnique(ConstantNode.forBoolean(false));
 195         }
 196     }
 197 
 198     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 199     static class ValidEffectNodeAddOrUniqueWithInputs extends ValueNode implements Virtualizable {
 200 
 201         public static final NodeClass<ValidEffectNodeAddOrUniqueWithInputs> TYPE = NodeClass.create(ValidEffectNodeAddOrUniqueWithInputs.class);
 202 
 203         protected ValidEffectNodeAddOrUniqueWithInputs() {
 204             super(TYPE, StampFactory.forVoid());
 205         }
 206 
 207         @Override
 208         public void virtualize(VirtualizerTool tool) {
 209             graph().addOrUnique(ConstantNode.forBoolean(false));
 210         }
 211     }
 212 
 213     @Test(expected = VerificationError.class)
 214     public void testInvalidAdd() {
 215         testVirtualizableEffects(InvalidEffectNodeAdd.class);
 216     }
 217 
 218     @Test(expected = VerificationError.class)
 219     public void testInvalidAddWithoutUnique() {
 220         testVirtualizableEffects(InvalidEffectNodeAddWithoutUnique.class);
 221     }
 222 
 223     @Test(expected = VerificationError.class)
 224     public void testInvalidAddOrUnique() {
 225         testVirtualizableEffects(InvalidEffectNodeAddOrUnique.class);
 226     }
 227 
 228     @Test(expected = VerificationError.class)
 229     public void testInvalidAddWithoutUniqueWithInputs() {
 230         testVirtualizableEffects(InvalidEffectNodeAddWithoutUniqueWithInputs.class);
 231     }
 232 
 233     @Test(expected = VerificationError.class)
 234     public void testInvalidAddOrUniqueWithInputs() {
 235         testVirtualizableEffects(InvalidEffectNodeAddOrUniqueWithInputs.class);
 236     }
 237 
 238     @Test
 239     public void testValidAdd() {
 240         testVirtualizableEffects(ValidEffectNodeAdd.class);
 241     }
 242 
 243     @Test
 244     public void testValidAddWithoutUnique() {
 245         testVirtualizableEffects(ValidEffectNodeAddWithoutUnique.class);
 246     }
 247 
 248     @Test
 249     public void testValidAddOrUnique() {
 250         testVirtualizableEffects(ValidEffectNodeAddOrUnique.class);
 251     }
 252 
 253     @Test
 254     public void testValidAddWithoutUniqueWithInputs() {
 255         testVirtualizableEffects(ValidEffectNodeAddWithoutUniqueWithInputs.class);
 256     }
 257 
 258     @Test
 259     public void testValidAddOrUniqueWithInputs() {
 260         testVirtualizableEffects(ValidEffectNodeAddOrUniqueWithInputs.class);
 261     }
 262 
 263     @SuppressWarnings("try")
 264     private static void testVirtualizableEffects(Class<?> c) {
 265         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
 266         Providers providers = rt.getHostBackend().getProviders();
 267         MetaAccessProvider metaAccess = providers.getMetaAccess();
 268         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
 269         Plugins plugins = new Plugins(new InvocationPlugins());
 270         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
 271         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
 272         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
 273         for (Method m : c.getDeclaredMethods()) {
 274             if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
 275                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
 276                 StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build();
 277                 graphBuilderSuite.apply(graph, context);
 278                 try (DebugConfigScope s = Debug.disableIntercept()) {
 279                     new VerifyVirtualizableUsage().apply(graph, context);
 280                 }
 281             }
 282         }
 283     }
 284 }