1 /*
2 * Copyright (c) 2021, 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 8262912
27 * @library / /test/lib
28 * @summary Test class resolution based on whitelist created by ciInstanceKlass entries in replay file.
29 * @requires vm.flightRecorder != true & vm.compMode != "Xint" & 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.TestUnresolvedClasses
35 */
36
37 package compiler.ciReplay;
38
39 import jdk.test.lib.Asserts;
40
41 import java.io.IOException;
42 import java.nio.file.Files;
43 import java.nio.file.Paths;
44 import java.nio.file.Path;
45 import java.nio.file.StandardOpenOption;
46 import java.util.ArrayList;
47 import java.util.List;
48
49 public class TestUnresolvedClasses extends CiReplayBase {
50 private static final String LOG_FILE = "hotspot.log";
51 private static final String[] COMMAND_LINE = new String[] {"-XX:LogFile='" + LOG_FILE + "'", "-XX:+LogCompilation", "-XX:+PrintIdeal",
52 "-XX:CompileCommand=dontinline,compiler.ciReplay.Test::dontInline"};
53 public static void main(String[] args) {
54 new TestUnresolvedClasses().runTest(false, TIERED_DISABLED_VM_OPTION);
55 }
56
57 @Override
58 public String getTestClass() {
59 return Test.class.getName();
60 }
61
62 @Override
63 public void testAction() {
64 positiveTest(COMMAND_LINE);
65 // Should find CallStaticJava node for dontInline() as f.bar() is resolved and parsing completes.
66 checkLogFile(true);
67
68 // Remove ciInstanceKlass entry for Foo in replay file.
69 try {
70 Path replayFilePath = Paths.get(REPLAY_FILE_NAME);
71 List<String> replayContent = Files.readAllLines(replayFilePath);
72 List<String> newReplayContent = new ArrayList<>();
73 boolean foundFoo = false;
74 for (String line : replayContent) {
75 if (!line.startsWith("ciInstanceKlass compiler/ciReplay/Foo")) {
76 newReplayContent.add(line);
77 } else {
78 foundFoo = true;
79 }
80 }
81 Asserts.assertTrue(foundFoo, "Did not find ciInstanceKlass compiler/ciReplay/Foo entry");
82 Files.write(replayFilePath, newReplayContent, StandardOpenOption.TRUNCATE_EXISTING);
83 } catch (IOException ioe) {
84 throw new Error("Failed to read/write replay data: " + ioe, ioe);
85 }
86
87 positiveTest(COMMAND_LINE);
88 // No ciInstanceKlass entry for Foo is found in the replay. Replay compilation simulates that Foo is unresolved.
89 // Therefore, C2 cannot resolve f.bar() at parsing time. It emits an UCT to resolve Foo and stops parsing.
90 // The call to dontInline() will not be parsed and thus we should not find a CallStaticJava node for it.
91 checkLogFile(false);
92 remove(LOG_FILE);
93 }
94
95 // Parse <ideal> entry in hotspot.log file and try to find the call for dontInline().
96 private void checkLogFile(boolean shouldMatch) {
97 String toMatch = "Test::dontInline";
98 try (var br = Files.newBufferedReader(Paths.get(LOG_FILE))) {
99 String line;
100 boolean printIdealLine = false;
101 while ((line = br.readLine()) != null) {
102 if (printIdealLine) {
103 if (line.startsWith("</ideal")) {
104 break;
105 }
106 if (line.contains(toMatch)) {
107 Asserts.assertTrue(line.contains("CallStaticJava"), "must be CallStaticJava node");
108 Asserts.assertTrue(shouldMatch, "Should not have found " + toMatch);
109 return;
110 }
111 } else {
112 printIdealLine = line.startsWith("<ideal");
113 }
114 }
115 } catch (IOException e) {
116 throw new Error("Failed to read " + LOG_FILE + " data: " + e, e);
117 }
118 Asserts.assertFalse(shouldMatch, "Should have found " + toMatch);
119 }
120 }
121
122 class Test {
123 static Foo f = new Foo();
124
125 public static void main(String[] args) {
126 for (int i = 0; i < 10000; i++) {
127 test();
128 }
129 }
130
131 public static void test() {
132 f.bar();
133 // At replay compilation: Should emit UCT for f.bar() because class Foo is unloaded. Parsing stops here.
134 // dontInline() is not parsed anymore.
135 dontInline();
136 }
137
138 // Not inlined
139 public static void dontInline() {
140 }
141 }
142
143 class Foo {
144 public int bar() {
145 return 3;
146 }
147 }
|
1 /*
2 * Copyright (c) 2021, 2026, 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 8262912
27 * @library / /test/lib
28 * @summary Test class resolution based on whitelist created by ciInstanceKlass entries in replay file.
29 * @requires vm.flightRecorder != true & vm.compMode != "Xint" & 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.TestUnresolvedClasses
35 */
36
37 package compiler.ciReplay;
38
39 import jdk.test.lib.Asserts;
40
41 import java.util.List;
42
43 public class TestUnresolvedClasses extends CiReplayBase {
44 private static final String LOG_FILE = "hotspot.log";
45 private final PrintIdeal printIdeal = new PrintIdeal(LOG_FILE);
46
47 public static void main(String[] args) {
48 new TestUnresolvedClasses().runTest(false, TIERED_DISABLED_VM_OPTION);
49 }
50
51 @Override
52 public String getTestClass() {
53 return Test.class.getName();
54 }
55
56 @Override
57 public void testAction() {
58 List<String> vmFlags = printIdeal.vmFlags();
59 vmFlags.add("-XX:CompileCommand=dontinline,*Test::dontInline");
60 String[] commandLine = vmFlags.toArray(new String[0]);
61 positiveTest(commandLine);
62 printIdeal.parse();
63 // Should find CallStaticJava node for dontInline() as f.bar() is resolved and parsing completes.
64 checkLogFile(true);
65
66 ReplayFile replayFile = new ReplayFile(getReplayFileName());
67 // Remove ciInstanceKlass entry for Foo in replay file.
68 replayFile.removeLineStartingWith("ciInstanceKlass compiler/ciReplay/TestUnresolvedClasses$Foo");
69
70 positiveTest(commandLine);
71 printIdeal.parse();
72 // No ciInstanceKlass entry for Foo is found in the replay. Replay compilation simulates that Foo is unresolved.
73 // Therefore, C2 cannot resolve f.bar() at parsing time. It emits an UCT to resolve Foo and stops parsing.
74 // The call to dontInline() will not be parsed and thus we should not find a CallStaticJava node for it.
75 checkLogFile(false);
76 remove(LOG_FILE);
77 }
78
79 // Parse <ideal> entry in hotspot.log file and try to find the call for dontInline().
80 private void checkLogFile(boolean shouldMatch) {
81 String toMatch = "Test::dontInline";
82 String line = printIdeal.find(toMatch);
83 if (shouldMatch) {
84 Asserts.assertTrue(line.contains("CallStaticJava"), "must be CallStaticJava node");
85 } else {
86 Asserts.assertTrue(line.isEmpty(), "Should not have found " + toMatch);
87 }
88 }
89
90 private static class Test {
91 static Foo f = new Foo();
92
93 public static void main(String[] args) {
94 for (int i = 0; i < 10000; i++) {
95 test();
96 }
97 }
98
99 public static void test() {
100 f.bar();
101 // At replay compilation: Should emit UCT for f.bar() because class Foo is unloaded. Parsing stops here.
102 // dontInline() is not parsed anymore.
103 dontInline();
104 }
105
106 // Not inlined
107 public static void dontInline() {
108 }
109 }
110
111 private static class Foo {
112 public int bar() {
113 return 3;
114 }
115 }
116 }
|