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 */
23package org.graalvm.compiler.core.test.debug;
24
25import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
26
27import java.lang.reflect.Method;
28import java.lang.reflect.Modifier;
29
30import org.junit.Test;
31
32import org.graalvm.compiler.api.test.Graal;
33import org.graalvm.compiler.debug.Debug;
34import org.graalvm.compiler.debug.DebugConfigScope;
35import org.graalvm.compiler.debug.DebugMethodMetrics;
36import org.graalvm.compiler.graph.Node;
37import org.graalvm.compiler.java.GraphBuilderPhase;
38import org.graalvm.compiler.nodes.StructuredGraph;
39import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
40import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
41import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
42import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
43import org.graalvm.compiler.phases.OptimisticOptimizations;
44import org.graalvm.compiler.phases.Phase;
45import org.graalvm.compiler.phases.PhaseSuite;
46import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
47import org.graalvm.compiler.phases.tiers.HighTierContext;
48import org.graalvm.compiler.phases.util.Providers;
49import org.graalvm.compiler.phases.verify.VerifyDebugUsage;
50import org.graalvm.compiler.runtime.RuntimeProvider;
51
52import jdk.vm.ci.meta.MetaAccessProvider;
53import jdk.vm.ci.meta.ResolvedJavaMethod;
54
55/**
56 *
57 * Tests to verify that the usage of method metrics does not generate compile time overhead through
58 * eager evaluation of arguments.
59 */
60public class VerifyMethodMetricsTest {
61
62    private static class InvalidCCP_ToString01Inc extends Phase {
63        @Override
64        protected void run(StructuredGraph graph) {
65            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
66            for (Node n : graph.getNodes()) {
67                m.incrementMetric(n.toString());
68            }
69        }
70    }
71
72    private static class InvalidCCP_Concat01Inc extends Phase {
73        @Override
74        protected void run(StructuredGraph graph) {
75            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
76            for (Node n : graph.getNodes()) {
77                m.incrementMetric("a" + n.toString());
78            }
79        }
80    }
81
82    private static class InvalidCCP_ToString02Inc extends Phase {
83        @Override
84        protected void run(StructuredGraph graph) {
85            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
86            for (Node n : graph.getNodes()) {
87                m.incrementMetric("%s", n.toString());
88            }
89        }
90    }
91
92    private static class InvalidCCP_Concat02Inc extends Phase {
93        private final String s = this.getClass().toGenericString();
94
95        @Override
96        protected void run(StructuredGraph graph) {
97            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
98            for (Node n : graph.getNodes()) {
99                m.incrementMetric("%s%s", "a" + s, n);
100            }
101        }
102    }
103
104    private static class ValidCCP_ToStringInc extends Phase {
105        @Override
106        protected void run(StructuredGraph graph) {
107            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
108            for (Node n : graph.getNodes()) {
109                m.addToMetric(1, "%s", n);
110            }
111        }
112    }
113
114    private static class ValidCCP_ConcatInc extends Phase {
115        @Override
116        protected void run(StructuredGraph graph) {
117            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
118            for (Node n : graph.getNodes()) {
119                m.incrementMetric("%s%s", "a", n);
120            }
121        }
122    }
123
124    private static class InvalidCCP_ToString01Add extends Phase {
125        @Override
126        protected void run(StructuredGraph graph) {
127            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
128            for (Node n : graph.getNodes()) {
129                m.addToMetric(1, n.toString());
130            }
131        }
132    }
133
134    private static class InvalidCCP_Concat01Add extends Phase {
135        @Override
136        protected void run(StructuredGraph graph) {
137            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
138            for (Node n : graph.getNodes()) {
139                m.addToMetric(1, "a" + n.toString());
140            }
141        }
142    }
143
144    private static class InvalidCCP_ToString02Add extends Phase {
145        @Override
146        protected void run(StructuredGraph graph) {
147            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
148            for (Node n : graph.getNodes()) {
149                m.addToMetric(1, "%s", n.toString());
150            }
151        }
152    }
153
154    private static class InvalidCCP_Concat02Add extends Phase {
155        private final String s = this.getClass().toGenericString();
156
157        @Override
158        protected void run(StructuredGraph graph) {
159            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
160            for (Node n : graph.getNodes()) {
161                m.addToMetric(1, "%s%s", "a" + s, n);
162            }
163        }
164    }
165
166    private static class ValidCCP_ToStringAdd extends Phase {
167        @Override
168        protected void run(StructuredGraph graph) {
169            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
170            for (Node n : graph.getNodes()) {
171                m.addToMetric(1, "%s", n);
172            }
173        }
174    }
175
176    private static class ValidCCP_ConcatAdd extends Phase {
177        @Override
178        protected void run(StructuredGraph graph) {
179            DebugMethodMetrics m = Debug.methodMetrics(graph.method());
180            for (Node n : graph.getNodes()) {
181                m.addToMetric(1, "%s%s", "a", n);
182            }
183        }
184    }
185
186    @Test(expected = VerificationError.class)
187    public void testLogInvalidToString01Add() {
188        testDebugUsageClass(InvalidCCP_ToString01Add.class);
189    }
190
191    @Test(expected = VerificationError.class)
192    public void testLogInvalidConcat01Add() {
193        testDebugUsageClass(InvalidCCP_Concat01Add.class);
194    }
195
196    @Test(expected = VerificationError.class)
197    public void testLogInvalidToString02Add() {
198        testDebugUsageClass(InvalidCCP_ToString02Add.class);
199    }
200
201    @Test(expected = VerificationError.class)
202    public void testLogInvalidConcat02Add() {
203        testDebugUsageClass(InvalidCCP_Concat02Add.class);
204    }
205
206    @Test
207    public void testLogValidToStringAdd() {
208        testDebugUsageClass(ValidCCP_ToStringAdd.class);
209    }
210
211    @Test
212    public void testLogValidConcatAdd() {
213        testDebugUsageClass(ValidCCP_ConcatAdd.class);
214    }
215
216    @Test(expected = VerificationError.class)
217    public void testLogInvalidToString01Inc() {
218        testDebugUsageClass(InvalidCCP_ToString01Inc.class);
219    }
220
221    @Test(expected = VerificationError.class)
222    public void testLogInvalidConcat01Inc() {
223        testDebugUsageClass(InvalidCCP_Concat01Inc.class);
224    }
225
226    @Test(expected = VerificationError.class)
227    public void testLogInvalidToString02Inc() {
228        testDebugUsageClass(InvalidCCP_ToString02Inc.class);
229    }
230
231    @Test(expected = VerificationError.class)
232    public void testLogInvalidConcat02Inc() {
233        testDebugUsageClass(InvalidCCP_Concat02Inc.class);
234    }
235
236    @Test
237    public void testLogValidToStringInc() {
238        testDebugUsageClass(ValidCCP_ToStringInc.class);
239    }
240
241    @Test
242    public void testLogValidConcatInc() {
243        testDebugUsageClass(ValidCCP_ConcatInc.class);
244    }
245
246    @SuppressWarnings("try")
247    private static void testDebugUsageClass(Class<?> c) {
248        RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
249        Providers providers = rt.getHostBackend().getProviders();
250        MetaAccessProvider metaAccess = providers.getMetaAccess();
251        PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
252        Plugins plugins = new Plugins(new InvocationPlugins());
253        GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
254        graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
255        HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
256        for (Method m : c.getDeclaredMethods()) {
257            if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
258                ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
259                StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID);
260                graphBuilderSuite.apply(graph, context);
261                try (DebugConfigScope s = Debug.disableIntercept()) {
262                    new VerifyDebugUsage().apply(graph, context);
263                }
264            }
265        }
266    }
267}
268