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 
  27 import java.lang.reflect.Method;
  28 import java.lang.reflect.Modifier;
  29 
  30 import org.graalvm.compiler.api.test.Graal;
  31 import org.graalvm.compiler.debug.DebugCloseable;
  32 import org.graalvm.compiler.debug.DebugHandlersFactory;
  33 import org.graalvm.compiler.debug.DebugContext;
  34 import org.graalvm.compiler.debug.GraalError;
  35 import org.graalvm.compiler.debug.Indent;
  36 import org.graalvm.compiler.graph.Node;
  37 import org.graalvm.compiler.java.GraphBuilderPhase;
  38 import org.graalvm.compiler.nodes.StructuredGraph;
  39 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  40 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  41 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  42 import org.graalvm.compiler.options.OptionValues;
  43 import org.graalvm.compiler.phases.OptimisticOptimizations;
  44 import org.graalvm.compiler.phases.Phase;
  45 import org.graalvm.compiler.phases.PhaseSuite;
  46 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
  47 import org.graalvm.compiler.phases.tiers.HighTierContext;
  48 import org.graalvm.compiler.phases.util.Providers;
  49 import org.graalvm.compiler.phases.verify.VerifyDebugUsage;
  50 import org.graalvm.compiler.runtime.RuntimeProvider;
  51 import org.junit.Test;
  52 
  53 import jdk.vm.ci.meta.MetaAccessProvider;
  54 import jdk.vm.ci.meta.ResolvedJavaMethod;
  55 
  56 public class VerifyDebugUsageTest {
  57 
  58     private static class InvalidLogUsagePhase extends Phase {
  59 
  60         @Override
  61         protected void run(StructuredGraph graph) {
  62             DebugContext debug = graph.getDebug();
  63             for (Node n : graph.getNodes()) {
  64                 debug.log("%s", n.toString());
  65             }
  66         }
  67 
  68     }
  69 
  70     private static class InvalidLogAndIndentUsagePhase extends Phase {
  71 
  72         @Override
  73         @SuppressWarnings("try")
  74         protected void run(StructuredGraph graph) {
  75             DebugContext debug = graph.getDebug();
  76             try (Indent i = debug.logAndIndent("%s", graph.toString())) {
  77                 for (Node n : graph.getNodes()) {
  78                     debug.log("%s", n);
  79                 }
  80             }
  81         }
  82 
  83     }
  84 
  85     private static class InvalidDumpUsagePhase extends Phase {
  86 
  87         @Override
  88         protected void run(StructuredGraph graph) {
  89             DebugContext debug = graph.getDebug();
  90             debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph.toString());
  91         }
  92     }
  93 
  94     private static class InvalidDumpLevelPhase extends Phase {
  95 
  96         @Override
  97         protected void run(StructuredGraph graph) {
  98             DebugContext debug = graph.getDebug();
  99             debug.dump(DebugContext.VERY_DETAILED_LEVEL + 1, graph, "%s", graph);
 100         }
 101     }
 102 
 103     private static class NonConstantDumpLevelPhase extends Phase {
 104 
 105         @Override
 106         protected void run(StructuredGraph graph) {
 107             DebugContext debug = graph.getDebug();
 108             debug.dump(getLevel(), graph, "%s", graph);
 109         }
 110 
 111         int getLevel() {
 112             return 10;
 113         }
 114     }
 115 
 116     private static class InvalidVerifyUsagePhase extends Phase {
 117 
 118         @Override
 119         protected void run(StructuredGraph graph) {
 120             DebugContext debug = graph.getDebug();
 121             debug.verify(graph, "%s", graph.toString());
 122         }
 123 
 124     }
 125 
 126     private static class InvalidConcatLogUsagePhase extends Phase {
 127 
 128         @Override
 129         protected void run(StructuredGraph graph) {
 130             DebugContext debug = graph.getDebug();
 131             for (Node n : graph.getNodes()) {
 132                 debug.log("error " + n);
 133             }
 134         }
 135 
 136     }
 137 
 138     private static class InvalidConcatLogAndIndentUsagePhase extends Phase {
 139 
 140         @Override
 141         @SuppressWarnings("try")
 142         protected void run(StructuredGraph graph) {
 143             DebugContext debug = graph.getDebug();
 144             try (Indent i = debug.logAndIndent("error " + graph)) {
 145                 for (Node n : graph.getNodes()) {
 146                     debug.log("%s", n);
 147                 }
 148             }
 149         }
 150 
 151     }
 152 
 153     private static class InvalidConcatDumpUsagePhase extends Phase {
 154 
 155         @Override
 156         protected void run(StructuredGraph graph) {
 157             DebugContext debug = graph.getDebug();
 158             debug.dump(DebugContext.BASIC_LEVEL, graph, "error " + graph);
 159         }
 160 
 161     }
 162 
 163     private static class InvalidConcatVerifyUsagePhase extends Phase {
 164 
 165         @Override
 166         protected void run(StructuredGraph graph) {
 167             DebugContext debug = graph.getDebug();
 168             debug.verify(graph, "error " + graph);
 169         }
 170 
 171     }
 172 
 173     private static class ValidLogUsagePhase extends Phase {
 174 
 175         @Override
 176         protected void run(StructuredGraph graph) {
 177             DebugContext debug = graph.getDebug();
 178             for (Node n : graph.getNodes()) {
 179                 debug.log("%s", n);
 180             }
 181         }
 182 
 183     }
 184 
 185     private static class ValidLogAndIndentUsagePhase extends Phase {
 186 
 187         @Override
 188         @SuppressWarnings("try")
 189         protected void run(StructuredGraph graph) {
 190             DebugContext debug = graph.getDebug();
 191             try (Indent i = debug.logAndIndent("%s", graph)) {
 192                 for (Node n : graph.getNodes()) {
 193                     debug.log("%s", n);
 194                 }
 195             }
 196         }
 197 
 198     }
 199 
 200     private static class ValidDumpUsagePhase extends Phase {
 201 
 202         @Override
 203         protected void run(StructuredGraph graph) {
 204             DebugContext debug = graph.getDebug();
 205             debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph);
 206         }
 207 
 208     }
 209 
 210     private static class ValidVerifyUsagePhase extends Phase {
 211 
 212         @Override
 213         protected void run(StructuredGraph graph) {
 214             DebugContext debug = graph.getDebug();
 215             debug.verify(graph, "%s", graph);
 216         }
 217 
 218     }
 219 
 220     private static class InvalidGraalErrorGuaranteePhase extends Phase {
 221         @Override
 222         protected void run(StructuredGraph graph) {
 223             GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph.toString());
 224         }
 225     }
 226 
 227     private static class ValidGraalErrorGuaranteePhase extends Phase {
 228         @Override
 229         protected void run(StructuredGraph graph) {
 230             GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s", graph);
 231         }
 232     }
 233 
 234     public static Object sideEffect;
 235 
 236     private static class InvalidGraalErrorCtorPhase extends Phase {
 237         @Override
 238         protected void run(StructuredGraph graph) {
 239             sideEffect = new GraalError("No Error %s", graph.toString());
 240         }
 241     }
 242 
 243     private static class ValidGraalErrorCtorPhase extends Phase {
 244         @Override
 245         protected void run(StructuredGraph graph) {
 246             sideEffect = new GraalError("Error %s", graph);
 247         }
 248     }
 249 
 250     @Test(expected = VerificationError.class)
 251     public void testLogInvalid() {
 252         testDebugUsageClass(InvalidLogUsagePhase.class);
 253     }
 254 
 255     @Test(expected = VerificationError.class)
 256     public void testLogAndIndentInvalid() {
 257         testDebugUsageClass(InvalidLogAndIndentUsagePhase.class);
 258     }
 259 
 260     @Test(expected = VerificationError.class)
 261     public void testVerifyInvalid() {
 262         testDebugUsageClass(InvalidVerifyUsagePhase.class);
 263     }
 264 
 265     @Test(expected = VerificationError.class)
 266     public void testDumpInvalid() {
 267         testDebugUsageClass(InvalidDumpUsagePhase.class);
 268     }
 269 
 270     @Test(expected = VerificationError.class)
 271     public void testDumpLevelInvalid() {
 272         testDebugUsageClass(InvalidDumpLevelPhase.class);
 273     }
 274 
 275     @Test(expected = VerificationError.class)
 276     public void testDumpNonConstantLevelInvalid() {
 277         testDebugUsageClass(NonConstantDumpLevelPhase.class);
 278     }
 279 
 280     @Test(expected = VerificationError.class)
 281     public void testLogInvalidConcat() {
 282         testDebugUsageClass(InvalidConcatLogUsagePhase.class);
 283     }
 284 
 285     @Test(expected = VerificationError.class)
 286     public void testLogAndIndentInvalidConcat() {
 287         testDebugUsageClass(InvalidConcatLogAndIndentUsagePhase.class);
 288     }
 289 
 290     @Test(expected = VerificationError.class)
 291     public void testVerifyInvalidConcat() {
 292         testDebugUsageClass(InvalidConcatVerifyUsagePhase.class);
 293     }
 294 
 295     @Test(expected = VerificationError.class)
 296     public void testDumpInvalidConcat() {
 297         testDebugUsageClass(InvalidConcatDumpUsagePhase.class);
 298     }
 299 
 300     @Test
 301     public void testLogValid() {
 302         testDebugUsageClass(ValidLogUsagePhase.class);
 303     }
 304 
 305     @Test()
 306     public void testLogAndIndentValid() {
 307         testDebugUsageClass(ValidLogAndIndentUsagePhase.class);
 308     }
 309 
 310     @Test
 311     public void testVerifyValid() {
 312         testDebugUsageClass(ValidVerifyUsagePhase.class);
 313     }
 314 
 315     @Test
 316     public void testDumpValid() {
 317         testDebugUsageClass(ValidDumpUsagePhase.class);
 318     }
 319 
 320     @Test(expected = VerificationError.class)
 321     public void testGraalGuaranteeInvalid() {
 322         testDebugUsageClass(InvalidGraalErrorGuaranteePhase.class);
 323     }
 324 
 325     @Test
 326     public void testGraalGuaranteeValid() {
 327         testDebugUsageClass(ValidGraalErrorGuaranteePhase.class);
 328     }
 329 
 330     @Test(expected = VerificationError.class)
 331     public void testGraalCtorInvalid() {
 332         testDebugUsageClass(InvalidGraalErrorCtorPhase.class);
 333     }
 334 
 335     @Test
 336     public void testGraalCtorValid() {
 337         testDebugUsageClass(ValidGraalErrorCtorPhase.class);
 338     }
 339 
 340     @SuppressWarnings("try")
 341     private static void testDebugUsageClass(Class<?> c) {
 342         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
 343         Providers providers = rt.getHostBackend().getProviders();
 344         MetaAccessProvider metaAccess = providers.getMetaAccess();
 345         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
 346         Plugins plugins = new Plugins(new InvocationPlugins());
 347         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
 348         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
 349         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
 350         OptionValues options = getInitialOptions();
 351         DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
 352         for (Method m : c.getDeclaredMethods()) {
 353             if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
 354                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
 355                 StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
 356                 graphBuilderSuite.apply(graph, context);
 357                 try (DebugCloseable s = debug.disableIntercept()) {
 358                     new VerifyDebugUsage().apply(graph, context);
 359                 }
 360             }
 361         }
 362     }
 363 }