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