1.1 --- a/src/share/vm/opto/escape.cpp Sat Nov 06 18:52:07 2010 -0700 1.2 +++ b/src/share/vm/opto/escape.cpp Sat Nov 06 20:35:36 2010 -0700 1.3 @@ -85,6 +85,7 @@ 1.4 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 1.5 _processed(C->comp_arena()), 1.6 _collecting(true), 1.7 + _progress(false), 1.8 _compile(C), 1.9 _igvn(igvn), 1.10 _node_map(C->comp_arena()) { 1.11 @@ -113,7 +114,7 @@ 1.12 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); 1.13 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge"); 1.14 assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge"); 1.15 - f->add_edge(to_i, PointsToNode::PointsToEdge); 1.16 + add_edge(f, to_i, PointsToNode::PointsToEdge); 1.17 } 1.18 1.19 void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) { 1.20 @@ -126,7 +127,7 @@ 1.21 // don't add a self-referential edge, this can occur during removal of 1.22 // deferred edges 1.23 if (from_i != to_i) 1.24 - f->add_edge(to_i, PointsToNode::DeferredEdge); 1.25 + add_edge(f, to_i, PointsToNode::DeferredEdge); 1.26 } 1.27 1.28 int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) { 1.29 @@ -157,7 +158,7 @@ 1.30 assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets"); 1.31 t->set_offset(offset); 1.32 1.33 - f->add_edge(to_i, PointsToNode::FieldEdge); 1.34 + add_edge(f, to_i, PointsToNode::FieldEdge); 1.35 } 1.36 1.37 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) { 1.38 @@ -995,7 +996,7 @@ 1.39 GrowableArray<Node *> memnode_worklist; 1.40 GrowableArray<PhiNode *> orig_phis; 1.41 1.42 - PhaseGVN *igvn = _igvn; 1.43 + PhaseIterGVN *igvn = _igvn; 1.44 uint new_index_start = (uint) _compile->num_alias_types(); 1.45 Arena* arena = Thread::current()->resource_area(); 1.46 VectorSet visited(arena); 1.47 @@ -1531,14 +1532,9 @@ 1.48 has_allocations = true; 1.49 } 1.50 if(n->is_AddP()) { 1.51 - // Collect address nodes which directly reference an allocation. 1.52 - // Use them during stage 3 below to build initial connection graph 1.53 - // field edges. Other field edges could be added after StoreP/LoadP 1.54 - // nodes are processed during stage 4 below. 1.55 - Node* base = get_addp_base(n); 1.56 - if(base->is_Proj() && base->in(0)->is_Allocate()) { 1.57 - cg_worklist.append(n->_idx); 1.58 - } 1.59 + // Collect address nodes. Use them during stage 3 below 1.60 + // to build initial connection graph field edges. 1.61 + cg_worklist.append(n->_idx); 1.62 } else if (n->is_MergeMem()) { 1.63 // Collect all MergeMem nodes to add memory slices for 1.64 // scalar replaceable objects in split_unique_types(). 1.65 @@ -1562,18 +1558,28 @@ 1.66 build_connection_graph(n, igvn); 1.67 } 1.68 1.69 - // 3. Pass to create fields edges (Allocate -F-> AddP). 1.70 + // 3. Pass to create initial fields edges (JavaObject -F-> AddP) 1.71 + // to reduce number of iterations during stage 4 below. 1.72 uint cg_length = cg_worklist.length(); 1.73 for( uint next = 0; next < cg_length; ++next ) { 1.74 int ni = cg_worklist.at(next); 1.75 - build_connection_graph(ptnode_adr(ni)->_node, igvn); 1.76 + Node* n = ptnode_adr(ni)->_node; 1.77 + Node* base = get_addp_base(n); 1.78 + if (base->is_Proj()) 1.79 + base = base->in(0); 1.80 + PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type(); 1.81 + if (nt == PointsToNode::JavaObject) { 1.82 + build_connection_graph(n, igvn); 1.83 + } 1.84 } 1.85 1.86 cg_worklist.clear(); 1.87 cg_worklist.append(_phantom_object); 1.88 + GrowableArray<uint> worklist; 1.89 1.90 // 4. Build Connection Graph which need 1.91 // to walk the connection graph. 1.92 + _progress = false; 1.93 for (uint ni = 0; ni < nodes_size(); ni++) { 1.94 PointsToNode* ptn = ptnode_adr(ni); 1.95 Node *n = ptn->_node; 1.96 @@ -1581,13 +1587,52 @@ 1.97 build_connection_graph(n, igvn); 1.98 if (ptn->node_type() != PointsToNode::UnknownType) 1.99 cg_worklist.append(n->_idx); // Collect CG nodes 1.100 + if (!_processed.test(n->_idx)) 1.101 + worklist.append(n->_idx); // Collect C/A/L/S nodes 1.102 } 1.103 } 1.104 1.105 + // After IGVN user nodes may have smaller _idx than 1.106 + // their inputs so they will be processed first in 1.107 + // previous loop. Because of that not all Graph 1.108 + // edges will be created. Walk over interesting 1.109 + // nodes again until no new edges are created. 1.110 + // 1.111 + // Normally only 1-3 passes needed to build 1.112 + // Connection Graph depending on graph complexity. 1.113 + // Set limit to 10 to catch situation when something 1.114 + // did go wrong and recompile the method without EA. 1.115 + 1.116 +#define CG_BUILD_ITER_LIMIT 10 1.117 + 1.118 + uint length = worklist.length(); 1.119 + int iterations = 0; 1.120 + while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) { 1.121 + _progress = false; 1.122 + for( uint next = 0; next < length; ++next ) { 1.123 + int ni = worklist.at(next); 1.124 + PointsToNode* ptn = ptnode_adr(ni); 1.125 + Node* n = ptn->_node; 1.126 + assert(n != NULL, "should be known node"); 1.127 + build_connection_graph(n, igvn); 1.128 + } 1.129 + } 1.130 + if (iterations >= CG_BUILD_ITER_LIMIT) { 1.131 + assert(iterations < CG_BUILD_ITER_LIMIT, 1.132 + err_msg("infinite EA connection graph build with %d nodes and worklist size %d", 1.133 + nodes_size(), length)); 1.134 + // Possible infinite build_connection_graph loop, 1.135 + // retry compilation without escape analysis. 1.136 + C->record_failure(C2Compiler::retry_no_escape_analysis()); 1.137 + _collecting = false; 1.138 + return false; 1.139 + } 1.140 +#undef CG_BUILD_ITER_LIMIT 1.141 + 1.142 Arena* arena = Thread::current()->resource_area(); 1.143 VectorSet ptset(arena); 1.144 - GrowableArray<uint> deferred_edges; 1.145 VectorSet visited(arena); 1.146 + worklist.clear(); 1.147 1.148 // 5. Remove deferred edges from the graph and adjust 1.149 // escape state of nonescaping objects. 1.150 @@ -1597,7 +1642,7 @@ 1.151 PointsToNode* ptn = ptnode_adr(ni); 1.152 PointsToNode::NodeType nt = ptn->node_type(); 1.153 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 1.154 - remove_deferred(ni, &deferred_edges, &visited); 1.155 + remove_deferred(ni, &worklist, &visited); 1.156 Node *n = ptn->_node; 1.157 if (n->is_AddP()) { 1.158 // Search for objects which are not scalar replaceable 1.159 @@ -1608,7 +1653,7 @@ 1.160 } 1.161 1.162 // 6. Propagate escape states. 1.163 - GrowableArray<int> worklist; 1.164 + worklist.clear(); 1.165 bool has_non_escaping_obj = false; 1.166 1.167 // push all GlobalEscape nodes on the worklist 1.168 @@ -2444,13 +2489,14 @@ 1.169 1.170 // Don't set processed bit for AddP, LoadP, StoreP since 1.171 // they may need more then one pass to process. 1.172 + // Also don't mark as processed Call nodes since their 1.173 + // arguments may need more then one pass to process. 1.174 if (_processed.test(n_idx)) 1.175 return; // No need to redefine node's state. 1.176 1.177 if (n->is_Call()) { 1.178 CallNode *call = n->as_Call(); 1.179 process_call_arguments(call, phase); 1.180 - _processed.set(n_idx); 1.181 return; 1.182 } 1.183