1
1
/*
2
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2023, 2024, Red Hat, Inc. All rights reserved.
3
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
3
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5
*
5
6
* This code is free software; you can redistribute it and/or modify it
55
56
56
57
package compiler .print ;
57
58
59
+ import jdk .test .lib .Platform ;
58
60
import jdk .test .lib .process .OutputAnalyzer ;
59
61
import jdk .test .lib .process .ProcessTools ;
60
62
64
66
65
67
public class CompileCommandMemLimit {
66
68
69
+ // Method we don't specify; default memlimit should apply
67
70
final static String METHOD1 = "method1" ;
71
+ // Method we explicitly limit to 4K limit
68
72
final static String METHOD2 = "method2" ;
73
+ // Method for which we explicitly disable a limit on the command line.
74
+ final static String METHOD3 = "method3" ;
69
75
70
76
static boolean c2 ;
71
77
static boolean test_crash ;
@@ -77,27 +83,22 @@ public static void main(String[] args) throws Exception {
77
83
default : throw new RuntimeException ("invalid argument" );
78
84
}
79
85
c2 = Boolean .parseBoolean (args [1 ]);
80
- test (METHOD1 , METHOD2 );
81
- test (METHOD2 , METHOD1 );
82
- }
83
-
84
- private static void test (String include , String exclude ) throws Exception {
85
-
86
- // A method that is known to cost compilers a bit of memory to compile
87
86
88
87
List <String > options = new ArrayList <String >();
89
88
options .add ("-Xcomp" );
90
89
options .add ("-XX:-Inline" );
91
90
options .add ("-Xmx100m" );
91
+ options .add ("-XX:-CreateCoredumpOnCrash" );
92
92
options .add ("-XX:CompileCommand=compileonly," + getTestClass () + "::*" );
93
- // We pass a very small size to guarantee the crash
94
- options .add ("-XX:CompileCommand=MemStat," + getTestMethod (include ) + ",print" );
95
- if (test_crash ) {
96
- options .add ("-XX:CompileCommand=MemLimit," + getTestMethod (include ) + ",4k~crash" );
97
- options .add ("-XX:-CreateCoredumpOnCrash" );
98
- } else {
99
- options .add ("-XX:CompileCommand=MemLimit," + getTestMethod (include ) + ",4k" );
100
- }
93
+
94
+ // We want a final report
95
+ options .add ("-XX:CompileCommand=MemStat,*.*,print" );
96
+
97
+ // We limit method 2 to a very small limit that is guaranteed to trigger
98
+ options .add ("-XX:CompileCommand=MemLimit," + getTestMethod (METHOD2 ) + ",4k" + (test_crash ? "~crash" : "" ));
99
+
100
+ // We disable any limit set on method 3
101
+ options .add ("-XX:CompileCommand=MemLimit," + getTestMethod (METHOD3 ) + ",0" );
101
102
102
103
if (c2 ) {
103
104
options .add ("-XX:-TieredCompilation" );
@@ -110,20 +111,22 @@ private static void test(String include, String exclude) throws Exception {
110
111
111
112
oa .reportDiagnosticSummary ();
112
113
113
- String expectedNameIncl = getTestMethod (include )
114
- .replace ('.' , '/' )
115
- .replace ("$" , "\\ $" );
116
- String expectedNameExcl = getTestMethod (exclude )
117
- .replace ('.' , '/' )
118
- .replace ("$" , "\\ $" );
119
-
114
+ String method1regex = testMethodNameForRegex (getTestMethod (METHOD1 ));
115
+ String method2regex = testMethodNameForRegex (getTestMethod (METHOD2 ));
116
+ String method3regex = testMethodNameForRegex (getTestMethod (METHOD3 ));
120
117
String ct = c2 ? "c2" : "c1" ;
121
118
122
119
if (test_crash ) {
123
120
oa .shouldNotHaveExitValue (0 );
124
121
oa .shouldMatch ("# *Internal Error.*" );
125
- oa .shouldMatch ("# *fatal error: " + ct + " *" + expectedNameIncl + ".*: Hit MemLimit .*limit: 4096.*" );
126
- oa .shouldNotMatch (".*" + expectedNameExcl + ".*" );
122
+
123
+ // method 2 should have hit its tiny limit
124
+ oa .shouldMatch ("# *fatal error: " + ct + " *" + method2regex + ".*: Hit MemLimit .*limit: 4096.*" );
125
+
126
+ // none of the other ones should have hit a limit
127
+ oa .shouldNotMatch (method1regex + ".*Hit MemLimit" );
128
+ oa .shouldNotMatch (method3regex + ".*Hit MemLimit" );
129
+
127
130
// Make sure we get a non-zero-sized replay file (JDK-8331314)
128
131
oa .shouldContain ("# Compiler replay data is saved as:" );
129
132
String replayfile = oa .firstMatch ("# (\\ S+replay_pid\\ d+\\ .log)" , 1 );
@@ -137,18 +140,38 @@ private static void test(String include, String exclude) throws Exception {
137
140
if (f .length () == 0 ) {
138
141
throw new RuntimeException ("Replayfile " + replayfile + " has size 0" );
139
142
}
140
-
141
143
} else {
142
- // Should see trace output when methods are compiled
143
- oa .shouldHaveExitValue (0 )
144
- .shouldMatch (".*" + expectedNameIncl + ".*" )
145
- .shouldNotMatch (".*" + expectedNameExcl + ".*" );
144
+ oa .shouldHaveExitValue (0 );
145
+
146
+ // In debug builds we have an inbuilt MemLimit. It is very high, so we don't expect it to fire in this test.
147
+ // But it will still show up in the final report.
148
+ String implicitMemoryLimit = Platform .isDebugBuild () ? "1024M" : "-" ;
149
+
150
+ // With C2, we print number of nodes, with C1 we don't
151
+ String numberNodesRegex = c2 ? "\\ d+" : "-" ;
146
152
147
- // Expect this log line
148
- oa .shouldMatch (".* " + expectedNameIncl + ".*Hit MemLimit.* " );
153
+ // method 2 should have hit its tiny limit
154
+ oa .shouldMatch (ct + " " + method2regex + ".*: Hit MemLimit \\ (limit: 4096 now: \\ d+ \\ ) " );
149
155
150
- // Expect final output to contain "oom"
151
- oa .shouldMatch (".*oom.*" + expectedNameIncl + ".*" );
156
+ // neither of the other ones should have hit a limit
157
+ oa .shouldNotMatch (method1regex + ".*Hit MemLimit" );
158
+ oa .shouldNotMatch (method3regex + ".*Hit MemLimit" );
159
+
160
+ // Final report:
161
+ // Method 1 should show up as "ok" and with the default limit, e.g.
162
+ // total NA RA result #nodes limit time type #rc thread method
163
+ // 32728 0 32728 ok - 1024M 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J)
164
+ oa .shouldMatch ("\\ d+ +\\ d+ +\\ d+ +ok +" + numberNodesRegex + " +" + implicitMemoryLimit + " +.* +" + method1regex );
165
+
166
+ // Method 2 should show up as "oom" and with its tiny limit, e.g.
167
+ // total NA RA result #nodes limit time type #rc thread method
168
+ // 32728 0 32728 oom - 4096B 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J)
169
+ oa .shouldMatch ("\\ d+ +\\ d+ +\\ d+ +oom +" + numberNodesRegex + " +4096B +.* +" + method2regex );
170
+
171
+ // Method 3 should show up as "ok", and with no limit, even in debug builds, e.g.
172
+ // total NA RA result #nodes limit time type #rc thread method
173
+ // 32728 0 32728 ok - - 0.045 c1 1 0x000000011b019c10 compiler/print/CompileCommandMemLimit$TestMain::method1(()J)
174
+ oa .shouldMatch ("\\ d+ +\\ d+ +\\ d+ +ok +" + numberNodesRegex + " +- +.* +" + method3regex );
152
175
}
153
176
}
154
177
@@ -161,16 +184,23 @@ public static String getTestMethod(String method) {
161
184
return getTestClass () + "::" + method ;
162
185
}
163
186
187
+ private static String testMethodNameForRegex (String m ) {
188
+ return m .replace ('.' , '/' )
189
+ .replace ("$" , "\\ $" );
190
+ }
191
+
164
192
public static class TestMain {
165
193
public static void main (String [] args ) {
166
194
method1 ();
167
195
method2 ();
196
+ method3 ();
168
197
}
169
198
170
199
static long method1 () {
171
200
return System .currentTimeMillis ();
172
201
}
173
202
static void method2 () {}
203
+ static void method3 () {}
174
204
}
175
205
}
176
206
0 commit comments