Skip to content

Commit b05fa02

Browse files
Hui ShiDamonFool
authored andcommitted
8267904: C2 crash when compile negative Arrays.copyOf length after loop
Reviewed-by: roland, kvn
1 parent 95ddf7d commit b05fa02

File tree

4 files changed

+98
-3
lines changed

4 files changed

+98
-3
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: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3971,8 +3971,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
39713971
if (map()->find_edge(length) >= 0) {
39723972
Node* ccast = alloc->make_ideal_length(ary_type, &_gvn);
39733973
if (ccast != length) {
3974-
_gvn.set_type_bottom(ccast);
3975-
record_for_igvn(ccast);
3974+
ccast = _gvn.transform(ccast);
39763975
replace_in_map(length, ccast);
39773976
}
39783977
}

src/hotspot/share/opto/library_call.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4443,6 +4443,30 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
44434443
Node* alloc_mem = alloc->in(TypeFunc::Memory);
44444444
C->gvn_replace_by(callprojs.fallthrough_ioproj, alloc->in(TypeFunc::I_O));
44454445
C->gvn_replace_by(init->proj_out(TypeFunc::Memory), alloc_mem);
4446+
4447+
// The CastIINode created in GraphKit::new_array (in AllocateArrayNode::make_ideal_length) must stay below
4448+
// the allocation (i.e. is only valid if the allocation succeeds):
4449+
// 1) replace CastIINode with AllocateArrayNode's length here
4450+
// 2) Create CastIINode again once allocation has moved (see below) at the end of this method
4451+
Node* init_control = init->proj_out(TypeFunc::Control);
4452+
Node* alloc_length = alloc->Ideal_length();
4453+
#ifdef ASSERT
4454+
Node* prev_cast = NULL;
4455+
#endif
4456+
for (uint i = 0; i < init_control->outcnt(); i++) {
4457+
Node *init_out = init_control->raw_out(i);
4458+
if (init_out->is_CastII() && init_out->in(0) == init_control && init_out->in(1) == alloc_length) {
4459+
#ifdef ASSERT
4460+
if (prev_cast == NULL) {
4461+
prev_cast = init_out;
4462+
assert(_gvn.hash_find(prev_cast) != NULL, "not found");
4463+
} else {
4464+
assert(_gvn.hash_find(prev_cast) == _gvn.hash_find(init_out), "not equal CastIINode");
4465+
}
4466+
#endif
4467+
C->gvn_replace_by(init_out, alloc_length);
4468+
}
4469+
}
44464470
C->gvn_replace_by(init->proj_out(TypeFunc::Control), alloc->in(0));
44474471

44484472
// move the allocation here (after the guards)
@@ -4474,6 +4498,18 @@ void LibraryCallKit::arraycopy_move_allocation_here(AllocateArrayNode* alloc, No
44744498
dest->set_req(0, control());
44754499
Node* destx = _gvn.transform(dest);
44764500
assert(destx == dest, "where has the allocation result gone?");
4501+
4502+
// Cast length on remaining path to be as narrow as possible
4503+
// previous CastNode inserted when creating AllocateArrayNode
4504+
// is removed in early step in LibraryCallKit::inline_arraycopy
4505+
Node* length = alloc->in(AllocateNode::ALength);
4506+
if (map()->find_edge(length) >= 0) {
4507+
Node* ccast = alloc->make_ideal_length(ary_type, &_gvn);
4508+
if (ccast != length) {
4509+
ccast = _gvn.transform(ccast);
4510+
replace_in_map(length, ccast);
4511+
}
4512+
}
44774513
}
44784514
}
44794515

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.c2.TestNegativeArrayCopyAfterLoop
30+
*/
31+
32+
package compiler.c2;
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)