Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit63e4b5c

Browse files
committed
8292260: [BACKOUT] JDK-8279219: [REDO] C2 crash when allocating array of size too large
Reviewed-by: stuefeBackport-of: 967a28c3d85fdde6d5eb48aa0edd8f7597772469
1 parente068eba commit63e4b5c

File tree

11 files changed

+75
-255
lines changed

11 files changed

+75
-255
lines changed

‎src/hotspot/share/opto/callnode.cpp‎

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,6 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype,
13781378
init_req( KlassNode , klass_node);
13791379
init_req( InitialTest , initial_test);
13801380
init_req( ALength , topnode);
1381-
init_req( ValidLengthTest , topnode);
13821381
C->add_macro_node(this);
13831382
}
13841383

@@ -1399,6 +1398,54 @@ void AllocateNode::compute_MemBar_redundancy(ciMethod* initializer)
13991398
}
14001399
}
14011400

1401+
//=============================================================================
1402+
Node*AllocateArrayNode::Ideal(PhaseGVN *phase,bool can_reshape) {
1403+
if (remove_dead_region(phase, can_reshape))returnthis;
1404+
// Don't bother trying to transform a dead node
1405+
if (in(0) &&in(0)->is_top())returnNULL;
1406+
1407+
const Type* type = phase->type(Ideal_length());
1408+
if (type->isa_int() && type->is_int()->_hi <0) {
1409+
if (can_reshape) {
1410+
PhaseIterGVN *igvn = phase->is_IterGVN();
1411+
// Unreachable fall through path (negative array length),
1412+
// the allocation can only throw so disconnect it.
1413+
Node* proj =proj_out_or_null(TypeFunc::Control);
1414+
Node* catchproj =NULL;
1415+
if (proj !=NULL) {
1416+
for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) {
1417+
Node *cn = proj->fast_out(i);
1418+
if (cn->is_Catch()) {
1419+
catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index);
1420+
break;
1421+
}
1422+
}
1423+
}
1424+
if (catchproj !=NULL && catchproj->outcnt() >0 &&
1425+
(catchproj->outcnt() >1 ||
1426+
catchproj->unique_out()->Opcode() != Op_Halt)) {
1427+
assert(catchproj->is_CatchProj(),"must be a CatchProjNode");
1428+
Node* nproj = catchproj->clone();
1429+
igvn->register_new_node_with_optimizer(nproj);
1430+
1431+
Node *frame =newParmNode( phase->C->start(), TypeFunc::FramePtr );
1432+
frame = phase->transform(frame);
1433+
// Halt & Catch Fire
1434+
Node* halt =newHaltNode(nproj, frame,"unexpected negative array length");
1435+
phase->C->root()->add_req(halt);
1436+
phase->transform(halt);
1437+
1438+
igvn->replace_node(catchproj, phase->C->top());
1439+
returnthis;
1440+
}
1441+
}else {
1442+
// Can't correct it during regular GVN so register for IGVN
1443+
phase->C->record_for_igvn(this);
1444+
}
1445+
}
1446+
returnNULL;
1447+
}
1448+
14021449
// Retrieve the length from the AllocateArrayNode. Narrow the type with a
14031450
// CastII, if appropriate. If we are not allowed to create new nodes, and
14041451
// a CastII is appropriate, return NULL.

‎src/hotspot/share/opto/callnode.hpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,6 @@ class AllocateNode : public CallNode {
839839
KlassNode,// type (maybe dynamic) of the obj.
840840
InitialTest,// slow-path test (may be constant)
841841
ALength,// array length (or TOP if none)
842-
ValidLengthTest,
843842
ParmLimit
844843
};
845844

@@ -849,7 +848,6 @@ class AllocateNode : public CallNode {
849848
fields[KlassNode] = TypeInstPtr::NOTNULL;
850849
fields[InitialTest] = TypeInt::BOOL;
851850
fields[ALength] = t;// length (can be a bad length)
852-
fields[ValidLengthTest] = TypeInt::BOOL;
853851

854852
const TypeTuple *domain =TypeTuple::make(ParmLimit, fields);
855853

@@ -947,16 +945,18 @@ class AllocateNode : public CallNode {
947945
//
948946
classAllocateArrayNode :publicAllocateNode {
949947
public:
950-
AllocateArrayNode(Compile* C,const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node,
951-
Node* initial_test, Node* count_val, Node* valid_length_test)
948+
AllocateArrayNode(Compile* C,const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
949+
Node* size, Node* klass_node, Node* initial_test,
950+
Node* count_val
951+
)
952952
: AllocateNode(C, atype, ctrl, mem, abio, size, klass_node,
953953
initial_test)
954954
{
955955
init_class_id(Class_AllocateArray);
956956
set_req(AllocateNode::ALength, count_val);
957-
set_req(AllocateNode::ValidLengthTest, valid_length_test);
958957
}
959958
virtualintOpcode()const;
959+
virtual Node *Ideal(PhaseGVN *phase,bool can_reshape);
960960

961961
// Dig the length operand out of a array allocation site.
962962
Node*Ideal_length() {

‎src/hotspot/share/opto/cfgnode.cpp‎

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,17 +2352,6 @@ const Type* CatchNode::Value(PhaseGVN* phase) const {
23522352
// Rethrows always throw exceptions, never return
23532353
if (call->entry_point() ==OptoRuntime::rethrow_stub()) {
23542354
f[CatchProjNode::fall_through_index] = Type::TOP;
2355-
}elseif (call->is_AllocateArray()) {
2356-
Node* klass_node = call->in(AllocateNode::KlassNode);
2357-
Node* length = call->in(AllocateNode::ALength);
2358-
const Type* length_type = phase->type(length);
2359-
const Type* klass_type = phase->type(klass_node);
2360-
Node* valid_length_test = call->in(AllocateNode::ValidLengthTest);
2361-
const Type*valid_length_test_t = phase->type(valid_length_test);
2362-
if (length_type == Type::TOP || klass_type == Type::TOP ||valid_length_test_t == Type::TOP ||
2363-
valid_length_test_t->is_int()->is_con(0)) {
2364-
f[CatchProjNode::fall_through_index] = Type::TOP;
2365-
}
23662355
}elseif( call->req() > TypeFunc::Parms ) {
23672356
const Type *arg0 = phase->type( call->in(TypeFunc::Parms) );
23682357
// Check for null receiver to virtual or interface calls

‎src/hotspot/share/opto/compile.cpp‎

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3706,7 +3706,7 @@ bool Compile::final_graph_reshaping() {
37063706
// 'fall-thru' path, so expected kids is 1 less.
37073707
if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) {
37083708
if (n->in(0)->in(0)->is_Call()) {
3709-
CallNode*call = n->in(0)->in(0)->as_Call();
3709+
CallNode *call = n->in(0)->in(0)->as_Call();
37103710
if (call->entry_point() ==OptoRuntime::rethrow_stub()) {
37113711
required_outcnt--;// Rethrow always has 1 less kid
37123712
}elseif (call->req() > TypeFunc::Parms &&
@@ -3715,25 +3715,22 @@ bool Compile::final_graph_reshaping() {
37153715
// detected that the virtual call will always result in a null
37163716
// pointer exception. The fall-through projection of this CatchNode
37173717
// will not be populated.
3718-
Node*arg0 = call->in(TypeFunc::Parms);
3718+
Node *arg0 = call->in(TypeFunc::Parms);
37193719
if (arg0->is_Type() &&
37203720
arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) {
37213721
required_outcnt--;
37223722
}
3723-
}elseif (call->entry_point() ==OptoRuntime::new_array_Java() ||
3724-
call->entry_point() ==OptoRuntime::new_array_nozero_Java()) {
3725-
// Check for illegal array length. In such case, the optimizer has
3723+
}elseif (call->entry_point() ==OptoRuntime::new_array_Java() &&
3724+
call->req() > TypeFunc::Parms+1 &&
3725+
call->is_CallStaticJava()) {
3726+
// Check for negative array length. In such case, the optimizer has
37263727
// detected that the allocation attempt will always result in an
37273728
// exception. There is no fall-through projection of this CatchNode .
3728-
assert(call->is_CallStaticJava(),"static call expected");
3729-
assert(call->req() == call->jvms()->endoff() +1,"missing extra input");
3730-
Node* valid_length_test = call->in(call->req()-1);
3731-
call->del_req(call->req()-1);
3732-
if (valid_length_test->find_int_con(1) ==0) {
3729+
Node *arg1 = call->in(TypeFunc::Parms+1);
3730+
if (arg1->is_Type() &&
3731+
arg1->as_Type()->type()->join(TypeInt::POS)->empty()) {
37333732
required_outcnt--;
37343733
}
3735-
assert(n->outcnt() == required_outcnt,"malformed control flow");
3736-
continue;
37373734
}
37383735
}
37393736
}
@@ -3742,14 +3739,6 @@ bool Compile::final_graph_reshaping() {
37423739
record_method_not_compilable("malformed control flow");
37433740
returntrue;// Not all targets reachable!
37443741
}
3745-
}elseif (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) {
3746-
CallNode* call = n->in(0)->in(0)->as_Call();
3747-
if (call->entry_point() ==OptoRuntime::new_array_Java() ||
3748-
call->entry_point() ==OptoRuntime::new_array_nozero_Java()) {
3749-
assert(call->is_CallStaticJava(),"static call expected");
3750-
assert(call->req() == call->jvms()->endoff() +1,"missing extra input");
3751-
call->del_req(call->req()-1);// valid length test useless now
3752-
}
37533742
}
37543743
// Check that I actually visited all kids. Unreached kids
37553744
// must be infinite loops.

‎src/hotspot/share/opto/graphKit.cpp‎

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2593,9 +2593,7 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep
25932593
// Make a catch node with just two handlers: fall-through and catch-all
25942594
Node* i_o = _gvn.transform(newProjNode(call, TypeFunc::I_O, separate_io_proj) );
25952595
Node* catc = _gvn.transform(newCatchNode(control(), i_o,2) );
2596-
Node* norm =newCatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci);
2597-
_gvn.set_type_bottom(norm);
2598-
C->record_for_igvn(norm);
2596+
Node* norm = _gvn.transform(newCatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) );
25992597
Node* excp = _gvn.transform(newCatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) );
26002598

26012599
{ PreserveJVMStatepjvms(this);
@@ -3731,28 +3729,20 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
37313729
initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
37323730
}
37333731

3734-
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
3735-
Node* valid_length_test = _gvn.intcon(1);
3736-
if (ary_type->klass()->is_array_klass()) {
3737-
BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type();
3738-
jint max =TypeAryPtr::max_array_length(bt);
3739-
Node* valid_length_cmp = _gvn.transform(newCmpUNode(length,intcon(max)));
3740-
valid_length_test = _gvn.transform(newBoolNode(valid_length_cmp, BoolTest::le));
3741-
}
3742-
37433732
// Create the AllocateArrayNode and its result projections
37443733
AllocateArrayNode* alloc
37453734
=newAllocateArrayNode(C,AllocateArrayNode::alloc_type(TypeInt::INT),
37463735
control(), mem,i_o(),
37473736
size, klass_node,
37483737
initial_slow_test,
3749-
length, valid_length_test);
3738+
length);
37503739

37513740
// Cast to correct type. Note that the klass_node may be constant or not,
37523741
// and in the latter case the actual array type will be inexact also.
37533742
// (This happens via a non-constant argument to inline_native_newArray.)
37543743
// In any case, the value of klass_node provides the desired array type.
37553744
const TypeInt* length_type = _gvn.find_int_type(length);
3745+
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
37563746
if (ary_type->isa_aryptr() && length_type !=NULL) {
37573747
// Try to get a better type than POS for the size
37583748
ary_type = ary_type->is_aryptr()->cast_to_size(length_type);

‎src/hotspot/share/opto/macro.cpp‎

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,8 +1288,7 @@ void PhaseMacroExpand::expand_allocate_common(
12881288
AllocateNode* alloc,// allocation node to be expanded
12891289
Node* length,// array length for an array allocation
12901290
const TypeFunc* slow_call_type,// Type of slow call
1291-
address slow_call_address,// Address of slow call
1292-
Node* valid_length_test// whether length is valid or not
1291+
address slow_call_address// Address of slow call
12931292
)
12941293
{
12951294

@@ -1629,12 +1628,6 @@ void PhaseMacroExpand::expand_allocate_common(
16291628
// Copy debug information and adjust JVMState information, then replace
16301629
// allocate node with the call
16311630
copy_call_debug_info((CallNode *) alloc, call);
1632-
// For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify
1633-
// that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough
1634-
// path dies).
1635-
if (valid_length_test !=NULL) {
1636-
call->add_req(valid_length_test);
1637-
}
16381631
if (!always_slow) {
16391632
call->set_cnt(PROB_UNLIKELY_MAG(4));// Same effect as RC_UNCOMMON.
16401633
}else {
@@ -1989,12 +1982,11 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false,
19891982
voidPhaseMacroExpand::expand_allocate(AllocateNode *alloc) {
19901983
expand_allocate_common(alloc,NULL,
19911984
OptoRuntime::new_instance_Type(),
1992-
OptoRuntime::new_instance_Java(),NULL);
1985+
OptoRuntime::new_instance_Java());
19931986
}
19941987

19951988
voidPhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
19961989
Node* length = alloc->in(AllocateNode::ALength);
1997-
Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest);
19981990
InitializeNode* init = alloc->initialization();
19991991
Node* klass_node = alloc->in(AllocateNode::KlassNode);
20001992
ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass();
@@ -2009,7 +2001,7 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
20092001
}
20102002
expand_allocate_common(alloc, length,
20112003
OptoRuntime::new_array_Type(),
2012-
slow_call_address, valid_length_test);
2004+
slow_call_address);
20132005
}
20142006

20152007
//-------------------mark_eliminated_box----------------------------------

‎src/hotspot/share/opto/macro.hpp‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ class PhaseMacroExpand : public Phase {
9898
voidexpand_allocate_common(AllocateNode* alloc,
9999
Node* length,
100100
const TypeFunc* slow_call_type,
101-
address slow_call_address,
102-
Node* valid_length_test);
101+
address slow_call_address);
103102
Node *value_from_mem(Node *mem, Node *ctl, BasicType ft,const Type *ftype,const TypeOopPtr *adr_t, AllocateNode *alloc);
104103
Node *value_from_mem_phi(Node *mem, BasicType ft,const Type *ftype,const TypeOopPtr *adr_t, AllocateNode *alloc, Node_Stack *value_phis,int level);
105104

‎src/hotspot/share/opto/split_if.cpp‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
128128
}
129129
}else {
130130
// We might see an Opaque1 from a loop limit check here
131-
assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1 || use->is_AllocateArray(),"unexpected node type");
132-
Node *use_c =(use->is_If() || use->is_AllocateArray()) ? use->in(0) :get_ctrl(use);
131+
assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1,"unexpected node type");
132+
Node *use_c = use->is_If() ? use->in(0) :get_ctrl(use);
133133
if (use_c == blk1 || use_c == blk2) {
134134
assert(use->is_CMove(),"unexpected node type");
135135
continue;
@@ -166,15 +166,14 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
166166
--j;
167167
}else {
168168
// We might see an Opaque1 from a loop limit check here
169-
assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1 || u->is_AllocateArray(),"unexpected node type");
170-
assert(u->is_AllocateArray() || u->in(1) == bol,"");
171-
assert(!u->is_AllocateArray() || u->in(AllocateNode::ValidLengthTest) == bol,"wrong input to AllocateArray");
169+
assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1,"unexpected node type");
170+
assert(u->in(1) == bol,"");
172171
// Get control block of either the CMove or the If input
173-
Node *u_ctrl =(u->is_If() || u->is_AllocateArray()) ? u->in(0) :get_ctrl(u);
172+
Node *u_ctrl = u->is_If() ? u->in(0) :get_ctrl(u);
174173
assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(),"won't converge");
175174
Node *x = bol->clone();
176175
register_new_node(x, u_ctrl);
177-
_igvn.replace_input_of(u,u->is_AllocateArray() ? AllocateNode::ValidLengthTest :1, x);
176+
_igvn.replace_input_of(u,1, x);
178177
--j;
179178
}
180179
}

‎test/hotspot/jtreg/compiler/allocation/TestAllocArrayAfterAllocNoUse.java‎

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp