-
Bug
-
Resolution: Fixed
-
P5
-
11, 16
-
b21
-
generic
-
generic
When I work on JDK-8254269, I realize that Node::disconnect_inputs may leave some precedences undeleted.
In Node::disconnect_inputs, the following loop is buggy if there're more than one non-null values in precedence section.
// Remove precedence edges if any exist
// Note: Safepoints may have precedence edges, even during parsing
if( (req() != len()) && (in(req()) != NULL) ) {
uint max = len();
for( uint i = 0; i < max; ++i ) {
if( in(i) == 0 ) continue;
if( in(i) == n ) ++edges_to_n;
set_prec(i, NULL);
}
}
set_prec(i, NULL) invokes rm_prec(i) under the hook. After deleting the _in[j], close_prec_gap_at(j) will fill it with the last non-null value or null when no found.
//------------------------------rm_prec----------------------------------------
// Remove a precedence input. Precedence inputs are unordered, with
// duplicates removed and NULLs packed down at the end.
void Node::rm_prec( uint j ) {
assert(j < _max, "oob: i=%d, _max=%d", j, _max);
assert(j >= _cnt, "not a precedence edge");
if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges.
_in[j]->del_out((Node *)this);
close_prec_gap_at(j);
}
It means that loop as follows may skip precedences!
for( uint i = 0; i < max; ++i ) {
set_prec(i, NULL);
}
It's fine because so far, only dead nodes invoke disconnect_inputs() .
it's also conservatively okay if a node have a fake precedence because it only affect instruction scheduling and code motion.
In Node::disconnect_inputs, the following loop is buggy if there're more than one non-null values in precedence section.
// Remove precedence edges if any exist
// Note: Safepoints may have precedence edges, even during parsing
if( (req() != len()) && (in(req()) != NULL) ) {
uint max = len();
for( uint i = 0; i < max; ++i ) {
if( in(i) == 0 ) continue;
if( in(i) == n ) ++edges_to_n;
set_prec(i, NULL);
}
}
set_prec(i, NULL) invokes rm_prec(i) under the hook. After deleting the _in[j], close_prec_gap_at(j) will fill it with the last non-null value or null when no found.
//------------------------------rm_prec----------------------------------------
// Remove a precedence input. Precedence inputs are unordered, with
// duplicates removed and NULLs packed down at the end.
void Node::rm_prec( uint j ) {
assert(j < _max, "oob: i=%d, _max=%d", j, _max);
assert(j >= _cnt, "not a precedence edge");
if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges.
_in[j]->del_out((Node *)this);
close_prec_gap_at(j);
}
It means that loop as follows may skip precedences!
for( uint i = 0; i < max; ++i ) {
set_prec(i, NULL);
}
It's fine because so far, only dead nodes invoke disconnect_inputs() .
it's also conservatively okay if a node have a fake precedence because it only affect instruction scheduling and code motion.