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
This repository was archived by the owner on Sep 19, 2023. It is now read-only.
/jdk19Public archive

Commit967a28c

Browse files
author
Vladimir Kozlov
committed
8292260: [BACKOUT] JDK-8279219: [REDO] C2 crash when allocating array of size too large
Reviewed-by: vlivanov
1 parent4c6d22a commit967a28c

File tree

11 files changed

+76
-255
lines changed

11 files changed

+76
-255
lines changed

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

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1550,7 +1550,6 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype,
15501550
init_req( KlassNode , klass_node);
15511551
init_req( InitialTest , initial_test);
15521552
init_req( ALength , topnode);
1553-
init_req( ValidLengthTest , topnode);
15541553
C->add_macro_node(this);
15551554
}
15561555

@@ -1577,6 +1576,54 @@ Node *AllocateNode::make_ideal_mark(PhaseGVN *phase, Node* obj, Node* control, N
15771576
return mark_node;
15781577
}
15791578

1579+
//=============================================================================
1580+
Node*AllocateArrayNode::Ideal(PhaseGVN *phase,bool can_reshape) {
1581+
if (remove_dead_region(phase, can_reshape))returnthis;
1582+
// Don't bother trying to transform a dead node
1583+
if (in(0) &&in(0)->is_top())returnNULL;
1584+
1585+
const Type* type = phase->type(Ideal_length());
1586+
if (type->isa_int() && type->is_int()->_hi <0) {
1587+
if (can_reshape) {
1588+
PhaseIterGVN *igvn = phase->is_IterGVN();
1589+
// Unreachable fall through path (negative array length),
1590+
// the allocation can only throw so disconnect it.
1591+
Node* proj =proj_out_or_null(TypeFunc::Control);
1592+
Node* catchproj =NULL;
1593+
if (proj !=NULL) {
1594+
for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) {
1595+
Node *cn = proj->fast_out(i);
1596+
if (cn->is_Catch()) {
1597+
catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index);
1598+
break;
1599+
}
1600+
}
1601+
}
1602+
if (catchproj !=NULL && catchproj->outcnt() >0 &&
1603+
(catchproj->outcnt() >1 ||
1604+
catchproj->unique_out()->Opcode() != Op_Halt)) {
1605+
assert(catchproj->is_CatchProj(),"must be a CatchProjNode");
1606+
Node* nproj = catchproj->clone();
1607+
igvn->register_new_node_with_optimizer(nproj);
1608+
1609+
Node *frame =newParmNode( phase->C->start(), TypeFunc::FramePtr );
1610+
frame = phase->transform(frame);
1611+
// Halt & Catch Fire
1612+
Node* halt =newHaltNode(nproj, frame,"unexpected negative array length");
1613+
phase->C->root()->add_req(halt);
1614+
phase->transform(halt);
1615+
1616+
igvn->replace_node(catchproj, phase->C->top());
1617+
returnthis;
1618+
}
1619+
}else {
1620+
// Can't correct it during regular GVN so register for IGVN
1621+
phase->C->record_for_igvn(this);
1622+
}
1623+
}
1624+
returnNULL;
1625+
}
1626+
15801627
// Retrieve the length from the AllocateArrayNode. Narrow the type with a
15811628
// CastII, if appropriate. If we are not allowed to create new nodes, and
15821629
// 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
@@ -874,7 +874,6 @@ class AllocateNode : public CallNode {
874874
KlassNode,// type (maybe dynamic) of the obj.
875875
InitialTest,// slow-path test (may be constant)
876876
ALength,// array length (or TOP if none)
877-
ValidLengthTest,
878877
ParmLimit
879878
};
880879

@@ -884,7 +883,6 @@ class AllocateNode : public CallNode {
884883
fields[KlassNode] = TypeInstPtr::NOTNULL;
885884
fields[InitialTest] = TypeInt::BOOL;
886885
fields[ALength] = t;// length (can be a bad length)
887-
fields[ValidLengthTest] = TypeInt::BOOL;
888886

889887
const TypeTuple *domain =TypeTuple::make(ParmLimit, fields);
890888

@@ -979,16 +977,18 @@ class AllocateNode : public CallNode {
979977
//
980978
classAllocateArrayNode :publicAllocateNode {
981979
public:
982-
AllocateArrayNode(Compile* C,const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node,
983-
Node* initial_test, Node* count_val, Node* valid_length_test)
980+
AllocateArrayNode(Compile* C,const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
981+
Node* size, Node* klass_node, Node* initial_test,
982+
Node* count_val
983+
)
984984
: AllocateNode(C, atype, ctrl, mem, abio, size, klass_node,
985985
initial_test)
986986
{
987987
init_class_id(Class_AllocateArray);
988988
set_req(AllocateNode::ALength, count_val);
989-
set_req(AllocateNode::ValidLengthTest, valid_length_test);
990989
}
991990
virtualintOpcode()const;
991+
virtual Node *Ideal(PhaseGVN *phase,bool can_reshape);
992992

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

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2729,17 +2729,6 @@ const Type* CatchNode::Value(PhaseGVN* phase) const {
27292729
// Rethrows always throw exceptions, never return
27302730
if (call->entry_point() ==OptoRuntime::rethrow_stub()) {
27312731
f[CatchProjNode::fall_through_index] = Type::TOP;
2732-
}elseif (call->is_AllocateArray()) {
2733-
Node* klass_node = call->in(AllocateNode::KlassNode);
2734-
Node* length = call->in(AllocateNode::ALength);
2735-
const Type* length_type = phase->type(length);
2736-
const Type* klass_type = phase->type(klass_node);
2737-
Node* valid_length_test = call->in(AllocateNode::ValidLengthTest);
2738-
const Type*valid_length_test_t = phase->type(valid_length_test);
2739-
if (length_type == Type::TOP || klass_type == Type::TOP ||valid_length_test_t == Type::TOP ||
2740-
valid_length_test_t->is_int()->is_con(0)) {
2741-
f[CatchProjNode::fall_through_index] = Type::TOP;
2742-
}
27432732
}elseif( call->req() > TypeFunc::Parms ) {
27442733
const Type *arg0 = phase->type( call->in(TypeFunc::Parms) );
27452734
// 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
@@ -3885,7 +3885,7 @@ bool Compile::final_graph_reshaping() {
38853885
// 'fall-thru' path, so expected kids is 1 less.
38863886
if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) {
38873887
if (n->in(0)->in(0)->is_Call()) {
3888-
CallNode*call = n->in(0)->in(0)->as_Call();
3888+
CallNode *call = n->in(0)->in(0)->as_Call();
38893889
if (call->entry_point() ==OptoRuntime::rethrow_stub()) {
38903890
required_outcnt--;// Rethrow always has 1 less kid
38913891
}elseif (call->req() > TypeFunc::Parms &&
@@ -3894,25 +3894,22 @@ bool Compile::final_graph_reshaping() {
38943894
// detected that the virtual call will always result in a null
38953895
// pointer exception. The fall-through projection of this CatchNode
38963896
// will not be populated.
3897-
Node*arg0 = call->in(TypeFunc::Parms);
3897+
Node *arg0 = call->in(TypeFunc::Parms);
38983898
if (arg0->is_Type() &&
38993899
arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) {
39003900
required_outcnt--;
39013901
}
3902-
}elseif (call->entry_point() ==OptoRuntime::new_array_Java() ||
3903-
call->entry_point() ==OptoRuntime::new_array_nozero_Java()) {
3904-
// Check for illegal array length. In such case, the optimizer has
3902+
}elseif (call->entry_point() ==OptoRuntime::new_array_Java() &&
3903+
call->req() > TypeFunc::Parms+1 &&
3904+
call->is_CallStaticJava()) {
3905+
// Check for negative array length. In such case, the optimizer has
39053906
// detected that the allocation attempt will always result in an
39063907
// exception. There is no fall-through projection of this CatchNode .
3907-
assert(call->is_CallStaticJava(),"static call expected");
3908-
assert(call->req() == call->jvms()->endoff() +1,"missing extra input");
3909-
Node* valid_length_test = call->in(call->req()-1);
3910-
call->del_req(call->req()-1);
3911-
if (valid_length_test->find_int_con(1) ==0) {
3908+
Node *arg1 = call->in(TypeFunc::Parms+1);
3909+
if (arg1->is_Type() &&
3910+
arg1->as_Type()->type()->join(TypeInt::POS)->empty()) {
39123911
required_outcnt--;
39133912
}
3914-
assert(n->outcnt() == required_outcnt,"malformed control flow");
3915-
continue;
39163913
}
39173914
}
39183915
}
@@ -3921,14 +3918,6 @@ bool Compile::final_graph_reshaping() {
39213918
record_method_not_compilable("malformed control flow");
39223919
returntrue;// Not all targets reachable!
39233920
}
3924-
}elseif (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) {
3925-
CallNode* call = n->in(0)->in(0)->as_Call();
3926-
if (call->entry_point() ==OptoRuntime::new_array_Java() ||
3927-
call->entry_point() ==OptoRuntime::new_array_nozero_Java()) {
3928-
assert(call->is_CallStaticJava(),"static call expected");
3929-
assert(call->req() == call->jvms()->endoff() +1,"missing extra input");
3930-
call->del_req(call->req()-1);// valid length test useless now
3931-
}
39323921
}
39333922
// Check that I actually visited all kids. Unreached kids
39343923
// must be infinite loops.

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2600,9 +2600,7 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep
26002600
// Make a catch node with just two handlers: fall-through and catch-all
26012601
Node* i_o = _gvn.transform(newProjNode(call, TypeFunc::I_O, separate_io_proj) );
26022602
Node* catc = _gvn.transform(newCatchNode(control(), i_o,2) );
2603-
Node* norm =newCatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci);
2604-
_gvn.set_type_bottom(norm);
2605-
C->record_for_igvn(norm);
2603+
Node* norm = _gvn.transform(newCatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) );
26062604
Node* excp = _gvn.transform(newCatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci) );
26072605

26082606
{ PreserveJVMStatepjvms(this);
@@ -3853,28 +3851,20 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
38533851
initial_slow_test = initial_slow_test->as_Bool()->as_int_value(&_gvn);
38543852
}
38553853

3856-
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
3857-
Node* valid_length_test = _gvn.intcon(1);
3858-
if (ary_type->isa_aryptr()) {
3859-
BasicType bt = ary_type->isa_aryptr()->elem()->array_element_basic_type();
3860-
jint max =TypeAryPtr::max_array_length(bt);
3861-
Node* valid_length_cmp = _gvn.transform(newCmpUNode(length,intcon(max)));
3862-
valid_length_test = _gvn.transform(newBoolNode(valid_length_cmp, BoolTest::le));
3863-
}
3864-
38653854
// Create the AllocateArrayNode and its result projections
38663855
AllocateArrayNode* alloc
38673856
=newAllocateArrayNode(C,AllocateArrayNode::alloc_type(TypeInt::INT),
38683857
control(), mem,i_o(),
38693858
size, klass_node,
38703859
initial_slow_test,
3871-
length, valid_length_test);
3860+
length);
38723861

38733862
// Cast to correct type. Note that the klass_node may be constant or not,
38743863
// and in the latter case the actual array type will be inexact also.
38753864
// (This happens via a non-constant argument to inline_native_newArray.)
38763865
// In any case, the value of klass_node provides the desired array type.
38773866
const TypeInt* length_type = _gvn.find_int_type(length);
3867+
const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();
38783868
if (ary_type->isa_aryptr() && length_type !=NULL) {
38793869
// Try to get a better type than POS for the size
38803870
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
@@ -1209,8 +1209,7 @@ void PhaseMacroExpand::expand_allocate_common(
12091209
AllocateNode* alloc,// allocation node to be expanded
12101210
Node* length,// array length for an array allocation
12111211
const TypeFunc* slow_call_type,// Type of slow call
1212-
address slow_call_address,// Address of slow call
1213-
Node* valid_length_test// whether length is valid or not
1212+
address slow_call_address// Address of slow call
12141213
)
12151214
{
12161215
Node* ctrl = alloc->in(TypeFunc::Control);
@@ -1395,12 +1394,6 @@ void PhaseMacroExpand::expand_allocate_common(
13951394
// Copy debug information and adjust JVMState information, then replace
13961395
// allocate node with the call
13971396
call->copy_call_debug_info(&_igvn, alloc);
1398-
// For array allocations, copy the valid length check to the call node so Compile::final_graph_reshaping() can verify
1399-
// that the call has the expected number of CatchProj nodes (in case the allocation always fails and the fallthrough
1400-
// path dies).
1401-
if (valid_length_test !=NULL) {
1402-
call->add_req(valid_length_test);
1403-
}
14041397
if (expand_fast_path) {
14051398
call->set_cnt(PROB_UNLIKELY_MAG(4));// Same effect as RC_UNCOMMON.
14061399
}else {
@@ -1887,12 +1880,11 @@ Node* PhaseMacroExpand::prefetch_allocation(Node* i_o, Node*& needgc_false,
18871880
voidPhaseMacroExpand::expand_allocate(AllocateNode *alloc) {
18881881
expand_allocate_common(alloc,NULL,
18891882
OptoRuntime::new_instance_Type(),
1890-
OptoRuntime::new_instance_Java(),NULL);
1883+
OptoRuntime::new_instance_Java());
18911884
}
18921885

18931886
voidPhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
18941887
Node* length = alloc->in(AllocateNode::ALength);
1895-
Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest);
18961888
InitializeNode* init = alloc->initialization();
18971889
Node* klass_node = alloc->in(AllocateNode::KlassNode);
18981890
const TypeAryKlassPtr*ary_klass_t = _igvn.type(klass_node)->isa_aryklassptr();
@@ -1907,7 +1899,7 @@ void PhaseMacroExpand::expand_allocate_array(AllocateArrayNode *alloc) {
19071899
}
19081900
expand_allocate_common(alloc, length,
19091901
OptoRuntime::new_array_Type(),
1910-
slow_call_address, valid_length_test);
1902+
slow_call_address);
19111903
}
19121904

19131905
//-------------------mark_eliminated_box----------------------------------

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ class PhaseMacroExpand : public Phase {
9292
voidexpand_allocate_common(AllocateNode* alloc,
9393
Node* length,
9494
const TypeFunc* slow_call_type,
95-
address slow_call_address,
96-
Node* valid_length_test);
95+
address slow_call_address);
96+
voidyank_initalize_node(InitializeNode* node);
9797
voidyank_alloc_node(AllocateNode* alloc);
9898
Node *value_from_mem(Node *mem, Node *ctl, BasicType ft,const Type *ftype,const TypeOopPtr *adr_t, AllocateNode *alloc);
9999
Node *value_from_mem_phi(Node *mem, BasicType ft,const Type *ftype,const TypeOopPtr *adr_t, AllocateNode *alloc, Node_Stack *value_phis,int level);

‎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