1/*
2 * Copyright (c) 2017, 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.hotspot.test;
24
25import org.graalvm.compiler.core.common.GraalOptions;
26import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
27import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
28import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
29import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
30import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
31import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase;
32import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
33import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase;
34import org.graalvm.compiler.nodes.StructuredGraph;
35import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
36import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
37import org.graalvm.compiler.nodes.spi.LoweringTool;
38import org.graalvm.compiler.options.OptionValues;
39import org.graalvm.compiler.phases.common.CanonicalizerPhase;
40import org.graalvm.compiler.phases.common.LoweringPhase;
41import org.graalvm.compiler.phases.tiers.HighTierContext;
42import org.junit.Assert;
43import org.junit.Test;
44
45public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest {
46    private final GraalHotSpotVMConfig config = runtime().getVMConfig();
47
48    @Override
49    protected Plugins getDefaultGraphBuilderPlugins() {
50        Plugins plugins = super.getDefaultGraphBuilderPlugins();
51        plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin());
52        return plugins;
53    }
54
55    public static class X {
56        public static int x;
57        public static int y;
58        public static int z;
59        public static Object o;
60    }
61
62    public static class Y extends X {
63        public static int a;
64        public static int b;
65    }
66
67    public static int a;
68
69    public static void assignFields() {
70        X.x = 1;
71        X.y = 2;
72        X.z = 3;
73    }
74
75    public static void assignFieldsInBranches(boolean x) {
76        if (x) {
77            X.y = 1;
78        } else {
79            X.z = 2;
80        }
81    }
82
83    public static void assignFieldsWithDominatingInit(boolean x) {
84        X.x = 1;
85        if (x) {
86            X.y = 2;
87        } else {
88            X.z = 3;
89        }
90    }
91
92    public static void assignString() {
93        X.o = "foo";
94    }
95
96    public static void assignToParentAndChild() {
97        Y.a = 1;
98        X.x = 2;
99    }
100
101    public static void assignToThis() {
102        a = 1;
103    }
104
105    public static void assignFieldsWithDominatingInitOfParent(boolean x) {
106        Y.a = 1;
107        if (x) {
108            X.y = 2;
109        } else {
110            X.z = 3;
111        }
112        Y.b = 4;
113    }
114
115    private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) {
116        StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true));
117        HighTierContext highTierContext = getDefaultHighTierContext();
118        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
119        new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
120        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
121        new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext);
122        new ReplaceConstantNodesPhase(false).apply(graph, highTierContext);
123        Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count());
124        Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count());
125        Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count());
126    }
127
128    @Test
129    public void test1() {
130        test("assignFields", 1, 0, 0);
131    }
132
133    @Test
134    public void test2() {
135        test("assignFieldsWithDominatingInit", 1, 0, 0);
136    }
137
138    @Test
139    public void test3() {
140        test("assignString", 1, 1, 0);
141    }
142
143    @Test
144    public void test4() {
145        test("assignToParentAndChild", 1, 1, 0);
146    }
147
148    @Test
149    public void test5() {
150        test("assignToThis", 0, 0, 1);
151    }
152
153    @Test
154    public void test6() {
155        test("assignFieldsWithDominatingInitOfParent", 1, 1, 0);
156    }
157
158    @Test
159    public void test7() {
160        test("assignFieldsInBranches", 2, 1, 0);
161    }
162}
163