Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit 22ebd19

Browse files
author
Hui Shi
committed
8268362: [REDO] C2 crash when compile negative Arrays.copyOf length after loop
Reviewed-by: kvn, roland
1 parent f8df953 commit 22ebd19

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
@@ -1758,7 +1758,7 @@ Node *AllocateArrayNode::make_ideal_length(const TypeOopPtr* oop_type, PhaseTran
17581758
InitializeNode* init = initialization();
17591759
assert(init != NULL, "initialization not found");
17601760
length = new CastIINode(length, narrow_length_type);
1761-
length->set_req(0, init->proj_out_or_null(0));
1761+
length->set_req(TypeFunc::Control, init->proj_out_or_null(TypeFunc::Control));
17621762
}
17631763
}
17641764

src/hotspot/share/opto/graphKit.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,15 +1184,31 @@ Node* GraphKit::load_array_length(Node* array) {
11841184
Node *r_adr = basic_plus_adr(array, arrayOopDesc::length_offset_in_bytes());
11851185
alen = _gvn.transform( new LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS));
11861186
} else {
1187-
alen = alloc->Ideal_length();
1188-
Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn);
1189-
if (ccast != alen) {
1190-
alen = _gvn.transform(ccast);
1191-
}
1187+
alen = array_ideal_length(alloc, _gvn.type(array)->is_oopptr(), false);
11921188
}
11931189
return alen;
11941190
}
11951191

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

39813997
Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception);
39823998

3983-
// Cast length on remaining path to be as narrow as possible
3984-
if (map()->find_edge(length) >= 0) {
3985-
Node* ccast = alloc->make_ideal_length(ary_type, &_gvn);
3986-
if (ccast != length) {
3987-
_gvn.set_type_bottom(ccast);
3988-
record_for_igvn(ccast);
3989-
replace_in_map(length, ccast);
3990-
}
3991-
}
3992-
3999+
array_ideal_length(alloc, ary_type, true);
39934000
return javaoop;
39944001
}
39954002

src/hotspot/share/opto/graphKit.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ class GraphKit : public Phase {
343343
Node* load_object_klass(Node* object);
344344
// Find out the length of an array.
345345
Node* load_array_length(Node* array);
346+
// Cast array allocation's length as narrow as possible.
347+
// If replace_length_in_map is true, replace length with CastIINode in map.
348+
// This method is invoked after creating/moving ArrayAllocationNode or in load_array_length
349+
Node* array_ideal_length(AllocateArrayNode* alloc,
350+
const TypeOopPtr* oop_type,
351+
bool replace_length_in_map);
346352

347353

348354
// 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
@@ -4445,6 +4445,36 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
44454445
Node* alloc_mem = alloc->in(TypeFunc::Memory);
44464446
C->gvn_replace_by(callprojs.fallthrough_ioproj, alloc->in(TypeFunc::I_O));
44474447
C->gvn_replace_by(init->proj_out(TypeFunc::Memory), alloc_mem);
4448+
4449+
// The CastIINode created in GraphKit::new_array (in AllocateArrayNode::make_ideal_length) must stay below
4450+
// the allocation (i.e. is only valid if the allocation succeeds):
4451+
// 1) replace CastIINode with AllocateArrayNode's length here
4452+
// 2) Create CastIINode again once allocation has moved (see below) at the end of this method
4453+
//
4454+
// Multiple identical CastIINodes might exist here. Each GraphKit::load_array_length() call will generate
4455+
// new separate CastIINode (arraycopy guard checks or any array length use between array allocation and ararycopy)
4456+
Node* init_control = init->proj_out(TypeFunc::Control);
4457+
Node* alloc_length = alloc->Ideal_length();
4458+
#ifdef ASSERT
4459+
Node* prev_cast = NULL;
4460+
#endif
4461+
for (uint i = 0; i < init_control->outcnt(); i++) {
4462+
Node* init_out = init_control->raw_out(i);
4463+
if (init_out->is_CastII() && init_out->in(TypeFunc::Control) == init_control && init_out->in(1) == alloc_length) {
4464+
#ifdef ASSERT
4465+
if (prev_cast == NULL) {
4466+
prev_cast = init_out;
4467+
} else {
4468+
if (prev_cast->cmp(*init_out) == false) {
4469+
prev_cast->dump();
4470+
init_out->dump();
4471+
assert(false, "not equal CastIINode");
4472+
}
4473+
}
4474+
#endif
4475+
C->gvn_replace_by(init_out, alloc_length);
4476+
}
4477+
}
44484478
C->gvn_replace_by(init->proj_out(TypeFunc::Control), alloc->in(0));
44494479

44504480
// move the allocation here (after the guards)
@@ -4476,6 +4506,8 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
44764506
dest->set_req(0, control());
44774507
Node* destx = _gvn.transform(dest);
44784508
assert(destx == dest, "where has the allocation result gone?");
4509+
4510+
array_ideal_length(alloc, ary_type, true);
44794511
}
44804512
}
44814513

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)