Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/hotspot/jtreg/compiler/loopopts/TestEliminateNullCheckWithSplitIf.java
64478 views
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
/*
26
* @test
27
* @key stress randomness
28
* @bug 8275610
29
* @summary Null check for field access of object floats above null check resulting in a segfault.
30
* @requires vm.compiler2.enabled
31
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test
32
* -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:StressSeed=42 compiler.loopopts.TestEliminateNullCheckWithSplitIf
33
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.loopopts.TestEliminateNullCheckWithSplitIf::test
34
* -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:+StressIGVN compiler.loopopts.TestEliminateNullCheckWithSplitIf
35
*/
36
37
package compiler.loopopts;
38
39
public class TestEliminateNullCheckWithSplitIf {
40
public static int[] iArrFld = new int[20];
41
public static int[] iArrFld2 = new int[20];
42
public static int iFld = 10;
43
public static MyClass obj;
44
45
public static void main(String[] strArr) {
46
for (int i = 0; i < 10000; i++) {
47
obj = (i % 100 == 0 ? null : new MyClass());
48
test();
49
}
50
}
51
52
// The field access obj.iFld requires a null check NC3 and adds a not-null CastPP node on the succeeded projection.
53
// In the first IGVN after parsing, the null check NC3 can be subsumed by the explicit null check NC2.
54
// (done in IfNode::simple_subsuming()). The Bool node of NC2 is also shared with the same null check NC1 earlier.
55
// However, C2 cannot remove the null check NC2, yet, because the IR in between the two checks are too complex
56
// (IfNode::search_identical() fails).
57
// Now, loopopts are applied:
58
// (1) First, the split if optimization is done. It recognizes that NC1 and NC2 are back to back null checks and removes
59
// the null check NC2 by splitting it through the region R which is removed afterwards. In this process, control dependent
60
// data nodes on the out projections of NC2 end up at the new regions R1/R2 created for each projection for R. They get
61
// the last nodes of the if and else block as input. For this example, R1 is a control input to the CastPP node which
62
// will merge both true projections.
63
// (2) Later in loop opts, the loop L is transformed into normal code and y will become a constant 1.
64
// After loopopts, another round of IGVN is done:
65
// (These steps also depend on the order in which they are applied in order to trigger the bug)
66
// (1) The region R is removed because one path is dead (a result of the split if optimization).
67
// (2) The new If node added by the above split if optimization is also folded. This rewires the CastPP node to
68
// the last control node in the If block which is the true projection of range check RC2. Up until now, the CastPP
69
// is still after the null check NC1.
70
// (3) The range check RC2 is removed because the range check RC1 already covers this range (see RangeCheck::Ideal()).
71
// All data nodes which are control dependent on RC2 will be rewired to the dominating range check RC1, including
72
// the non-null CastPP node - which now has a control input above the null check NC1. This also means that the field
73
// load obj.iFld now has the same early control as the CastPP (CastPP -> AddP -> LoadI). Using StressGCM can
74
// now schedule the obj.iFld load before the null check NC1 because the early control allows it which leads to a
75
// segmentation fault if obj is null.
76
public static void test() {
77
int x = iArrFld[17]; // Emits range check RC1
78
if (obj != null) { // Null check NC1
79
int y = 0;
80
for (int i = 0; i < 1; i++) { // Loop L
81
y++;
82
}
83
// Use additional loop to keep the rangecheck for iArrFld[y] in before loopopts.
84
// y will become constant 1 but only once the loop above is removed in loopopts.
85
x = iArrFld[y]; // Emits range check RC2
86
} else {
87
x = iArrFld2[18];
88
}
89
// Region R merging the if and else paths above.
90
if (obj != null) { // Null check NC2
91
x = iArrFld2[obj.iFld]; // Emits Null check NC3 for obj.iFld
92
}
93
}
94
}
95
96
class MyClass {
97
int iFld;
98
}
99
100
101
102
103
104