提交 7939996d 编写于 作者: M mdoerr

8146612: C2: Precedence edges specification violated

Reviewed-by: kvn
上级 d8b2c553
/*
* 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<int>& 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);
}
......
/*
* 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----------------------------------------
......
/*
* 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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册