+{"files":[{"patch":"@@ -1659,1 +1659,0 @@\n- init_req( ValidLengthTest , topnode);\n@@ -1686,0 +1685,48 @@\n+\/\/=============================================================================\n+Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {\n+ if (remove_dead_region(phase, can_reshape)) return this;\n+ \/\/ Don't bother trying to transform a dead node\n+ if (in(0) && in(0)->is_top()) return NULL;\n+\n+ const Type* type = phase->type(Ideal_length());\n+ if (type->isa_int() && type->is_int()->_hi < 0) {\n+ if (can_reshape) {\n+ PhaseIterGVN *igvn = phase->is_IterGVN();\n+ \/\/ Unreachable fall through path (negative array length),\n+ \/\/ the allocation can only throw so disconnect it.\n+ Node* proj = proj_out_or_null(TypeFunc::Control);\n+ Node* catchproj = NULL;\n+ if (proj != NULL) {\n+ for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) {\n+ Node *cn = proj->fast_out(i);\n+ if (cn->is_Catch()) {\n+ catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index);\n+ break;\n+ }\n+ }\n+ }\n+ if (catchproj != NULL && catchproj->outcnt() > 0 &&\n+ (catchproj->outcnt() > 1 ||\n+ catchproj->unique_out()->Opcode() != Op_Halt)) {\n+ assert(catchproj->is_CatchProj(), \"must be a CatchProjNode\");\n+ Node* nproj = catchproj->clone();\n+ igvn->register_new_node_with_optimizer(nproj);\n+\n+ Node *frame = new ParmNode( phase->C->start(), TypeFunc::FramePtr );\n+ frame = phase->transform(frame);\n+ \/\/ Halt & Catch Fire\n+ Node* halt = new HaltNode(nproj, frame, \"unexpected negative array length\");\n+ phase->C->root()->add_req(halt);\n+ phase->transform(halt);\n+\n+ igvn->replace_node(catchproj, phase->C->top());\n+ return this;\n+ }\n+ } else {\n+ \/\/ Can't correct it during regular GVN so register for IGVN\n+ phase->C->record_for_igvn(this);\n+ }\n+ }\n+ return NULL;\n+}\n+\n","filename":"src\/hotspot\/share\/opto\/callnode.cpp","additions":48,"deletions":1,"binary":false,"changes":49,"status":"modified"},{"patch":"@@ -916,1 +916,0 @@\n- ValidLengthTest,\n@@ -926,1 +925,0 @@\n- fields[ValidLengthTest] = TypeInt::BOOL;\n@@ -1021,2 +1019,4 @@\n- AllocateArrayNode(Compile* C, const TypeFunc* atype, Node* ctrl, Node* mem, Node* abio, Node* size, Node* klass_node,\n- Node* initial_test, Node* count_val, Node* valid_length_test)\n+ AllocateArrayNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,\n+ Node* size, Node* klass_node, Node* initial_test,\n+ Node* count_val\n+ )\n@@ -1028,1 +1028,0 @@\n- set_req(AllocateNode::ValidLengthTest, valid_length_test);\n@@ -1031,0 +1030,1 @@\n+ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);\n","filename":"src\/hotspot\/share\/opto\/callnode.hpp","additions":5,"deletions":5,"binary":false,"changes":10,"status":"modified"},{"patch":"@@ -2690,14 +2690,0 @@\n- } else if (call->is_AllocateArray()) {\n- Node* klass_node = call->in(AllocateNode::KlassNode);\n- Node *length = call->in(AllocateNode::ALength);\n- const Type* length_type = phase->type(length);\n- const Type* klass_type = phase->type(klass_node);\n- if (length_type == Type::TOP || klass_type == Type::TOP) {\n- f[CatchProjNode::fall_through_index] = Type::TOP;\n- } else {\n- Node* valid_length_test = call->in(AllocateNode::ValidLengthTest);\n- const Type* valid_length_test_t = phase->type(valid_length_test);\n- if (valid_length_test_t->isa_int() && valid_length_test_t->is_int()->is_con(0)) {\n- f[CatchProjNode::fall_through_index] = Type::TOP;\n- }\n- }\n","filename":"src\/hotspot\/share\/opto\/cfgnode.cpp","additions":0,"deletions":14,"binary":false,"changes":14,"status":"modified"},{"patch":"@@ -3745,1 +3745,1 @@\n- CallNode* call = n->in(0)->in(0)->as_Call();\n+ CallNode *call = n->in(0)->in(0)->as_Call();\n@@ -3754,1 +3754,1 @@\n- Node* arg0 = call->in(TypeFunc::Parms);\n+ Node *arg0 = call->in(TypeFunc::Parms);\n@@ -3759,2 +3759,3 @@\n- } else if (call->entry_point() == OptoRuntime::new_array_Java() ||\n- call->entry_point() == OptoRuntime::new_array_nozero_Java()) {\n+ } else if (call->entry_point() == OptoRuntime::new_array_Java() &&\n+ call->req() > TypeFunc::Parms+1 &&\n+ call->is_CallStaticJava()) {\n@@ -3764,5 +3765,3 @@\n- assert(call->is_CallStaticJava(), \"static call expected\");\n- assert(call->len() > call->req() && call->in(call->req()) != NULL, \"no precendent edge\");\n- Node* valid_length_test = call->in(call->req());\n- call->rm_prec(call->req());\n- if (valid_length_test->find_int_con(1) == 0) {\n+ Node *arg1 = call->in(TypeFunc::Parms+1);\n+ if (arg1->is_Type() &&\n+ arg1->as_Type()->type()->join(TypeInt::POS)->empty()) {\n@@ -3771,2 +3770,0 @@\n- assert(n->outcnt() == required_outcnt, \"malformed control flow\");\n- continue;\n@@ -3781,7 +3778,0 @@\n- } else if (n->is_PCTable() && n->in(0) && n->in(0)->in(0) && n->in(0)->in(0)->is_Call()) {\n- CallNode* call = n->in(0)->in(0)->as_Call();\n- if (call->entry_point() == OptoRuntime::new_array_Java() ||\n- call->entry_point() == OptoRuntime::new_array_nozero_Java()) {\n- assert(call->len() > call->req() && call->in(call->req()) != NULL, \"precedent edge expected\");\n- call->rm_prec(call->req());\n- }\n","filename":"src\/hotspot\/share\/opto\/compile.cpp","additions":8,"deletions":18,"binary":false,"changes":26,"status":"modified"},{"patch":"@@ -2741,3 +2741,1 @@\n- Node* norm = new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci);\n- _gvn.set_type_bottom(norm);\n- C->record_for_igvn(norm);\n+ Node* norm = _gvn.transform( new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci) );\n@@ -3984,9 +3982,0 @@\n- const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();\n- Node* valid_length_test = C->top();\n- if (ary_type->klass()->is_array_klass()) {\n- BasicType bt = ary_type->klass()->as_array_klass()->element_type()->basic_type();\n- jint max = TypeAryPtr::max_array_length(bt);\n- Node* valid_length_cmp = _gvn.transform(new CmpUNode(length, intcon(max)));\n- valid_length_test = _gvn.transform(new BoolNode(valid_length_cmp, BoolTest::le));\n- }\n-\n@@ -3999,1 +3988,1 @@\n- length, valid_length_test);\n+ length);\n@@ -4006,0 +3995,1 @@\n+ const TypeOopPtr* ary_type = _gvn.type(klass_node)->is_klassptr()->as_instance_type();\n","filename":"src\/hotspot\/share\/opto\/graphKit.cpp","additions":3,"deletions":13,"binary":false,"changes":16,"status":"modified"},{"patch":"@@ -1211,2 +1211,1 @@\n- address slow_call_address, \/\/ Address of slow call\n- Node* valid_length_test \/\/ whether length is valid or not\n+ address slow_call_address \/\/ Address of slow call\n@@ -1397,3 +1396,0 @@\n- if (valid_length_test != NULL) {\n- call->add_prec(valid_length_test);\n- }\n@@ -1882,1 +1878,1 @@\n- OptoRuntime::new_instance_Java(), NULL);\n+ OptoRuntime::new_instance_Java());\n@@ -1887,1 +1883,0 @@\n- Node* valid_length_test = alloc->in(AllocateNode::ValidLengthTest);\n@@ -1902,1 +1897,1 @@\n- slow_call_address, valid_length_test);\n+ slow_call_address);\n","filename":"src\/hotspot\/share\/opto\/macro.cpp","additions":3,"deletions":8,"binary":false,"changes":11,"status":"modified"},{"patch":"@@ -95,2 +95,2 @@\n- address slow_call_address,\n- Node* valid_length_test);\n+ address slow_call_address);\n+ void yank_initalize_node(InitializeNode* node);\n","filename":"src\/hotspot\/share\/opto\/macro.hpp","additions":2,"deletions":2,"binary":false,"changes":4,"status":"modified"},{"patch":"@@ -131,2 +131,2 @@\n- assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1 || use->is_AllocateArray(), \"unexpected node type\");\n- Node *use_c = (use->is_If() || use->is_AllocateArray()) ? use->in(0) : get_ctrl(use);\n+ assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, \"unexpected node type\");\n+ Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use);\n@@ -169,3 +169,2 @@\n- assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1 || u->is_AllocateArray(), \"unexpected node type\");\n- assert(u->is_AllocateArray() || u->in(1) == bol, \"\");\n- assert(!u->is_AllocateArray() || u->in(AllocateNode::ValidLengthTest) == bol, \"wrong input to AllocateArray\");\n+ assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, \"unexpected node type\");\n+ assert(u->in(1) == bol, \"\");\n@@ -173,1 +172,1 @@\n- Node *u_ctrl = (u->is_If() || u->is_AllocateArray()) ? u->in(0) : get_ctrl(u);\n+ Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u);\n@@ -177,1 +176,1 @@\n- _igvn.replace_input_of(u, u->is_AllocateArray() ? AllocateNode::ValidLengthTest : 1, x);\n+ _igvn.replace_input_of(u, 1, x);\n","filename":"src\/hotspot\/share\/opto\/split_if.cpp","additions":6,"deletions":7,"binary":false,"changes":13,"status":"modified"},{"patch":"@@ -1,79 +0,0 @@\n-\/*\n- * Copyright (c) 2021, Red Hat, Inc. All rights reserved.\n- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n- *\n- * This code is free software; you can redistribute it and\/or modify it\n- * under the terms of the GNU General Public License version 2 only, as\n- * published by the Free Software Foundation.\n- *\n- * This code is distributed in the hope that it will be useful, but WITHOUT\n- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n- * version 2 for more details (a copy is included in the LICENSE file that\n- * accompanied this code).\n- *\n- * You should have received a copy of the GNU General Public License version\n- * 2 along with this work; if not, write to the Free Software Foundation,\n- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n- *\n- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n- * or visit www.oracle.com if you need additional information or have any\n- * questions.\n- *\/\n-\n-\/*\n- * @test\n- * bug 8278413\n- * @summary C2 crash when allocating array of size too large\n- * @library \/test\/lib \/\n- * @build sun.hotspot.WhiteBox\n- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox\n- * @run main\/othervm -ea -Xbootclasspath\/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestFailedAllocationBadGraph\n- *\/\n-\n-import sun.hotspot.WhiteBox;\n-import java.lang.reflect.Method;\n-import compiler.whitebox.CompilerWhiteBoxTest;\n-\n-public class TestFailedAllocationBadGraph {\n- private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();\n-\n- private static long[] array;\n- private static int field;\n- private static volatile int barrier;\n-\n- public static void main(String[] args) throws Exception {\n- run(\"test1\");\n- run(\"test2\");\n- }\n-\n- private static void run(String method) throws Exception {\n- Method m = TestFailedAllocationBadGraph.class.getDeclaredMethod(method);\n- WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);\n- if (!WHITE_BOX.isMethodCompiled(m) || WHITE_BOX.getMethodCompilationLevel(m) != CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION) {\n- throw new RuntimeException(\"should still be compiled\");\n- }\n- }\n-\n- private static int test1() {\n- int length = Integer.MAX_VALUE;\n- try {\n- array = new long[length];\n- } catch (OutOfMemoryError outOfMemoryError) {\n- barrier = 0x42;\n- length = field;\n- }\n- return length;\n- }\n-\n- private static int test2() {\n- int length = -1;\n- try {\n- array = new long[length];\n- } catch (OutOfMemoryError outOfMemoryError) {\n- barrier = 0x42;\n- length = field;\n- }\n- return length;\n- }\n-}\n","filename":"test\/hotspot\/jtreg\/compiler\/allocation\/TestFailedAllocationBadGraph.java","additions":0,"deletions":79,"binary":false,"changes":79,"status":"deleted"}]}
0 commit comments