//------------------------------call_catch_cleanup----------------------------- // If we inserted any instructions between a Call and his CatchNode, // clone the instructions on all paths below the Catch. void PhaseCFG::call_catch_cleanup(Block* block) { // End of region to clone uint end = block->end_idx(); if( !block->get_node(end)->is_Catch() ) return; // Start of region to clone uint beg = end; while(!block->get_node(beg-1)->is_MachProj() || !block->get_node(beg-1)->in(0)->is_MachCall() ) { beg--; assert(beg > 0,"Catch cleanup walking beyond block boundary"); } // Range of inserted instructions is [beg, end) if( beg == end ) return; // Clone along all Catch output paths. Clone area between the 'beg' and // 'end' indices. for( uint i = 0; i < block->_num_succs; i++ ) { Block *sb = block->_succs[i]; // Clone the entire area; ignoring the edge fixup for now. for( uint j = end; j > beg; j-- ) { // It is safe here to clone a node with anti_dependence // since clones dominate on each path. Node *clone = block->get_node(j-1)->clone(); sb->insert_node(clone, 1); map_node_to_block(clone, sb); } } // Fixup edges. Check the def-use info per cloned Node for(uint i2 = beg; i2 < end; i2++ ) { uint n_clone_idx = i2-beg+1; // Index of clone of n in each successor block Node *n = block->get_node(i2); // Node that got cloned // Need DU safe iterator because of edge manipulation in calls. Unique_Node_List *out = new Unique_Node_List(Thread::current()->resource_area()); for (DUIterator_Fast j1max, j1 = n->fast_outs(j1max); j1 < j1max; j1++) { out->push(n->fast_out(j1)); } uint max = out->size(); for (uint j = 0; j < max; j++) {// For all users Node *use = out->pop(); Block *buse = get_block_for_node(use); if( use->is_Phi() ) { for( uint k = 1; k < use->req(); k++ ) if( use->in(k) == n ) { Block* b = get_block_for_node(buse->pred(k)); Node *fixup = catch_cleanup_find_cloned_def(b, n, block, n_clone_idx); use->set_req(k, fixup); } } else { if (block == buse) { catch_cleanup_intra_block(use, n, block, beg, n_clone_idx); } else { catch_cleanup_inter_block(use, buse, n, block, n_clone_idx); } } } // End for all users } // End of for all Nodes in cloned area // Remove the now-dead cloned ops for(uint i3 = beg; i3 < end; i3++ ) { block->get_node(beg)->disconnect_inputs(NULL, C); block->remove_node(beg); } // If the successor blocks have a CreateEx node, move it back to the top for(uint i4 = 0; i4 < block->_num_succs; i4++ ) { Block *sb = block->_succs[i4]; uint new_cnt = end - beg; // Remove any newly created, but dead, nodes. for( uint j = new_cnt; j > 0; j-- ) { Node *n = sb->get_node(j); if (n->outcnt() == 0 && (!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){ n->disconnect_inputs(NULL, C); sb->remove_node(j); new_cnt--; } } // If any newly created nodes remain, move the CreateEx node to the top if (new_cnt > 0) { Node *cex = sb->get_node(1+new_cnt); if( cex->is_Mach() && cex->as_Mach()->ideal_Opcode() == Op_CreateEx ) { sb->remove_node(1+new_cnt); sb->insert_node(cex, 1); } } } }
void set_map(Node* from, Node* to) { ideal_nodes.push(from); _node_map.map(from->_idx, to); }