8194992: Null pointer dereference in MultiNode::proj_out related to loopexit()
Reviewed-by: kvn, thartmann
--- a/src/hotspot/share/opto/loopTransform.cpp Thu Jan 18 16:20:16 2018 +0000
+++ b/src/hotspot/share/opto/loopTransform.cpp Thu Jan 18 10:05:32 2018 -0800
@@ -1017,7 +1017,6 @@
CountedLoopNode *main_head = loop->_head->as_CountedLoop();
assert( main_head->is_normal_loop(), "" );
CountedLoopEndNode *main_end = main_head->loopexit();
- guarantee(main_end != NULL, "no loop exit node");
assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
Node *pre_header= main_head->in(LoopNode::EntryControl);
@@ -1243,7 +1242,6 @@
// Find common pieces of the loop being guarded with pre & post loops
CountedLoopNode *main_head = loop->_head->as_CountedLoop();
CountedLoopEndNode *main_end = main_head->loopexit();
- guarantee(main_end != NULL, "no loop exit node");
// diagnostic to show loop end is not properly formed
assert(main_end->outcnt() == 2, "1 true, 1 false path only");
@@ -1293,7 +1291,6 @@
// Find common pieces of the loop being guarded with pre & post loops
CountedLoopNode *main_head = loop->_head->as_CountedLoop();
CountedLoopEndNode *main_end = main_head->loopexit();
- guarantee(main_end != NULL, "no loop exit node");
// diagnostic to show loop end is not properly formed
assert(main_end->outcnt() == 2, "1 true, 1 false path only");
@@ -1427,7 +1424,6 @@
assert(LoopUnrollLimit, "");
CountedLoopNode *loop_head = loop->_head->as_CountedLoop();
CountedLoopEndNode *loop_end = loop_head->loopexit();
- assert(loop_end, "");
#ifndef PRODUCT
if (PrintOpto && VerifyLoopOptimizations) {
tty->print("Unrolling ");
@@ -2972,7 +2968,7 @@
}
store = n;
store_value = value;
- } else if (n->is_If() && n != head->loopexit()) {
+ } else if (n->is_If() && n != head->loopexit_or_null()) {
msg = "extra control flow";
msg_node = n;
}
@@ -3114,7 +3110,6 @@
ok.set(store->in(MemNode::Memory)->_idx);
CountedLoopEndNode* loop_exit = head->loopexit();
- guarantee(loop_exit != NULL, "no loop exit node");
// Loop structure is ok
ok.set(head->_idx);
--- a/src/hotspot/share/opto/loopnode.cpp Thu Jan 18 16:20:16 2018 +0000
+++ b/src/hotspot/share/opto/loopnode.cpp Thu Jan 18 10:05:32 2018 -0800
@@ -68,7 +68,7 @@
bool LoopNode::is_valid_counted_loop() const {
if (is_CountedLoop()) {
CountedLoopNode* l = as_CountedLoop();
- CountedLoopEndNode* le = l->loopexit();
+ CountedLoopEndNode* le = l->loopexit_or_null();
if (le != NULL &&
le->proj_out_or_null(1 /* true */) == l->in(LoopNode::LoopBackControl)) {
Node* phi = l->phi();
@@ -793,7 +793,7 @@
#ifdef ASSERT
assert(l->is_valid_counted_loop(), "counted loop shape is messed up");
- assert(l == loop->_head && l->phi() == phi && l->loopexit() == lex, "" );
+ assert(l == loop->_head && l->phi() == phi && l->loopexit_or_null() == lex, "" );
#endif
#ifndef PRODUCT
if (TraceLoopOpts) {
@@ -917,7 +917,7 @@
}
}
CountedLoopEndNode* cle = inner_out->in(0)->as_CountedLoopEnd();
- assert(cle == inner->loopexit(), "mismatch");
+ assert(cle == inner->loopexit_or_null(), "mismatch");
bool has_skeleton = outer_le->in(1)->bottom_type()->singleton() && outer_le->in(1)->bottom_type()->is_int()->get_con() == 0;
if (has_skeleton) {
assert(expect_skeleton == 1 || expect_skeleton == -1, "unexpected skeleton node");
--- a/src/hotspot/share/opto/loopnode.hpp Thu Jan 18 16:20:16 2018 +0000
+++ b/src/hotspot/share/opto/loopnode.hpp Thu Jan 18 10:05:32 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -215,6 +215,7 @@
Node *init_control() const { return in(EntryControl); }
Node *back_control() const { return in(LoopBackControl); }
+ CountedLoopEndNode *loopexit_or_null() const;
CountedLoopEndNode *loopexit() const;
Node *init_trip() const;
Node *stride() const;
@@ -342,7 +343,7 @@
return NULL;
}
Node *ln = iv_phi->in(0);
- if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
+ if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit_or_null() == this) {
return (CountedLoopNode*)ln;
}
return NULL;
@@ -354,7 +355,7 @@
};
-inline CountedLoopEndNode *CountedLoopNode::loopexit() const {
+inline CountedLoopEndNode *CountedLoopNode::loopexit_or_null() const {
Node *bc = back_control();
if( bc == NULL ) return NULL;
Node *le = bc->in(0);
@@ -362,13 +363,18 @@
return NULL;
return (CountedLoopEndNode*)le;
}
-inline Node *CountedLoopNode::init_trip() const { return loopexit() ? loopexit()->init_trip() : NULL; }
-inline Node *CountedLoopNode::stride() const { return loopexit() ? loopexit()->stride() : NULL; }
-inline int CountedLoopNode::stride_con() const { return loopexit() ? loopexit()->stride_con() : 0; }
-inline bool CountedLoopNode::stride_is_con() const { return loopexit() && loopexit()->stride_is_con(); }
-inline Node *CountedLoopNode::limit() const { return loopexit() ? loopexit()->limit() : NULL; }
-inline Node *CountedLoopNode::incr() const { return loopexit() ? loopexit()->incr() : NULL; }
-inline Node *CountedLoopNode::phi() const { return loopexit() ? loopexit()->phi() : NULL; }
+inline CountedLoopEndNode *CountedLoopNode::loopexit() const {
+ CountedLoopEndNode* cle = loopexit_or_null();
+ assert(cle != NULL, "loopexit is NULL");
+ return cle;
+}
+inline Node *CountedLoopNode::init_trip() const { return loopexit_or_null() ? loopexit()->init_trip() : NULL; }
+inline Node *CountedLoopNode::stride() const { return loopexit_or_null() ? loopexit()->stride() : NULL; }
+inline int CountedLoopNode::stride_con() const { return loopexit_or_null() ? loopexit()->stride_con() : 0; }
+inline bool CountedLoopNode::stride_is_con() const { return loopexit_or_null() && loopexit()->stride_is_con(); }
+inline Node *CountedLoopNode::limit() const { return loopexit_or_null() ? loopexit()->limit() : NULL; }
+inline Node *CountedLoopNode::incr() const { return loopexit_or_null() ? loopexit()->incr() : NULL; }
+inline Node *CountedLoopNode::phi() const { return loopexit_or_null() ? loopexit()->phi() : NULL; }
//------------------------------LoopLimitNode-----------------------------
// Counted Loop limit node which represents exact final iterator value:
--- a/src/hotspot/share/opto/loopopts.cpp Thu Jan 18 16:20:16 2018 +0000
+++ b/src/hotspot/share/opto/loopopts.cpp Thu Jan 18 10:05:32 2018 -0800
@@ -1731,7 +1731,7 @@
Node* sfpt = cl->outer_safepoint();
CountedLoopEndNode* cle = cl->loopexit();
CountedLoopNode* new_cl = old_new[cl->_idx]->as_CountedLoop();
- CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit();
+ CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit_or_null();
Node* cle_out = cle->proj_out(false);
Node* new_sfpt = NULL;
--- a/src/hotspot/share/opto/superword.cpp Thu Jan 18 16:20:16 2018 +0000
+++ b/src/hotspot/share/opto/superword.cpp Thu Jan 18 10:05:32 2018 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -190,7 +190,7 @@
int *ignored_loop_nodes = NEW_RESOURCE_ARRAY(int, ignored_size);
Node_Stack nstack((int)ignored_size);
CountedLoopNode *cl = lpt()->_head->as_CountedLoop();
- Node *cl_exit = cl->loopexit();
+ Node *cl_exit = cl->loopexit_or_null();
int rpo_idx = _post_block.length();
assert(rpo_idx == 0, "post loop block is empty");