Skip to content

Commit 2252165

Browse files
committed
8268362: [REDO] C2 crash when compile negative Arrays.copyOf length after loop
Backport-of: 22ebd19
1 parent 8008d33 commit 2252165

File tree

7 files changed

+227
-16
lines changed

7 files changed

+227
-16
lines changed

src/hotspot/share/opto/callnode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,7 @@ Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTran
14761476
InitializeNode* init = initialization();
14771477
assert(init != NULL, "initialization not found");
14781478
length = new CastIINode(length, narrow_length_type);
1479-
length->set_req(0, init->proj_out_or_null(0));
1479+
length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control));
14801480
}
14811481
}
14821482

src/hotspot/share/opto/graphKit.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,15 +1180,31 @@ Node* GraphKit::load_array_length(Node* array) {
11801180
Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes());
11811181
alen = _gvn.transform( new LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS));
11821182
} else {
1183-
alen = alloc->Ideal_length();
1184-
Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn);
1185-
if (ccast != alen) {
1186-
alen = _gvn.transform(ccast);
1187-
}
1183+
alen = array_ideal_length(alloc, _gvn.type(array)->is_oopptr(), false);
11881184
}
11891185
return alen;
11901186
}
11911187

1188+
Node* GraphKit::array_ideal_length(AllocateArrayNode* alloc,
1189+
const TypeOopPtr* oop_type,
1190+
bool replace_length_in_map) {
1191+
Node* length = alloc->Ideal_length();
1192+
if (replace_length_in_map == false || map()->find_edge(length) >= 0) {
1193+
Node* ccast = alloc->make_ideal_length(oop_type, &_gvn);
1194+
if (ccast != length) {
1195+
// do not transfrom ccast here, it might convert to top node for
1196+
// negative array length and break assumptions in parsing stage.
1197+
_gvn.set_type_bottom(ccast);
1198+
record_for_igvn(ccast);
1199+
if (replace_length_in_map) {
1200+
replace_in_map(length, ccast);
1201+
}
1202+
return ccast;
1203+
}
1204+
}
1205+
return length;
1206+
}
1207+
11921208
//------------------------------do_null_check----------------------------------
11931209
// Helper function to do a NULL pointer check. Returned value is
11941210
// the incoming address with NULL casted away. You are allowed to use the
@@ -3734,16 +3750,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
37343750

37353751
Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception);
37363752

3737-
// Cast length on remaining path to be as narrow as possible
3738-
if (map()->find_edge(length) >= 0) {
3739-
Node* ccast = alloc->make_ideal_length(ary_type, &_gvn);
3740-
if (ccast != length) {
3741-
_gvn.set_type_bottom(ccast);
3742-
record_for_igvn(ccast);
3743-
replace_in_map(length, ccast);
3744-
}
3745-
}
3746-
3753+
array_ideal_length(alloc, ary_type, true);
37473754
return javaoop;
37483755
}
37493756

src/hotspot/share/opto/graphKit.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,12 @@ class GraphKit : public Phase {
336336
Node* load_object_klass(Node* object);
337337
// Find out the length of an array.
338338
Node* load_array_length(Node* array);
339+
// Cast array allocation's length as narrow as possible.
340+
// If replace_length_in_map is true, replace length with CastIINode in map.
341+
// This method is invoked after creating/moving ArrayAllocationNode or in load_array_length
342+
Node* array_ideal_length(AllocateArrayNode* alloc,
343+
const TypeOopPtr* oop_type,
344+
bool replace_length_in_map);
339345

340346

341347
// Helper function to do a NULL pointer check or ZERO check based on type.

src/hotspot/share/opto/library_call.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,36 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
45924592
Node* alloc_mem = alloc->in(TypeFunc::Memory);
45934593
C->gvn_replace_by(callprojs.fallthrough_ioproj, alloc->in(TypeFunc::I_O));
45944594
C->gvn_replace_by(init->proj_out(TypeFunc::Memory), alloc_mem);
4595+
4596+
// The CastIINode created in GraphKit::new_array (in AllocateArrayNode::make_ideal_length) must stay below
4597+
// the allocation (i.e. is only valid if the allocation succeeds):
4598+
// 1) replace CastIINode with AllocateArrayNode's length here
4599+
// 2) Create CastIINode again once allocation has moved (see below) at the end of this method
4600+
//
4601+
// Multiple identical CastIINodes might exist here. Each GraphKit::load_array_length() call will generate
4602+
// new separate CastIINode (arraycopy guard checks or any array length use between array allocation and ararycopy)
4603+
Node* init_control = init->proj_out(TypeFunc::Control);
4604+
Node* alloc_length = alloc->Ideal_length();
4605+
#ifdef ASSERT
4606+
Node* prev_cast = NULL;
4607+
#endif
4608+
for (uint i = 0; i < init_control->outcnt(); i++) {
4609+
Node* init_out = init_control->raw_out(i);
4610+
if (init_out->is_CastII() && init_out->in(TypeFunc::Control) == init_control && init_out->in(1) == alloc_length) {
4611+
#ifdef ASSERT
4612+
if (prev_cast == NULL) {
4613+
prev_cast = init_out;
4614+
} else {
4615+
if (prev_cast->cmp(*init_out) == false) {
4616+
prev_cast->dump();
4617+
init_out->dump();
4618+
assert(false, "not equal CastIINode");
4619+
}
4620+
}
4621+
#endif
4622+
C->gvn_replace_by(init_out, alloc_length);
4623+
}
4624+
}
45954625
C->gvn_replace_by(init->proj_out(TypeFunc::Control), alloc->in(0));
45964626

45974627
// move the allocation here (after the guards)
@@ -4623,6 +4653,8 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
46234653
dest->set_req(0, control());
46244654
Node* destx = _gvn.transform(dest);
46254655
assert(destx == dest, "where has the allocation result gone?");
4656+
4657+
array_ideal_length(alloc, ary_type, true);
46264658
}
46274659
}
46284660

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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 8268362
27+
* @requires vm.compiler2.enabled & vm.debug
28+
* @summary C2 using negative array length as index, using a.length.
29+
* AllocateArrayNode::make_ideal_length create CastIINode to not negative range.
30+
* Apply transform in GraphKit::load_array_length will covert array load index type to top.
31+
* This cause assert in Parse::array_addressing, it expect index type is int.
32+
* @run main/othervm -XX:-PrintCompilation compiler.arraycopy.TestNegArrayLengthAsIndex1
33+
*/
34+
35+
package compiler.arraycopy;
36+
public class TestNegArrayLengthAsIndex1 {
37+
38+
public static void main(String[] args) throws Exception {
39+
for (int i = 0; i < 10000; i++) {
40+
foo();
41+
}
42+
}
43+
44+
static int foo() {
45+
int minusOne = -1;
46+
int[] a = null;
47+
try {
48+
a = new int[minusOne];
49+
} catch (NegativeArraySizeException e) {
50+
return 0;
51+
}
52+
return a[a.length - 1];
53+
}
54+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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 8268362
27+
* @requires vm.compiler2.enabled & vm.debug
28+
* @summary C2 using negative array length as index, using array allocation length.
29+
* This assertion is triggered by 8267904.
30+
* @run main/othervm compiler.arraycopy.TestNegArrayLengthAsIndex2
31+
*/
32+
33+
package compiler.arraycopy;
34+
public class TestNegArrayLengthAsIndex2 {
35+
36+
public static void main(String[] args) throws Exception {
37+
for (int i = 0; i < 10000; i++) {
38+
foo();
39+
}
40+
}
41+
42+
static int foo() {
43+
int minusOne = -1;
44+
int[] a = null;
45+
try {
46+
a = new int[minusOne];
47+
} catch (NegativeArraySizeException e) {
48+
return 0;
49+
}
50+
return a[minusOne - 1];
51+
}
52+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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 8267904
27+
* @requires vm.compiler2.enabled
28+
* @summary C2 inline array_copy move CastIINode(Array Length) before allocation cause crash.
29+
* @run main/othervm compiler.arraycopy.TestNegativeArrayCopyAfterLoop
30+
*/
31+
32+
package compiler.arraycopy;
33+
import java.util.Arrays;
34+
35+
class test {
36+
public static int exp_count = 0;
37+
public int in1 = -4096;
38+
test (){
39+
try {
40+
short sha4[] = new short[1012];
41+
for (int i = 0; i < sha4.length; i++) {
42+
sha4[i] = 9;
43+
}
44+
Arrays.copyOf(sha4, in1);
45+
} catch (Exception ex) {
46+
exp_count++;
47+
}
48+
}
49+
}
50+
51+
public class TestNegativeArrayCopyAfterLoop {
52+
public static void main(String[] args) {
53+
for (int i = 0; i < 20000; i++) {
54+
new test();
55+
}
56+
if (test.exp_count == 20000) {
57+
System.out.println("TEST PASSED");
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)