Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckSmearing.java
41149 views
1
/*
2
* Copyright (c) 2014, 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 8066103
27
* @summary C2's range check smearing allows out of bound array accesses
28
* @library /test/lib /
29
* @modules java.base/jdk.internal.misc
30
* java.management
31
* @build sun.hotspot.WhiteBox
32
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
33
* @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
34
* -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
35
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions -XX:+EagerJVMCI
36
* compiler.rangechecks.TestRangeCheckSmearing
37
*
38
*/
39
40
package compiler.rangechecks;
41
42
import compiler.whitebox.CompilerWhiteBoxTest;
43
import compiler.testlibrary.CompilerUtils;
44
import jdk.test.lib.Platform;
45
import sun.hotspot.WhiteBox;
46
47
import java.lang.annotation.Retention;
48
import java.lang.annotation.RetentionPolicy;
49
import java.lang.reflect.Method;
50
import java.lang.reflect.Modifier;
51
import java.util.Arrays;
52
import java.util.HashMap;
53
54
public class TestRangeCheckSmearing {
55
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
56
57
@Retention(RetentionPolicy.RUNTIME)
58
@interface Args { int[] value(); }
59
60
// first range check is i + max of all constants
61
@Args({0, 8})
62
static int m1(int[] array, int i, boolean allaccesses) {
63
int res = 0;
64
res += array[i+9];
65
if (allaccesses) {
66
res += array[i+8];
67
res += array[i+7];
68
res += array[i+6];
69
res += array[i+5];
70
res += array[i+4];
71
res += array[i+3];
72
res += array[i+2];
73
res += array[i+1];
74
}
75
return res;
76
}
77
78
// first range check is i + min of all constants
79
@Args({0, -9})
80
static int m2(int[] array, int i, boolean allaccesses) {
81
int res = 0;
82
res += array[i+1];
83
if (allaccesses) {
84
res += array[i+2];
85
res += array[i+3];
86
res += array[i+4];
87
res += array[i+5];
88
res += array[i+6];
89
res += array[i+7];
90
res += array[i+8];
91
res += array[i+9];
92
}
93
return res;
94
}
95
96
// first range check is not i + min/max of all constants
97
@Args({0, 8})
98
static int m3(int[] array, int i, boolean allaccesses) {
99
int res = 0;
100
res += array[i+3];
101
if (allaccesses) {
102
res += array[i+2];
103
res += array[i+1];
104
res += array[i+4];
105
res += array[i+5];
106
res += array[i+6];
107
res += array[i+7];
108
res += array[i+8];
109
res += array[i+9];
110
}
111
return res;
112
}
113
114
@Args({0, -9})
115
static int m4(int[] array, int i, boolean allaccesses) {
116
int res = 0;
117
res += array[i+3];
118
if (allaccesses) {
119
res += array[i+4];
120
res += array[i+1];
121
res += array[i+2];
122
res += array[i+5];
123
res += array[i+6];
124
res += array[i+7];
125
res += array[i+8];
126
res += array[i+9];
127
}
128
return res;
129
}
130
131
@Args({0, -3})
132
static int m5(int[] array, int i, boolean allaccesses) {
133
int res = 0;
134
res += array[i+3];
135
res += array[i+2];
136
if (allaccesses) {
137
res += array[i+1];
138
res += array[i+4];
139
res += array[i+5];
140
res += array[i+6];
141
res += array[i+7];
142
res += array[i+8];
143
res += array[i+9];
144
}
145
return res;
146
}
147
148
@Args({0, 6})
149
static int m6(int[] array, int i, boolean allaccesses) {
150
int res = 0;
151
res += array[i+3];
152
res += array[i+4];
153
if (allaccesses) {
154
res += array[i+2];
155
res += array[i+1];
156
res += array[i+5];
157
res += array[i+6];
158
res += array[i+7];
159
res += array[i+8];
160
res += array[i+9];
161
}
162
return res;
163
}
164
165
@Args({0, 6})
166
static int m7(int[] array, int i, boolean allaccesses) {
167
int res = 0;
168
res += array[i+3];
169
res += array[i+2];
170
res += array[i+4];
171
if (allaccesses) {
172
res += array[i+1];
173
res += array[i+5];
174
res += array[i+6];
175
res += array[i+7];
176
res += array[i+8];
177
res += array[i+9];
178
}
179
return res;
180
}
181
182
@Args({0, -3})
183
static int m8(int[] array, int i, boolean allaccesses) {
184
int res = 0;
185
res += array[i+3];
186
res += array[i+4];
187
res += array[i+2];
188
if (allaccesses) {
189
res += array[i+1];
190
res += array[i+5];
191
res += array[i+6];
192
res += array[i+7];
193
res += array[i+8];
194
res += array[i+9];
195
}
196
return res;
197
}
198
199
@Args({6, 15})
200
static int m9(int[] array, int i, boolean allaccesses) {
201
int res = 0;
202
res += array[i+3];
203
if (allaccesses) {
204
res += array[i-2];
205
res += array[i-1];
206
res += array[i-4];
207
res += array[i-5];
208
res += array[i-6];
209
}
210
return res;
211
}
212
213
@Args({3, 12})
214
static int m10(int[] array, int i, boolean allaccesses) {
215
int res = 0;
216
res += array[i+3];
217
if (allaccesses) {
218
res += array[i-2];
219
res += array[i-1];
220
res += array[i-3];
221
res += array[i+4];
222
res += array[i+5];
223
res += array[i+6];
224
}
225
return res;
226
}
227
228
@Args({3, -3})
229
static int m11(int[] array, int i, boolean allaccesses) {
230
int res = 0;
231
res += array[i+3];
232
res += array[i-2];
233
if (allaccesses) {
234
res += array[i+5];
235
res += array[i+6];
236
}
237
return res;
238
}
239
240
@Args({3, 6})
241
static int m12(int[] array, int i, boolean allaccesses) {
242
int res = 0;
243
res += array[i+3];
244
res += array[i+6];
245
if (allaccesses) {
246
res += array[i-2];
247
res += array[i-3];
248
}
249
return res;
250
}
251
252
// check that identical range check is replaced by dominating one
253
// only when correct
254
@Args({0})
255
static int m13(int[] array, int i, boolean ignore) {
256
int res = 0;
257
res += array[i+3];
258
res += array[i+3];
259
return res;
260
}
261
262
@Args({2, 0})
263
static int m14(int[] array, int i, boolean ignore) {
264
int res = 0;
265
266
res += array[i];
267
res += array[i-2];
268
res += array[i]; // If range check below were to be removed first this cannot be considered identical to first range check
269
res += array[i-1]; // range check removed so i-1 array access depends on previous check
270
271
return res;
272
}
273
274
static int[] m15_dummy = new int[10];
275
@Args({2, 0})
276
static int m15(int[] array, int i, boolean ignore) {
277
int res = 0;
278
res += array[i];
279
280
// When the loop is optimized out we don't want the
281
// array[i-1] access which is dependent on array[i]'s
282
// range check to become dependent on the identical range
283
// check above.
284
285
int[] array2 = m15_dummy;
286
int j = 0;
287
for (; j < 10; j++);
288
if (j == 10) {
289
array2 = array;
290
}
291
292
res += array2[i-2];
293
res += array2[i];
294
res += array2[i-1]; // range check removed so i-1 array access depends on previous check
295
296
return res;
297
}
298
299
@Args({2, 0})
300
static int m16(int[] array, int i, boolean ignore) {
301
int res = 0;
302
303
res += array[i];
304
res += array[i-1];
305
res += array[i-1];
306
res += array[i-2];
307
308
return res;
309
}
310
311
@Args({2, 0})
312
static int m17(int[] array, int i, boolean ignore) {
313
int res = 0;
314
315
res += array[i];
316
res += array[i-2];
317
res += array[i-2];
318
res += array[i+2];
319
res += array[i+2];
320
res += array[i-1];
321
res += array[i-1];
322
323
return res;
324
}
325
326
static public void main(String[] args) {
327
if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
328
throw new AssertionError("Background compilation enabled");
329
}
330
new TestRangeCheckSmearing().doTests();
331
}
332
boolean success = true;
333
boolean exception = false;
334
final int[] array = new int[10];
335
final HashMap<String,Method> tests = new HashMap<>();
336
{
337
final Class<?> TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class };
338
for (Method m : this.getClass().getDeclaredMethods()) {
339
if (m.getName().matches("m[0-9]+")) {
340
assert(Modifier.isStatic(m.getModifiers())) : m;
341
assert(m.getReturnType() == int.class) : m;
342
assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m;
343
tests.put(m.getName(), m);
344
}
345
}
346
}
347
348
void invokeTest(Method m, int[] array, int index, boolean z) {
349
try {
350
m.invoke(null, array, index, z);
351
} catch (ReflectiveOperationException roe) {
352
Throwable ex = roe.getCause();
353
if (ex instanceof ArrayIndexOutOfBoundsException)
354
throw (ArrayIndexOutOfBoundsException) ex;
355
throw new AssertionError(roe);
356
}
357
}
358
359
void doTest(String name) {
360
Method m = tests.get(name);
361
tests.remove(name);
362
int[] args = m.getAnnotation(Args.class).value();
363
int index0 = args[0], index1;
364
boolean exceptionRequired = true;
365
if (args.length == 2) {
366
index1 = args[1];
367
} else {
368
// no negative test for this one
369
assert(args.length == 1);
370
assert(name.equals("m13"));
371
exceptionRequired = false;
372
index1 = index0;
373
}
374
// Get the method compiled.
375
if (!WHITE_BOX.isMethodCompiled(m)) {
376
// If not, try to compile it with C2
377
if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
378
// C2 compiler not available, try to compile with C1
379
WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
380
}
381
}
382
if (!WHITE_BOX.isMethodCompiled(m)) {
383
throw new RuntimeException(m + " not compiled");
384
}
385
386
// valid access
387
invokeTest(m, array, index0, true);
388
389
if (!WHITE_BOX.isMethodCompiled(m)) {
390
throw new RuntimeException(m + " deoptimized on valid array access");
391
}
392
393
exception = false;
394
boolean test_success = true;
395
try {
396
invokeTest(m, array, index1, false);
397
} catch(ArrayIndexOutOfBoundsException aioob) {
398
exception = true;
399
System.out.println("ArrayIndexOutOfBoundsException thrown in "+name);
400
}
401
if (!exception) {
402
System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name);
403
}
404
405
if (CompilerUtils.getMaxCompilationLevel() == CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {
406
if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) {
407
System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name);
408
test_success = false;
409
}
410
}
411
412
if (exception != exceptionRequired) {
413
System.out.println((exceptionRequired?"exception required but not thrown":"not exception required but thrown") + " in "+name);
414
test_success = false;
415
}
416
417
if (!test_success) {
418
success = false;
419
System.out.println("TEST FAILED: "+name);
420
}
421
422
}
423
void doTests() {
424
doTest("m1");
425
doTest("m2");
426
doTest("m3");
427
doTest("m4");
428
doTest("m5");
429
doTest("m6");
430
doTest("m7");
431
doTest("m8");
432
doTest("m9");
433
doTest("m10");
434
doTest("m11");
435
doTest("m12");
436
doTest("m13");
437
doTest("m14");
438
doTest("m15");
439
doTest("m16");
440
doTest("m17");
441
if (!success) {
442
throw new RuntimeException("Some tests failed");
443
}
444
assert(tests.isEmpty()) : tests;
445
}
446
}
447
448