1 /* 2 * Copyright (c) 2014, 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 24 /* 25 * @test DeoptimizeFramesTest 26 * @bug 8028595 27 * @summary testing of WB::deoptimizeFrames() 28 * @library /test/lib / 29 * @modules java.base/jdk.internal.misc 30 * java.management 31 * @build sun.hotspot.WhiteBox 32 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 33 * sun.hotspot.WhiteBox$WhiteBoxPermission 34 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 35 * -XX:+WhiteBoxAPI -Xmixed -XX:-UseCounterDecay 36 * -XX:CompileCommand=compileonly,compiler.whitebox.DeoptimizeFramesTest$TestCaseImpl::method 37 * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot 38 * compiler.whitebox.DeoptimizeFramesTest true 39 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions 40 * -XX:+WhiteBoxAPI -Xmixed -XX:-UseCounterDecay 41 * -XX:CompileCommand=compileonly,compiler.whitebox.DeoptimizeFramesTest$TestCaseImpl::method 42 * -XX:CompileCommand=dontinline,java.util.concurrent.Phaser::* 43 * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom -XX:-DeoptimizeALot 44 * compiler.whitebox.DeoptimizeFramesTest false 45 */ 46 47 package compiler.whitebox; 48 49 import jdk.test.lib.Asserts; 50 import sun.hotspot.code.NMethod; 51 52 import java.lang.reflect.Executable; 53 import java.util.concurrent.Callable; 54 import java.util.concurrent.Phaser; 55 56 public class DeoptimizeFramesTest extends CompilerWhiteBoxTest { 57 private final boolean makeNotEntrant; 58 private final Phaser phaser; 59 DeoptimizeFramesTest(boolean makeNotEntrant, Phaser phaser)60 private DeoptimizeFramesTest(boolean makeNotEntrant, Phaser phaser) { 61 super(new TestCaseImpl(phaser)); 62 // to prevent inlining of #method 63 WHITE_BOX.testSetDontInlineMethod(method, true); 64 this.makeNotEntrant = makeNotEntrant; 65 this.phaser = phaser; 66 System.out.printf("DeoptimizeFramesTest(makeNotEntrant = %b)%n", 67 makeNotEntrant); 68 } 69 main(String[] args)70 public static void main(String[] args) throws Exception { 71 Asserts.assertEQ(args.length, 1, 72 "[TESTBUG] args should contain 1 element"); 73 new DeoptimizeFramesTest(Boolean.valueOf(args[0]), new Phaser()).runTest(); 74 } 75 76 @Override test()77 protected void test() throws Exception { 78 compile(); 79 checkCompiled(); 80 NMethod nm = NMethod.get(method, testCase.isOsr()); 81 82 WHITE_BOX.deoptimizeFrames(makeNotEntrant); 83 // #method should still be compiled, since it didn't have frames on stack 84 checkCompiled(); 85 NMethod nm2 = NMethod.get(method, testCase.isOsr()); 86 Asserts.assertEQ(nm.compile_id, nm2.compile_id, 87 "should be the same nmethod"); 88 89 phaser.register(); 90 Thread t = new Thread(() -> compile(1)); 91 t.start(); 92 // pass 1st phase, #method is on stack 93 int p = phaser.arriveAndAwaitAdvance(); 94 WHITE_BOX.deoptimizeFrames(makeNotEntrant); 95 // pass 2nd phase, #method can exit 96 phaser.awaitAdvance(phaser.arriveAndDeregister()); 97 98 try { 99 t.join(); 100 } catch (InterruptedException e) { 101 throw new Error("method '" + method + "' is still executing", e); 102 } 103 104 // invoke one more time to recompile not entrant if any 105 compile(1); 106 107 nm2 = NMethod.get(method, testCase.isOsr()); 108 if (makeNotEntrant) { 109 if (nm2 != null) { 110 Asserts.assertNE(nm.compile_id, nm2.compile_id, 111 String.format("compilation %d can't be available", nm.compile_id)); 112 } 113 } else { 114 Asserts.assertNE(nm2, null, "must not be null"); 115 Asserts.assertEQ(nm.compile_id, nm2.compile_id, "should be the same nmethod"); 116 } 117 } 118 119 120 private static class TestCaseImpl implements TestCase { 121 private static final Executable EXECUTABLE; 122 static { 123 try { 124 EXECUTABLE = TestCaseImpl.class.getDeclaredMethod("method"); 125 } catch (NoSuchMethodException e) { 126 throw new Error("[TESTBUG] method not found", e); 127 } 128 } 129 130 private final Phaser phaser; 131 TestCaseImpl(Phaser phaser)132 public TestCaseImpl(Phaser phaser) { 133 this.phaser = phaser; 134 phaser.register(); 135 } 136 137 @Override name()138 public String name() { 139 return "2phases"; 140 } 141 142 @Override getExecutable()143 public Executable getExecutable() { 144 return EXECUTABLE; 145 } 146 147 @Override getCallable()148 public Callable<Integer> getCallable() { 149 return () -> { 150 return method(); 151 }; 152 } 153 154 @Override isOsr()155 public boolean isOsr() { 156 return false; 157 } 158 method()159 private int method() { 160 phaser.arriveAndAwaitAdvance(); 161 phaser.arriveAndAwaitAdvance(); 162 return 0; 163 } 164 } 165 } 166