Tue, 10 Mar 2020 10:46:35 +0100
8146612: C2: Precedence edges specification violated
Reviewed-by: kvn
1.1 --- a/src/share/vm/opto/lcm.cpp Tue May 05 18:39:57 2020 +0100 1.2 +++ b/src/share/vm/opto/lcm.cpp Tue Mar 10 10:46:35 2020 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -815,6 +815,13 @@ 1.11 // and the edge will be lost. This is why this code should be 1.12 // executed only when Precedent (== TypeFunc::Parms) edge is present. 1.13 Node *x = n->in(TypeFunc::Parms); 1.14 + if (x != NULL && get_block_for_node(x) == block && n->find_prec_edge(x) != -1) { 1.15 + // Old edge to node within same block will get removed, but no precedence 1.16 + // edge will get added because it already exists. Update ready count. 1.17 + int cnt = ready_cnt.at(n->_idx); 1.18 + assert(cnt > 1, err_msg("MemBar node %d must not get ready here", n->_idx)); 1.19 + ready_cnt.at_put(n->_idx, cnt-1); 1.20 + } 1.21 n->del_req(TypeFunc::Parms); 1.22 n->add_prec(x); 1.23 }
2.1 --- a/src/share/vm/opto/node.cpp Tue May 05 18:39:57 2020 +0100 2.2 +++ b/src/share/vm/opto/node.cpp Tue Mar 10 10:46:35 2020 +0100 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -818,8 +818,9 @@ 2.11 // First remove corresponding def-use edge 2.12 Node *n = in(idx); 2.13 if (n != NULL) n->del_out((Node *)this); 2.14 - _in[idx] = in(--_cnt); // Compact the array 2.15 - _in[_cnt] = NULL; // NULL out emptied slot 2.16 + _in[idx] = in(--_cnt); // Compact the array 2.17 + // Avoid spec violation: Gap in prec edges. 2.18 + close_prec_gap_at(_cnt); 2.19 } 2.20 2.21 //------------------------------del_req_ordered-------------------------------- 2.22 @@ -831,10 +832,11 @@ 2.23 // First remove corresponding def-use edge 2.24 Node *n = in(idx); 2.25 if (n != NULL) n->del_out((Node *)this); 2.26 - if (idx < _cnt - 1) { // Not last edge ? 2.27 - Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*))); 2.28 + if (idx < --_cnt) { // Not last edge ? 2.29 + Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx)*sizeof(Node*))); 2.30 } 2.31 - _in[--_cnt] = NULL; // NULL out emptied slot 2.32 + // Avoid spec violation: Gap in prec edges. 2.33 + close_prec_gap_at(_cnt); 2.34 } 2.35 2.36 //------------------------------ins_req---------------------------------------- 2.37 @@ -865,10 +867,12 @@ 2.38 uint nrep = 0; 2.39 for (uint i = 0; i < len(); i++) { 2.40 if (in(i) == old) { 2.41 - if (i < req()) 2.42 + if (i < req()) { 2.43 set_req(i, neww); 2.44 - else 2.45 + } else { 2.46 + assert(find_prec_edge(neww) == -1, err_msg("spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx)); 2.47 set_prec(i, neww); 2.48 + } 2.49 nrep++; 2.50 } 2.51 } 2.52 @@ -974,24 +978,27 @@ 2.53 2.54 // Find a precedence edge to move 2.55 uint i = _cnt; 2.56 - while( in(i) != NULL ) i++; 2.57 + while( in(i) != NULL ) { 2.58 + if (in(i) == n) return; // Avoid spec violation: duplicated prec edge. 2.59 + i++; 2.60 + } 2.61 _in[i] = n; // Stuff prec edge over NULL 2.62 if ( n != NULL) n->add_out((Node *)this); // Add mirror edge 2.63 + 2.64 +#ifdef ASSERT 2.65 + while ((++i)<_max) { assert(_in[i] == NULL, err_msg("spec violation: Gap in prec edges (node %d)", _idx)); } 2.66 +#endif 2.67 } 2.68 2.69 //------------------------------rm_prec---------------------------------------- 2.70 // Remove a precedence input. Precedence inputs are unordered, with 2.71 // duplicates removed and NULLs packed down at the end. 2.72 void Node::rm_prec( uint j ) { 2.73 - 2.74 - // Find end of precedence list to pack NULLs 2.75 - uint i; 2.76 - for( i=j; i<_max; i++ ) 2.77 - if( !_in[i] ) // Find the NULL at end of prec edge list 2.78 - break; 2.79 - if (_in[j] != NULL) _in[j]->del_out((Node *)this); 2.80 - _in[j] = _in[--i]; // Move last element over removed guy 2.81 - _in[i] = NULL; // NULL out last element 2.82 + assert(j < _max, err_msg("oob: i=%d, _max=%d", j, _max)); 2.83 + assert(j >= _cnt, "not a precedence edge"); 2.84 + if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges. 2.85 + _in[j]->del_out((Node *)this); 2.86 + close_prec_gap_at(j); 2.87 } 2.88 2.89 //------------------------------size_of----------------------------------------
3.1 --- a/src/share/vm/opto/node.hpp Tue May 05 18:39:57 2020 +0100 3.2 +++ b/src/share/vm/opto/node.hpp Tue Mar 10 10:46:35 2020 +0100 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -423,6 +423,16 @@ 3.11 } 3.12 // Find first occurrence of n among my edges: 3.13 int find_edge(Node* n); 3.14 + int find_prec_edge(Node* n) { 3.15 + for (uint i = req(); i < len(); i++) { 3.16 + if (_in[i] == n) return i; 3.17 + if (_in[i] == NULL) { 3.18 + DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); ) 3.19 + break; 3.20 + } 3.21 + } 3.22 + return -1; 3.23 + } 3.24 int replace_edge(Node* old, Node* neww); 3.25 int replace_edges_in_range(Node* old, Node* neww, int start, int end); 3.26 // NULL out all inputs to eliminate incoming Def-Use edges. 3.27 @@ -469,6 +479,19 @@ 3.28 debug_only(_last_del = n; ++_del_tick); 3.29 #endif 3.30 } 3.31 + // Close gap after removing edge. 3.32 + void close_prec_gap_at(uint gap) { 3.33 + assert(_cnt <= gap && gap < _max, "no valid prec edge"); 3.34 + uint i = gap; 3.35 + Node *last = NULL; 3.36 + for (; i < _max-1; ++i) { 3.37 + Node *next = _in[i+1]; 3.38 + if (next == NULL) break; 3.39 + last = next; 3.40 + } 3.41 + _in[gap] = last; // Move last slot to empty one. 3.42 + _in[i] = NULL; // NULL out last slot. 3.43 + } 3.44 3.45 public: 3.46 // Globally replace this node by a given new node, updating all uses. 3.47 @@ -485,13 +508,23 @@ 3.48 // Add or remove precedence edges 3.49 void add_prec( Node *n ); 3.50 void rm_prec( uint i ); 3.51 + 3.52 + // Note: prec(i) will not necessarily point to n if edge already exists. 3.53 void set_prec( uint i, Node *n ) { 3.54 - assert( is_not_dead(n), "can not use dead node"); 3.55 - assert( i >= _cnt, "not a precedence edge"); 3.56 + assert(i < _max, err_msg("oob: i=%d, _max=%d", i, _max)); 3.57 + assert(is_not_dead(n), "can not use dead node"); 3.58 + assert(i >= _cnt, "not a precedence edge"); 3.59 + // Avoid spec violation: duplicated prec edge. 3.60 + if (_in[i] == n) return; 3.61 + if (n == NULL || find_prec_edge(n) != -1) { 3.62 + rm_prec(i); 3.63 + return; 3.64 + } 3.65 if (_in[i] != NULL) _in[i]->del_out((Node *)this); 3.66 _in[i] = n; 3.67 if (n != NULL) n->add_out((Node *)this); 3.68 } 3.69 + 3.70 // Set this node's index, used by cisc_version to replace current node 3.71 void set_idx(uint new_idx) { 3.72 const node_idx_t* ref = &_idx;