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