1 /* 2 * Copyright (c) 2017, 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.hotspot.test; 26 27 import org.graalvm.compiler.core.test.GraalCompilerTest; 28 import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; 29 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; 30 import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; 31 import org.graalvm.compiler.nodes.StructuredGraph; 32 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 33 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 34 import org.graalvm.compiler.phases.tiers.HighTierContext; 35 import org.junit.Assert; 36 import org.junit.Test; 37 38 public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest { 39 @Override 40 protected Plugins getDefaultGraphBuilderPlugins() { 41 Plugins plugins = super.getDefaultGraphBuilderPlugins(); 42 plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); 43 return plugins; 44 } 45 46 public static class X { 47 public static int x; 48 public static int y; 49 public static int z; 50 } 51 52 public static class Y extends X { 53 public static int a; 54 public static int b; 55 } 56 57 public static void assignFields() { 58 X.x = 1; 59 X.y = 2; 60 X.z = 3; 61 } 62 63 public static void assignFieldsConditionally(boolean choice) { 64 X.x = 1; 65 if (choice) { 66 X.y = 2; 67 } else { 68 X.z = 3; 69 } 70 } 71 72 public static void assignFieldsSubclassDominates() { 73 Y.a = 1; 74 X.x = 2; 75 X.y = 3; 76 X.z = 4; 77 } 78 79 public static void assignFieldsConditionallySubclassDominates(boolean choice) { 80 Y.a = 1; 81 if (choice) { 82 X.x = 2; 83 } else { 84 X.y = 3; 85 } 86 Y.z = 4; 87 } 88 89 public static void assignFieldsSubclassPostdominates() { 90 X.x = 1; 91 Y.a = 2; 92 } 93 94 public static void assignFieldsConditionallySubclassPostdominates(boolean choice) { 95 X.x = 1; 96 if (choice) { 97 X.y = 2; 98 } else { 99 X.z = 3; 100 } 101 Y.a = 4; 102 } 103 104 public static void assignFieldsConditionallyMixed(boolean choice) { 105 X.x = 1; 106 if (choice) { 107 Y.a = 2; 108 } else { 109 X.z = 3; 110 } 111 Y.b = 4; 112 } 113 114 public static void assignFieldsInLoop() { 115 X.x = 1; 116 for (int i = 0; i < 10; i++) { 117 X.y += X.z; 118 } 119 } 120 121 public static void assignFieldsInBranches(boolean choice) { 122 if (choice) { 123 X.x = 1; 124 } else { 125 X.y = 2; 126 } 127 X.z = 3; 128 } 129 130 public static void assignFieldsInBranchesMixed(boolean choice) { 131 if (choice) { 132 X.x = 1; 133 } else { 134 Y.a = 2; 135 } 136 X.z = 3; 137 } 138 139 static class SomeClass { 140 @BytecodeParserNeverInline 141 static void method() { 142 } 143 144 @BytecodeParserForceInline 145 static void inlinedMethod() { 146 } 147 } 148 149 public static void invokestatic() { 150 SomeClass.method(); 151 } 152 153 public static void invokestaticInlined() { 154 SomeClass.inlinedMethod(); 155 } 156 157 private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) { 158 StructuredGraph graph = parseEager(name, AllowAssumptions.NO); 159 Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count()); 160 HighTierContext highTierContext = getDefaultHighTierContext(); 161 new EliminateRedundantInitializationPhase().apply(graph, highTierContext); 162 Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count()); 163 } 164 165 @Test 166 public void test1() { 167 test("assignFields", 3, 1); 168 } 169 170 @Test 171 public void test2() { 172 test("assignFieldsConditionally", 3, 1); 173 } 174 175 @Test 176 public void test3() { 177 test("assignFieldsSubclassDominates", 4, 1); 178 } 179 180 @Test 181 public void test4() { 182 test("assignFieldsConditionallySubclassDominates", 4, 1); 183 } 184 185 @Test 186 public void test5() { 187 test("assignFieldsSubclassPostdominates", 2, 2); 188 } 189 190 @Test 191 public void test6() { 192 test("assignFieldsConditionallySubclassPostdominates", 4, 2); 193 } 194 195 @Test 196 public void test7() { 197 test("assignFieldsConditionallyMixed", 4, 3); 198 } 199 200 @Test 201 public void test8() { 202 test("assignFieldsInLoop", 4, 1); 203 } 204 205 @Test 206 public void test9() { 207 test("assignFieldsInBranches", 3, 2); 208 } 209 210 @Test 211 public void test10() { 212 test("assignFieldsInBranchesMixed", 3, 2); 213 } 214 215 @Test 216 public void test11() { 217 test("invokestatic", 1, 0); 218 } 219 220 @Test 221 public void test12() { 222 test("invokestaticInlined", 1, 1); 223 } 224 }