Skip to content

Commit e5e21a8

Browse files
committed
8328702: C2: Crash during parsing because sub type check is not folded
Reviewed-by: roland, kvn
1 parent f762637 commit e5e21a8

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

src/hotspot/share/opto/graphKit.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2709,7 +2709,18 @@ Node* Phase::gen_subtype_check(Node* subklass, Node* superklass, Node** ctrl, No
27092709
// Foo[] fa = blah(); Foo x = fa[0]; fa[1] = x;
27102710
// Here, the type of 'fa' is often exact, so the store check
27112711
// of fa[1]=x will fold up, without testing the nullness of x.
2712-
switch (C->static_subtype_check(superk, subk)) {
2712+
//
2713+
// Do not skip the static sub type check with StressReflectiveCode during
2714+
// parsing (i.e. with ExpandSubTypeCheckAtParseTime) because the
2715+
// associated CheckCastNodePP could already be folded when the type
2716+
// system can prove it's an impossible type. Therefore, we should also
2717+
// do the static sub type check here to ensure control is folded as well.
2718+
// Otherwise, the graph is left in a broken state.
2719+
// At macro expansion, we would have already folded the SubTypeCheckNode
2720+
// being expanded here because we always perform the static sub type
2721+
// check in SubTypeCheckNode::sub() regardless of whether
2722+
// StressReflectiveCode is set or not.
2723+
switch (C->static_subtype_check(superk, subk, !ExpandSubTypeCheckAtParseTime)) {
27132724
case Compile::SSC_always_false:
27142725
{
27152726
Node* always_fail = *ctrl;

src/hotspot/share/opto/type.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6458,14 +6458,19 @@ template <class T1, class T2> bool TypePtr::maybe_java_subtype_of_helper_for_arr
64586458
if (other->klass() == ciEnv::current()->Object_klass() && other->_interfaces->empty() && other_exact) {
64596459
return true;
64606460
}
6461-
int dummy;
6462-
bool this_top_or_bottom = (this_one->base_element_type(dummy) == Type::TOP || this_one->base_element_type(dummy) == Type::BOTTOM);
6463-
if (!this_one->is_loaded() || !other->is_loaded() || this_top_or_bottom) {
6461+
if (!this_one->is_loaded() || !other->is_loaded()) {
64646462
return true;
64656463
}
64666464
if (this_one->is_instance_type(other)) {
64676465
return other->klass()->equals(ciEnv::current()->Object_klass()) && other->_interfaces->intersection_with(this_one->_interfaces)->eq(other->_interfaces);
64686466
}
6467+
6468+
int dummy;
6469+
bool this_top_or_bottom = (this_one->base_element_type(dummy) == Type::TOP || this_one->base_element_type(dummy) == Type::BOTTOM);
6470+
if (this_top_or_bottom) {
6471+
return true;
6472+
}
6473+
64696474
assert(this_one->is_array_type(other), "");
64706475

64716476
const T1* other_ary = this_one->is_array_type(other);
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 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 id=Xcomp
26+
* @bug 8328702
27+
* @summary Check that SubTypeCheckNode is properly folded when having an array with bottom type elements checked
28+
* against an interface.
29+
*
30+
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.types.TestSubTypeCheckWithBottomArray::test*
31+
* -XX:CompileCommand=inline,compiler.types.TestSubTypeCheckWithBottomArray::check*
32+
* compiler.types.TestSubTypeCheckWithBottomArray
33+
*/
34+
35+
/*
36+
* @test id=Xbatch
37+
* @bug 8328702
38+
* @summary Check that SubTypeCheckNode is properly folded when having an array with bottom type elements checked
39+
* against an interface.
40+
*
41+
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.types.TestSubTypeCheckWithBottomArray::test*
42+
* -XX:CompileCommand=inline,compiler.types.TestSubTypeCheckWithBottomArray::check*
43+
* compiler.types.TestSubTypeCheckWithBottomArray
44+
*/
45+
46+
/*
47+
* @test id=stress
48+
* @bug 8328702
49+
* @summary Check that PartialSubtypeCheckNode is properly folded when having an array with bottom type elements checked
50+
* either against an interface or an unrelated non-sub-class.
51+
*
52+
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.types.TestSubTypeCheckWithBottomArray::test*
53+
* -XX:+UnlockDiagnosticVMOptions -XX:+ExpandSubTypeCheckAtParseTime
54+
* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressReflectiveCode
55+
* -XX:CompileCommand=inline,compiler.types.TestSubTypeCheckWithBottomArray::check*
56+
* compiler.types.TestSubTypeCheckWithBottomArray
57+
* @run main/othervm -Xbatch -XX:CompileCommand=compileonly,compiler.types.TestSubTypeCheckWithBottomArray::test*
58+
* -XX:+UnlockDiagnosticVMOptions -XX:+ExpandSubTypeCheckAtParseTime
59+
* -XX:+IgnoreUnrecognizedVMOptions -XX:+StressReflectiveCode
60+
* -XX:CompileCommand=inline,compiler.types.TestSubTypeCheckWithBottomArray::check*
61+
* compiler.types.TestSubTypeCheckWithBottomArray
62+
*/
63+
64+
package compiler.types;
65+
66+
public class TestSubTypeCheckWithBottomArray {
67+
static byte[] bArr = new byte[10];
68+
static Object[] oArr = new Object[10];
69+
static boolean flag;
70+
71+
public static void main(String[] args) {
72+
A a = new A();
73+
B b = new B();
74+
Y y = new Y();
75+
Z z = new Z();
76+
for (int i = 0; i < 10000; i++) {
77+
// With -Xcomp: Immediatly crashes because of no profiling -> don't know anything.
78+
checkInterface(a); // Make sure that checkInterface() sometimes passes instanceof.
79+
checkInterface(b); // Use two sub classes such that checkcast is required.
80+
testInterface();
81+
82+
checkClass(y); // Make sure that checkClass() sometimes passes instanceof.
83+
checkClass(z); // Use two sub classes such that checkcast is required.
84+
testClass();
85+
flag = !flag;
86+
}
87+
}
88+
89+
static void testInterface() {
90+
checkInterface(flag ? bArr : oArr); // Inlined, never passes instanceof
91+
}
92+
93+
static void checkInterface(Object o) {
94+
if (o instanceof I i) {
95+
// Use of i: Needs CheckCastPP which is replaced by top because [bottom <: I cannot be true.
96+
// But: SubTypeCheckNode is not folded away -> broken graph (data dies, control not)
97+
i.getClass();
98+
}
99+
}
100+
101+
static void testClass() {
102+
checkClass(flag ? bArr : oArr); // Inlined, never passes instanceof
103+
}
104+
105+
static void checkClass(Object o) {
106+
if (o instanceof X x) {
107+
// Use of i: Needs CheckCastPP which is replaced by top because [bottom <: I cannot be true.
108+
// But: SubTypeCheckNode is not folded away -> broken graph (data dies, control not)
109+
x.getClass();
110+
}
111+
}
112+
113+
}
114+
115+
interface I {}
116+
class A implements I {}
117+
class B implements I {}
118+
119+
class X {}
120+
class Y extends X {}
121+
class Z extends X {}

0 commit comments

Comments
 (0)