1 /*
  2  * Copyright (c) 2021, 2024, 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 8275868
 27  * @library / /test/lib
 28  * @summary Testing that ciReplay inlining does not fail with unresolved signature classes.
 29  * @requires vm.flightRecorder != true & vm.compMode != "Xint" & vm.compMode != "Xcomp" & vm.debug == true & vm.compiler2.enabled
 30  * @modules java.base/jdk.internal.misc
 31  * @build jdk.test.whitebox.WhiteBox
 32  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 33  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
 34  *      compiler.ciReplay.TestInliningProtectionDomain
 35  */
 36 
 37 package compiler.ciReplay;
 38 
 39 import jdk.test.lib.Asserts;
 40 
 41 import java.util.List;
 42 
 43 public class TestInliningProtectionDomain extends InliningBase {
 44 
 45     public static void main(String[] args) {
 46         new TestInliningProtectionDomain(ProtectionDomainTestCompiledBefore.class, true);
 47         new TestInliningProtectionDomain(ProtectionDomainTestNoOtherCompilationPublic.class, false);
 48         new TestInliningProtectionDomain(ProtectionDomainTestNoOtherCompilationPrivate.class, false);
 49         new TestInliningProtectionDomain(ProtectionDomainTestNoOtherCompilationPrivateString.class, false);
 50     }
 51 
 52     public TestInliningProtectionDomain(Class<?> testClass, boolean compileBar) {
 53         super(testClass);
 54         if (compileBar) {
 55             commandLineNormal.add("-XX:CompileCommand=compileonly," + testClass.getName() + "::bar");
 56         }
 57         runTest();
 58     }
 59 
 60     @Override
 61     public void testAction() {
 62         positiveTest(commandLineReplay);
 63         String entryString = getTestClass() + " " + "test";
 64         boolean inlineFails = testClass == ProtectionDomainTestNoOtherCompilationPrivate.class;
 65         int inlineeCount = inlineFails ? 1 : 5;
 66 
 67         List<InlineEntry> inlineesNormal = parseLogFile(LOG_FILE_NORMAL, entryString, "compile_id='" + getCompileIdFromFile(getReplayFileName()) + "'", inlineeCount);
 68         List<InlineEntry> inlineesReplay = parseLogFile(LOG_FILE_REPLAY, entryString, "test ()V", inlineeCount);
 69         verifyLists(inlineesNormal, inlineesReplay, inlineeCount);
 70 
 71         if (inlineFails) {
 72             Asserts.assertTrue(inlineesNormal.get(0).compare("compiler.ciReplay.ProtectionDomainTestNoOtherCompilationPrivate", "bar", inlineesNormal.get(0).isUnloadedSignatureClasses()));
 73             Asserts.assertTrue(inlineesReplay.get(0).compare("compiler.ciReplay.ProtectionDomainTestNoOtherCompilationPrivate", "bar", inlineesReplay.get(0).isDisallowedByReplay()));
 74         } else {
 75             Asserts.assertTrue(inlineesNormal.get(4).compare("compiler.ciReplay.InliningBar", "bar2", inlineesNormal.get(4).isNormalInline()));
 76             Asserts.assertTrue(inlineesReplay.get(4).compare("compiler.ciReplay.InliningBar", "bar2", inlineesReplay.get(4).isForcedByReplay() || inlineesReplay.get(4).isForcedIncrementalInlineByReplay()));
 77         }
 78     }
 79 }
 80 
 81 class ProtectionDomainTestCompiledBefore {
 82     public static void main(String[] args) {
 83         for (int i = 0; i < 10000; i++) {
 84             bar(); // Ensure that bar() was compiled
 85         }
 86         for (int i = 0; i < 10000; i++) {
 87             test();
 88         }
 89     }
 90 
 91     public static void test() {
 92         bar();
 93     }
 94 
 95     // Integer should be resolved for the protection domain of this class because the separate compilation of bar() in
 96     // the normal run will resolve all classes in the signature. Inlining succeeds.
 97     private static Integer bar() {
 98         InliningFoo.foo();
 99         return null;
100     }
101 }
102 
103 class ProtectionDomainTestNoOtherCompilationPublic {
104     public static void main(String[] args) {
105         for (int i = 0; i < 10000; i++) {
106             test();
107         }
108     }
109 
110     public static void test() {
111         bar(); // Not compiled before separately
112     }
113 
114     // Integer should be resolved for the protection domain of this class because getDeclaredMethods is called in normal run
115     // when validating main() method. In this process, all public methods of this class are visited and its signature classes
116     // are resolved. Inlining of bar() succeeds.
117     public static Integer bar() {
118         InliningFoo.foo();
119         return null;
120     }
121 }
122 
123 class ProtectionDomainTestNoOtherCompilationPrivate {
124     public static void main(String[] args) {
125         for (int i = 0; i < 10000; i++) {
126             test();
127         }
128     }
129 
130     public static void test() {
131         bar(); // Not compiled before separately
132     }
133 
134     // Integer should be unresolved for the protection domain of this class even though getDeclaredMethods is called in normal
135     // run when validating main() method. In this process, only public methods of this class are visited and its signature
136     // classes are resolved. Since this method is private, the signature classes are not resolved for this protection domain.
137     // Inlining of bar() should fail in normal run with "unresolved signature classes". Therefore, replay compilation should
138     // also not inline bar().
139     private static Integer bar() {
140         InliningFoo.foo();
141         return null;
142     }
143 }
144 
145 class ProtectionDomainTestNoOtherCompilationPrivateString {
146     public static void main(String[] args) {
147         for (int i = 0; i < 10000; i++) {
148             test();
149         }
150     }
151 
152     public static void test() {
153         bar(); // Not compiled before separately
154     }
155 
156     // Integer should be resovled for the protection domain of this class because getDeclaredMethods is called in normal run
157     // when validating main() method. In this process, public methods of this class are visited and its signature classes
158     // are resolved. bar() is private and not visited in this process (i.e. no resolution of String). But since main()
159     // has String[] as parameter, the String class will be resolved for this protection domain. Inlining of bar() succeeds.
160     private static String bar() {
161         InliningFoo.foo();
162         return null;
163     }
164 }
165 
166 class InliningFoo {
167     public static void foo() {
168         foo2();
169     }
170 
171     private static void foo2() {
172         InliningBar.bar();
173     }
174 }
175 
176 
177 class InliningBar {
178     public static void bar() {
179         bar2();
180     }
181 
182     private static void bar2() {}
183 }