diff --git a/src/share/vm/opto/lcm.cpp b/src/share/vm/opto/lcm.cpp index d7aa2535710eae6c6c966b5718cc1365269ca1db..e46bf07fbab0fdcf74c607d306edd80ffebd6cea 100644 --- a/src/share/vm/opto/lcm.cpp +++ b/src/share/vm/opto/lcm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -815,6 +815,13 @@ bool PhaseCFG::schedule_local(Block* block, GrowableArray& ready_cnt, Vecto // and the edge will be lost. This is why this code should be // executed only when Precedent (== TypeFunc::Parms) edge is present. Node *x = n->in(TypeFunc::Parms); + if (x != NULL && get_block_for_node(x) == block && n->find_prec_edge(x) != -1) { + // Old edge to node within same block will get removed, but no precedence + // edge will get added because it already exists. Update ready count. + int cnt = ready_cnt.at(n->_idx); + assert(cnt > 1, err_msg("MemBar node %d must not get ready here", n->_idx)); + ready_cnt.at_put(n->_idx, cnt-1); + } n->del_req(TypeFunc::Parms); n->add_prec(x); } diff --git a/src/share/vm/opto/node.cpp b/src/share/vm/opto/node.cpp index 76c1611c71043d89365380b2a059f5d9bf969214..22b41e33a5ac7ed3143db0d90430bc2887d44881 100644 --- a/src/share/vm/opto/node.cpp +++ b/src/share/vm/opto/node.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -818,8 +818,9 @@ void Node::del_req( uint idx ) { // First remove corresponding def-use edge Node *n = in(idx); if (n != NULL) n->del_out((Node *)this); - _in[idx] = in(--_cnt); // Compact the array - _in[_cnt] = NULL; // NULL out emptied slot + _in[idx] = in(--_cnt); // Compact the array + // Avoid spec violation: Gap in prec edges. + close_prec_gap_at(_cnt); } //------------------------------del_req_ordered-------------------------------- @@ -831,10 +832,11 @@ void Node::del_req_ordered( uint idx ) { // First remove corresponding def-use edge Node *n = in(idx); if (n != NULL) n->del_out((Node *)this); - if (idx < _cnt - 1) { // Not last edge ? - Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*))); + if (idx < --_cnt) { // Not last edge ? + Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx)*sizeof(Node*))); } - _in[--_cnt] = NULL; // NULL out emptied slot + // Avoid spec violation: Gap in prec edges. + close_prec_gap_at(_cnt); } //------------------------------ins_req---------------------------------------- @@ -865,10 +867,12 @@ int Node::replace_edge(Node* old, Node* neww) { uint nrep = 0; for (uint i = 0; i < len(); i++) { if (in(i) == old) { - if (i < req()) + if (i < req()) { set_req(i, neww); - else + } else { + assert(find_prec_edge(neww) == -1, err_msg("spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx)); set_prec(i, neww); + } nrep++; } } @@ -974,24 +978,27 @@ void Node::add_prec( Node *n ) { // Find a precedence edge to move uint i = _cnt; - while( in(i) != NULL ) i++; + while( in(i) != NULL ) { + if (in(i) == n) return; // Avoid spec violation: duplicated prec edge. + i++; + } _in[i] = n; // Stuff prec edge over NULL if ( n != NULL) n->add_out((Node *)this); // Add mirror edge + +#ifdef ASSERT + while ((++i)<_max) { assert(_in[i] == NULL, err_msg("spec violation: Gap in prec edges (node %d)", _idx)); } +#endif } //------------------------------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 ) { - - // Find end of precedence list to pack NULLs - uint i; - for( i=j; i<_max; i++ ) - if( !_in[i] ) // Find the NULL at end of prec edge list - break; - if (_in[j] != NULL) _in[j]->del_out((Node *)this); - _in[j] = _in[--i]; // Move last element over removed guy - _in[i] = NULL; // NULL out last element + assert(j < _max, err_msg("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); } //------------------------------size_of---------------------------------------- diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp index cba8fa89678ac65847cea8f67fc90ceea52aa9fa..dfc713ef0ef0ec71b7094d799143c656dd55445b 100644 --- a/src/share/vm/opto/node.hpp +++ b/src/share/vm/opto/node.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, 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 @@ -423,6 +423,16 @@ protected: } // Find first occurrence of n among my edges: int find_edge(Node* n); + int find_prec_edge(Node* n) { + for (uint i = req(); i < len(); i++) { + if (_in[i] == n) return i; + if (_in[i] == NULL) { + DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); ) + break; + } + } + return -1; + } int replace_edge(Node* old, Node* neww); int replace_edges_in_range(Node* old, Node* neww, int start, int end); // NULL out all inputs to eliminate incoming Def-Use edges. @@ -469,6 +479,19 @@ private: debug_only(_last_del = n; ++_del_tick); #endif } + // Close gap after removing edge. + void close_prec_gap_at(uint gap) { + assert(_cnt <= gap && gap < _max, "no valid prec edge"); + uint i = gap; + Node *last = NULL; + for (; i < _max-1; ++i) { + Node *next = _in[i+1]; + if (next == NULL) break; + last = next; + } + _in[gap] = last; // Move last slot to empty one. + _in[i] = NULL; // NULL out last slot. + } public: // Globally replace this node by a given new node, updating all uses. @@ -485,13 +508,23 @@ public: // Add or remove precedence edges void add_prec( Node *n ); void rm_prec( uint i ); + + // Note: prec(i) will not necessarily point to n if edge already exists. void set_prec( uint i, Node *n ) { - assert( is_not_dead(n), "can not use dead node"); - assert( i >= _cnt, "not a precedence edge"); + assert(i < _max, err_msg("oob: i=%d, _max=%d", i, _max)); + assert(is_not_dead(n), "can not use dead node"); + assert(i >= _cnt, "not a precedence edge"); + // Avoid spec violation: duplicated prec edge. + if (_in[i] == n) return; + if (n == NULL || find_prec_edge(n) != -1) { + rm_prec(i); + return; + } if (_in[i] != NULL) _in[i]->del_out((Node *)this); _in[i] = n; if (n != NULL) n->add_out((Node *)this); } + // Set this node's index, used by cisc_version to replace current node void set_idx(uint new_idx) { const node_idx_t* ref = &_idx;