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 * @test 26 * @bug 8136421 27 * @requires vm.jvmci 28 * & (vm.compMode != "Xcomp" | vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true) 29 * @summary no "-Xcomp -XX:-TieredCompilation" combination allowed until JDK-8140018 is resolved 30 * @library / /test/lib 31 * @library ../common/patches 32 * @modules java.base/jdk.internal.misc 33 * @modules java.base/jdk.internal.org.objectweb.asm 34 * java.base/jdk.internal.org.objectweb.asm.tree 35 * jdk.internal.vm.ci/jdk.vm.ci.hotspot 36 * jdk.internal.vm.ci/jdk.vm.ci.code 37 * jdk.internal.vm.ci/jdk.vm.ci.code.stack 38 * jdk.internal.vm.ci/jdk.vm.ci.meta 39 * 40 * @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox 41 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 42 * sun.hotspot.WhiteBox$WhiteBoxPermission 43 * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:. 44 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 45 * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 46 * -XX:CompileCommand=exclude,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::check 47 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame 48 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame2 49 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::recurse 50 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame3 51 * -XX:+DoEscapeAnalysis -XX:-UseCounterDecay 52 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=true 53 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false 54 * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest 55 * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:. 56 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 57 * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 58 * -XX:CompileCommand=exclude,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::check 59 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame 60 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame2 61 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::recurse 62 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame3 63 * -XX:+DoEscapeAnalysis -XX:-UseCounterDecay 64 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=false 65 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=false 66 * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest 67 * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:. 68 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 69 * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 70 * -XX:CompileCommand=exclude,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::check 71 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame 72 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame2 73 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::recurse 74 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame3 75 * -XX:+DoEscapeAnalysis -XX:-UseCounterDecay 76 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=true 77 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true 78 * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest 79 * @run main/othervm -Xmixed -Xbatch -Xbootclasspath/a:. 80 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 81 * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 82 * -XX:CompileCommand=exclude,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::check 83 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame 84 * -XX:CompileCommand=dontinline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame2 85 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::recurse 86 * -XX:CompileCommand=inline,compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest::testFrame3 87 * -XX:+DoEscapeAnalysis -XX:-UseCounterDecay 88 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst=false 89 * -Dcompiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate=true 90 * compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest 91 */ 92 93 package compiler.jvmci.compilerToVM; 94 95 import compiler.jvmci.common.CTVMUtilities; 96 import compiler.testlibrary.CompilerUtils; 97 import compiler.whitebox.CompilerWhiteBoxTest; 98 import jdk.test.lib.Asserts; 99 import jdk.vm.ci.code.stack.InspectedFrame; 100 import jdk.vm.ci.hotspot.CompilerToVMHelper; 101 import jdk.vm.ci.hotspot.HotSpotStackFrameReference; 102 import jdk.vm.ci.meta.ResolvedJavaMethod; 103 import jtreg.SkippedException; 104 import sun.hotspot.WhiteBox; 105 106 import java.lang.reflect.Method; 107 108 public class MaterializeVirtualObjectTest { 109 private static final WhiteBox WB; 110 private static final boolean INVALIDATE; 111 private static final int COMPILE_THRESHOLD; 112 private static final Method MATERIALIZED_METHOD; 113 private static final Method NOT_MATERIALIZED_METHOD; 114 private static final Method FRAME3_METHOD; 115 private static final ResolvedJavaMethod MATERIALIZED_RESOLVED; 116 private static final ResolvedJavaMethod NOT_MATERIALIZED_RESOLVED; 117 private static final ResolvedJavaMethod FRAME2_RESOLVED; 118 private static final ResolvedJavaMethod FRAME3_RESOLVED; 119 private static final boolean MATERIALIZE_FIRST; 120 121 static { 122 Method method1; 123 Method method2; 124 WB = WhiteBox.getWhiteBox(); 125 try { 126 method1 = MaterializeVirtualObjectTest.class.getDeclaredMethod("testFrame", 127 String.class, int.class); 128 method2 = MaterializeVirtualObjectTest.class.getDeclaredMethod("testFrame2", 129 String.class, int.class); 130 FRAME3_METHOD = MaterializeVirtualObjectTest.class.getDeclaredMethod("testFrame3", 131 Helper.class, int.class); 132 } catch (NoSuchMethodException e) { 133 throw new Error("Can't get executable for test method", e); 134 } 135 ResolvedJavaMethod resolved1; 136 resolved1 = CTVMUtilities.getResolvedMethod(method1); 137 FRAME2_RESOLVED = CTVMUtilities.getResolvedMethod(method2); 138 FRAME3_RESOLVED = CTVMUtilities.getResolvedMethod(FRAME3_METHOD); 139 INVALIDATE = Boolean.getBoolean( 140 "compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.invalidate"); 141 COMPILE_THRESHOLD = WB.getBooleanVMFlag("TieredCompilation") 142 ? CompilerWhiteBoxTest.THRESHOLD 143 : CompilerWhiteBoxTest.THRESHOLD * 2; 144 MATERIALIZE_FIRST = Boolean.getBoolean( 145 "compiler.jvmci.compilerToVM.MaterializeVirtualObjectTest.materializeFirst"); 146 MATERIALIZED_RESOLVED = MATERIALIZE_FIRST ? resolved1 : FRAME2_RESOLVED; 147 NOT_MATERIALIZED_RESOLVED = MATERIALIZE_FIRST ? FRAME2_RESOLVED : resolved1; 148 MATERIALIZED_METHOD = MATERIALIZE_FIRST ? method1 : method2; 149 NOT_MATERIALIZED_METHOD = MATERIALIZE_FIRST ? method2 : method1; 150 } 151 152 public static void main(String[] args) { 153 int levels[] = CompilerUtils.getAvailableCompilationLevels(); 154 // we need compilation level 4 to use EscapeAnalysis 155 if (levels.length < 1 || levels[levels.length - 1] != 4) { 156 throw new SkippedException("Test needs compilation level 4"); 157 } 158 159 new MaterializeVirtualObjectTest().test(); 160 } 161 162 private static String getName() { 163 return "CASE: invalidate=" + INVALIDATE + ", materializedMethod=" 164 + (MATERIALIZE_FIRST ? "testFrame" : "testFrame2") 165 + ", notMaterializedMethod=" 166 + (MATERIALIZE_FIRST ? "testFrame2" : "testFrame"); 167 } 168 169 private void test() { 170 System.out.println(getName()); 171 Asserts.assertFalse(WB.isMethodCompiled(MATERIALIZED_METHOD), 172 getName() + " : materialized method is compiled"); 173 Asserts.assertFalse(WB.isMethodCompiled(NOT_MATERIALIZED_METHOD), 174 getName() + " : not materialized method is compiled"); 175 for (int i = 0; i < CompilerWhiteBoxTest.THRESHOLD; i++) { 176 testFrame("someString", i); 177 } 178 Asserts.assertTrue(WB.isMethodCompiled(MATERIALIZED_METHOD), getName() 179 + " : materialized method not compiled"); 180 Asserts.assertTrue(WB.isMethodCompiled(NOT_MATERIALIZED_METHOD), 181 getName() + " : not materialized method not compiled"); 182 testFrame("someString", /* materialize */ CompilerWhiteBoxTest.THRESHOLD); 183 184 // run second test types 185 for (int i = 0; i < CompilerWhiteBoxTest.THRESHOLD; i++) { 186 testFrame("someString", i); 187 } 188 Asserts.assertTrue(WB.isMethodCompiled(MATERIALIZED_METHOD), getName() 189 + " : materialized method not compiled"); 190 Asserts.assertTrue(WB.isMethodCompiled(NOT_MATERIALIZED_METHOD), 191 getName() + " : not materialized method not compiled"); 192 testFrame("someString", /* materialize */ CompilerWhiteBoxTest.THRESHOLD + 1); 193 } 194 195 private void testFrame(String str, int iteration) { 196 Helper helper = new Helper(str); 197 testFrame2(str, iteration); 198 Asserts.assertTrue((helper.string != null) && (this != null) 199 && (helper != null), String.format("%s : some locals are null", getName())); 200 } 201 202 private void testFrame2(String str, int iteration) { 203 Helper helper = new Helper(str); 204 Helper helper2 = new Helper("bar"); 205 testFrame3(helper, iteration); 206 Asserts.assertTrue((helper.string != null) && (this != null) && helper.string == str 207 && (helper != null), String.format("%s : some locals are null", getName())); 208 Asserts.assertTrue((helper2.string != null) && (this != null) 209 && (helper2 != null), String.format("%s : some locals are null", getName())); 210 } 211 212 private void testFrame3(Helper outerHelper, int iteration) { 213 Helper innerHelper = new Helper("foo"); 214 recurse(2, iteration); 215 Asserts.assertTrue((innerHelper.string != null) && (this != null) 216 && (innerHelper != null), String.format("%s : some locals are null", getName())); 217 Asserts.assertTrue((outerHelper.string != null) && (this != null) 218 && (outerHelper != null), String.format("%s : some locals are null", getName())); 219 } 220 221 private void recurse(int depth, int iteration) { 222 if (depth == 0) { 223 check(iteration); 224 } else { 225 Integer s = new Integer(depth); 226 recurse(depth - 1, iteration); 227 Asserts.assertEQ(s.intValue(), depth, 228 String.format("different values: %s != %s", s.intValue(), depth)); 229 } 230 } 231 232 private void checkStructure(boolean materialize) { 233 boolean[] framesSeen = new boolean[2]; 234 Object[] helpers = new Object[1]; 235 CompilerToVMHelper.iterateFrames( 236 new ResolvedJavaMethod[] {FRAME3_RESOLVED}, 237 null, /* any */ 238 0, 239 f -> { 240 if (!framesSeen[1]) { 241 Asserts.assertTrue(f.isMethod(FRAME3_RESOLVED), 242 "Expected testFrame3 first"); 243 framesSeen[1] = true; 244 Asserts.assertTrue(f.getLocal(0) != null, "this should not be null"); 245 Asserts.assertTrue(f.getLocal(1) != null, "outerHelper should not be null"); 246 Asserts.assertTrue(f.getLocal(3) != null, "innerHelper should not be null"); 247 Asserts.assertEQ(((Helper) f.getLocal(3)).string, "foo", "innerHelper.string should be foo"); 248 helpers[0] = f.getLocal(1); 249 if (materialize) { 250 f.materializeVirtualObjects(false); 251 } 252 return null; //continue 253 } else { 254 Asserts.assertFalse(framesSeen[0], "frame3 can not have been seen"); 255 Asserts.assertTrue(f.isMethod(FRAME2_RESOLVED), 256 "Expected testFrame2 second"); 257 framesSeen[0] = true; 258 Asserts.assertTrue(f.getLocal(0) != null, "this should not be null"); 259 Asserts.assertTrue(f.getLocal(1) != null, "str should not be null"); 260 Asserts.assertTrue(f.getLocal(3) != null, "helper should not be null"); 261 Asserts.assertTrue(f.getLocal(4) != null, "helper2 should not be null"); 262 Asserts.assertEQ(((Helper) f.getLocal(3)).string, f.getLocal(1), "helper.string should be the same as str"); 263 Asserts.assertEQ(((Helper) f.getLocal(4)).string, "bar", "helper2.string should be foo"); 264 if (!materialize) { 265 Asserts.assertEQ(f.getLocal(3), helpers[0], "helper should be the same as frame3's outerHelper"); 266 } 267 return f; // stop 268 } 269 }); 270 Asserts.assertTrue(framesSeen[1], "frame3 should have been seen"); 271 Asserts.assertTrue(framesSeen[0], "frame2 should have been seen"); 272 } 273 274 private void check(int iteration) { 275 // Materialize virtual objects on last invocation 276 if (iteration == COMPILE_THRESHOLD) { 277 // get frames and check not-null 278 HotSpotStackFrameReference materialized = CompilerToVMHelper.iterateFrames( 279 new ResolvedJavaMethod[] {MATERIALIZED_RESOLVED}, 280 null /* any */, 281 0, 282 f -> (HotSpotStackFrameReference) f); 283 Asserts.assertNotNull(materialized, getName() 284 + " : got null frame for materialized method"); 285 Asserts.assertTrue(materialized.isMethod(MATERIALIZED_RESOLVED), 286 "Expected materialized method but got " + materialized); 287 InspectedFrame notMaterialized = CompilerToVMHelper.iterateFrames( 288 new ResolvedJavaMethod[] {NOT_MATERIALIZED_RESOLVED}, 289 null /* any */, 290 0, 291 f -> f); 292 Asserts.assertNE(materialized, notMaterialized, 293 "Got same frame pointer for both tested frames"); 294 Asserts.assertTrue(notMaterialized.isMethod(NOT_MATERIALIZED_RESOLVED), 295 "Expected notMaterialized method but got " + notMaterialized); 296 Asserts.assertNotNull(notMaterialized, getName() 297 + " : got null frame for not materialized method"); 298 Asserts.assertTrue(WB.isMethodCompiled(MATERIALIZED_METHOD), getName() 299 + " : materialized method not compiled"); 300 Asserts.assertTrue(WB.isMethodCompiled(NOT_MATERIALIZED_METHOD), 301 getName() + " : not materialized method not compiled"); 302 // check that frames has virtual objects before materialization stage 303 Asserts.assertTrue(materialized.hasVirtualObjects(), getName() 304 + ": materialized frame has no virtual object before materialization"); 305 Asserts.assertTrue(notMaterialized.hasVirtualObjects(), getName() 306 + ": notMaterialized frame has no virtual object before materialization"); 307 // materialize 308 CompilerToVMHelper.materializeVirtualObjects(materialized, INVALIDATE); 309 // check that only not materialized frame has virtual objects 310 Asserts.assertFalse(materialized.hasVirtualObjects(), getName() 311 + " : materialized has virtual object after materialization"); 312 Asserts.assertTrue(notMaterialized.hasVirtualObjects(), getName() 313 + " : notMaterialized has no virtual object after materialization"); 314 // check that materialized frame was deoptimized in case invalidate=true 315 Asserts.assertEQ(WB.isMethodCompiled(MATERIALIZED_METHOD), !INVALIDATE, getName() 316 + " : materialized method has unexpected compiled status"); 317 // check that not materialized frame wasn't deoptimized 318 Asserts.assertTrue(WB.isMethodCompiled(NOT_MATERIALIZED_METHOD), getName() 319 + " : not materialized method has unexpected compiled status"); 320 } else if (iteration == COMPILE_THRESHOLD + 1) { 321 checkStructure(false); 322 checkStructure(true); 323 } 324 } 325 326 private class Helper { 327 public String string; 328 329 public Helper(String s) { 330 this.string = s; 331 } 332 } 333 }