comparison src/share/vm/opto/phaseX.cpp @ 6244:611e8a669a2c

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
author dlong
date Mon, 16 Jul 2012 15:31:18 -0400
parents 670a74b863fc
children e626685e9f6c
comparison
equal deleted inserted replaced
6217:e74da3c2b827 6244:611e8a669a2c
755 755
756 //============================================================================= 756 //=============================================================================
757 //------------------------------PhaseIterGVN----------------------------------- 757 //------------------------------PhaseIterGVN-----------------------------------
758 // Initialize hash table to fresh and clean for +VerifyOpto 758 // Initialize hash table to fresh and clean for +VerifyOpto
759 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ), 759 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ),
760 _stack(C->unique() >> 1),
760 _delay_transform(false) { 761 _delay_transform(false) {
761 } 762 }
762 763
763 //------------------------------PhaseIterGVN----------------------------------- 764 //------------------------------PhaseIterGVN-----------------------------------
764 // Initialize with previous PhaseIterGVN info; used by PhaseCCP 765 // Initialize with previous PhaseIterGVN info; used by PhaseCCP
765 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), 766 PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn),
766 _worklist( igvn->_worklist ), 767 _worklist( igvn->_worklist ),
768 _stack( igvn->_stack ),
767 _delay_transform(igvn->_delay_transform) 769 _delay_transform(igvn->_delay_transform)
768 { 770 {
769 } 771 }
770 772
771 //------------------------------PhaseIterGVN----------------------------------- 773 //------------------------------PhaseIterGVN-----------------------------------
772 // Initialize with previous PhaseGVN info from Parser 774 // Initialize with previous PhaseGVN info from Parser
773 PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), 775 PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn),
774 _worklist(*C->for_igvn()), 776 _worklist(*C->for_igvn()),
777 _stack(C->unique() >> 1),
775 _delay_transform(false) 778 _delay_transform(false)
776 { 779 {
777 uint max; 780 uint max;
778 781
779 // Dead nodes in the hash table inherited from GVN were not treated as 782 // Dead nodes in the hash table inherited from GVN were not treated as
1136 1139
1137 //------------------------------remove_globally_dead_node---------------------- 1140 //------------------------------remove_globally_dead_node----------------------
1138 // Kill a globally dead Node. All uses are also globally dead and are 1141 // Kill a globally dead Node. All uses are also globally dead and are
1139 // aggressively trimmed. 1142 // aggressively trimmed.
1140 void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { 1143 void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
1141 assert(dead != C->root(), "killing root, eh?"); 1144 enum DeleteProgress {
1142 if (dead->is_top()) return; 1145 PROCESS_INPUTS,
1143 NOT_PRODUCT( set_progress(); ) 1146 PROCESS_OUTPUTS
1144 // Remove from iterative worklist 1147 };
1145 _worklist.remove(dead); 1148 assert(_stack.is_empty(), "not empty");
1146 if (!dead->is_Con()) { // Don't kill cons but uses 1149 _stack.push(dead, PROCESS_INPUTS);
1147 // Remove from hash table 1150
1148 _table.hash_delete( dead ); 1151 while (_stack.is_nonempty()) {
1149 // Smash all inputs to 'dead', isolating him completely 1152 dead = _stack.node();
1150 for( uint i = 0; i < dead->req(); i++ ) { 1153 uint progress_state = _stack.index();
1151 Node *in = dead->in(i); 1154 assert(dead != C->root(), "killing root, eh?");
1152 if( in ) { // Points to something? 1155 assert(!dead->is_top(), "add check for top when pushing");
1153 dead->set_req(i,NULL); // Kill the edge 1156 NOT_PRODUCT( set_progress(); )
1154 if (in->outcnt() == 0 && in != C->top()) {// Made input go dead? 1157 if (progress_state == PROCESS_INPUTS) {
1155 remove_dead_node(in); // Recursively remove 1158 // After following inputs, continue to outputs
1156 } else if (in->outcnt() == 1 && 1159 _stack.set_index(PROCESS_OUTPUTS);
1157 in->has_special_unique_user()) { 1160 // Remove from iterative worklist
1158 _worklist.push(in->unique_out()); 1161 _worklist.remove(dead);
1159 } else if (in->outcnt() <= 2 && dead->is_Phi()) { 1162 if (!dead->is_Con()) { // Don't kill cons but uses
1160 if( in->Opcode() == Op_Region ) 1163 bool recurse = false;
1161 _worklist.push(in); 1164 // Remove from hash table
1162 else if( in->is_Store() ) { 1165 _table.hash_delete( dead );
1163 DUIterator_Fast imax, i = in->fast_outs(imax); 1166 // Smash all inputs to 'dead', isolating him completely
1164 _worklist.push(in->fast_out(i)); 1167 for( uint i = 0; i < dead->req(); i++ ) {
1165 i++; 1168 Node *in = dead->in(i);
1166 if(in->outcnt() == 2) { 1169 if( in ) { // Points to something?
1167 _worklist.push(in->fast_out(i)); 1170 dead->set_req(i,NULL); // Kill the edge
1168 i++; 1171 if (in->outcnt() == 0 && in != C->top()) {// Made input go dead?
1172 _stack.push(in, PROCESS_INPUTS); // Recursively remove
1173 recurse = true;
1174 } else if (in->outcnt() == 1 &&
1175 in->has_special_unique_user()) {
1176 _worklist.push(in->unique_out());
1177 } else if (in->outcnt() <= 2 && dead->is_Phi()) {
1178 if( in->Opcode() == Op_Region )
1179 _worklist.push(in);
1180 else if( in->is_Store() ) {
1181 DUIterator_Fast imax, i = in->fast_outs(imax);
1182 _worklist.push(in->fast_out(i));
1183 i++;
1184 if(in->outcnt() == 2) {
1185 _worklist.push(in->fast_out(i));
1186 i++;
1187 }
1188 assert(!(i < imax), "sanity");
1189 }
1169 } 1190 }
1170 assert(!(i < imax), "sanity");
1171 } 1191 }
1172 } 1192 }
1173 } 1193
1174 } 1194 if (dead->is_macro()) {
1175 1195 C->remove_macro_node(dead);
1176 if (dead->is_macro()) { 1196 }
1177 C->remove_macro_node(dead); 1197
1178 } 1198 if (recurse) {
1179 } 1199 continue;
1180 // Aggressively kill globally dead uses 1200 }
1181 // (Cannot use DUIterator_Last because of the indefinite number 1201 }
1182 // of edge deletions per loop trip.) 1202 }
1183 while (dead->outcnt() > 0) { 1203
1184 remove_globally_dead_node(dead->raw_out(0)); 1204 // Aggressively kill globally dead uses
1205 // (Rather than pushing all the outs at once, we push one at a time,
1206 // plus the parent to resume later, because of the indefinite number
1207 // of edge deletions per loop trip.)
1208 if (dead->outcnt() > 0) {
1209 // Recursively remove
1210 _stack.push(dead->raw_out(0), PROCESS_INPUTS);
1211 } else {
1212 _stack.pop();
1213 }
1185 } 1214 }
1186 } 1215 }
1187 1216
1188 //------------------------------subsume_node----------------------------------- 1217 //------------------------------subsume_node-----------------------------------
1189 // Remove users from node 'old' and add them to node 'nn'. 1218 // Remove users from node 'old' and add them to node 'nn'.