提交 d39e2dd4 编写于 作者: D dlong

7147464: Java crashed while executing method with over 8k of dneg operations

Summary: replace recursive method with iterative
Reviewed-by: kvn, twisti
Contributed-by: dean.long@oracle.com
上级 ff734311
...@@ -757,6 +757,7 @@ void PhaseGVN::dead_loop_check( Node *n ) { ...@@ -757,6 +757,7 @@ void PhaseGVN::dead_loop_check( Node *n ) {
//------------------------------PhaseIterGVN----------------------------------- //------------------------------PhaseIterGVN-----------------------------------
// Initialize hash table to fresh and clean for +VerifyOpto // Initialize hash table to fresh and clean for +VerifyOpto
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ), PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
_stack(C->unique() >> 1),
_delay_transform(false) { _delay_transform(false) {
} }
...@@ -764,6 +765,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(i ...@@ -764,6 +765,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(i
// Initialize with previous PhaseIterGVN info; used by PhaseCCP // Initialize with previous PhaseIterGVN info; used by PhaseCCP
PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
_worklist( igvn->_worklist ), _worklist( igvn->_worklist ),
_stack( igvn->_stack ),
_delay_transform(igvn->_delay_transform) _delay_transform(igvn->_delay_transform)
{ {
} }
...@@ -772,6 +774,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), ...@@ -772,6 +774,7 @@ PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
// Initialize with previous PhaseGVN info from Parser // Initialize with previous PhaseGVN info from Parser
PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
_worklist(*C->for_igvn()), _worklist(*C->for_igvn()),
_stack(C->unique() >> 1),
_delay_transform(false) _delay_transform(false)
{ {
uint max; uint max;
...@@ -1138,51 +1141,77 @@ const Type* PhaseIterGVN::saturate(const Type* new_type, const Type* old_type, ...@@ -1138,51 +1141,77 @@ const Type* PhaseIterGVN::saturate(const Type* new_type, const Type* old_type,
// Kill a globally dead Node. All uses are also globally dead and are // Kill a globally dead Node. All uses are also globally dead and are
// aggressively trimmed. // aggressively trimmed.
void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
assert(dead != C->root(), "killing root, eh?"); enum DeleteProgress {
if (dead->is_top()) return; PROCESS_INPUTS,
NOT_PRODUCT( set_progress(); ) PROCESS_OUTPUTS
// Remove from iterative worklist };
_worklist.remove(dead); assert(_stack.is_empty(), "not empty");
if (!dead->is_Con()) { // Don't kill cons but uses _stack.push(dead, PROCESS_INPUTS);
// Remove from hash table
_table.hash_delete( dead ); while (_stack.is_nonempty()) {
// Smash all inputs to 'dead', isolating him completely dead = _stack.node();
for( uint i = 0; i < dead->req(); i++ ) { uint progress_state = _stack.index();
Node *in = dead->in(i); assert(dead != C->root(), "killing root, eh?");
if( in ) { // Points to something? assert(!dead->is_top(), "add check for top when pushing");
dead->set_req(i,NULL); // Kill the edge NOT_PRODUCT( set_progress(); )
if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? if (progress_state == PROCESS_INPUTS) {
remove_dead_node(in); // Recursively remove // After following inputs, continue to outputs
} else if (in->outcnt() == 1 && _stack.set_index(PROCESS_OUTPUTS);
in->has_special_unique_user()) { // Remove from iterative worklist
_worklist.push(in->unique_out()); _worklist.remove(dead);
} else if (in->outcnt() <= 2 && dead->is_Phi()) { if (!dead->is_Con()) { // Don't kill cons but uses
if( in->Opcode() == Op_Region ) bool recurse = false;
_worklist.push(in); // Remove from hash table
else if( in->is_Store() ) { _table.hash_delete( dead );
DUIterator_Fast imax, i = in->fast_outs(imax); // Smash all inputs to 'dead', isolating him completely
_worklist.push(in->fast_out(i)); for( uint i = 0; i < dead->req(); i++ ) {
i++; Node *in = dead->in(i);
if(in->outcnt() == 2) { if( in ) { // Points to something?
_worklist.push(in->fast_out(i)); dead->set_req(i,NULL); // Kill the edge
i++; if (in->outcnt() == 0 && in != C->top()) {// Made input go dead?
_stack.push(in, PROCESS_INPUTS); // Recursively remove
recurse = true;
} else if (in->outcnt() == 1 &&
in->has_special_unique_user()) {
_worklist.push(in->unique_out());
} else if (in->outcnt() <= 2 && dead->is_Phi()) {
if( in->Opcode() == Op_Region )
_worklist.push(in);
else if( in->is_Store() ) {
DUIterator_Fast imax, i = in->fast_outs(imax);
_worklist.push(in->fast_out(i));
i++;
if(in->outcnt() == 2) {
_worklist.push(in->fast_out(i));
i++;
}
assert(!(i < imax), "sanity");
}
} }
assert(!(i < imax), "sanity");
} }
} }
if (dead->is_macro()) {
C->remove_macro_node(dead);
}
if (recurse) {
continue;
}
} }
} }
if (dead->is_macro()) { // Aggressively kill globally dead uses
C->remove_macro_node(dead); // (Rather than pushing all the outs at once, we push one at a time,
// plus the parent to resume later, because of the indefinite number
// of edge deletions per loop trip.)
if (dead->outcnt() > 0) {
// Recursively remove
_stack.push(dead->raw_out(0), PROCESS_INPUTS);
} else {
_stack.pop();
} }
} }
// Aggressively kill globally dead uses
// (Cannot use DUIterator_Last because of the indefinite number
// of edge deletions per loop trip.)
while (dead->outcnt() > 0) {
remove_globally_dead_node(dead->raw_out(0));
}
} }
//------------------------------subsume_node----------------------------------- //------------------------------subsume_node-----------------------------------
......
...@@ -403,6 +403,8 @@ class PhaseIterGVN : public PhaseGVN { ...@@ -403,6 +403,8 @@ class PhaseIterGVN : public PhaseGVN {
// Subsume users of node 'old' into node 'nn' // Subsume users of node 'old' into node 'nn'
void subsume_node( Node *old, Node *nn ); void subsume_node( Node *old, Node *nn );
Node_Stack _stack; // Stack used to avoid recursion
protected: protected:
// Idealize new Node 'n' with respect to its inputs and its value // Idealize new Node 'n' with respect to its inputs and its value
...@@ -438,8 +440,8 @@ public: ...@@ -438,8 +440,8 @@ public:
// It is significant only for debugging and profiling. // It is significant only for debugging and profiling.
Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL); Node* register_new_node_with_optimizer(Node* n, Node* orig = NULL);
// Kill a globally dead Node. It is allowed to have uses which are // Kill a globally dead Node. All uses are also globally dead and are
// assumed dead and left 'in limbo'. // aggressively trimmed.
void remove_globally_dead_node( Node *dead ); void remove_globally_dead_node( Node *dead );
// Kill all inputs to a dead node, recursively making more dead nodes. // Kill all inputs to a dead node, recursively making more dead nodes.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册