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