1.1 --- a/src/share/vm/opto/escape.cpp Fri Jul 02 15:01:47 2010 -0700 1.2 +++ b/src/share/vm/opto/escape.cpp Fri Jul 02 17:30:30 2010 -0700 1.3 @@ -81,18 +81,18 @@ 1.4 } 1.5 #endif 1.6 1.7 -ConnectionGraph::ConnectionGraph(Compile * C) : 1.8 +ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : 1.9 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 1.10 _processed(C->comp_arena()), 1.11 _collecting(true), 1.12 _compile(C), 1.13 + _igvn(igvn), 1.14 _node_map(C->comp_arena()) { 1.15 1.16 _phantom_object = C->top()->_idx, 1.17 add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true); 1.18 1.19 // Add ConP(#NULL) and ConN(#NULL) nodes. 1.20 - PhaseGVN* igvn = C->initial_gvn(); 1.21 Node* oop_null = igvn->zerocon(T_OBJECT); 1.22 _oop_null = oop_null->_idx; 1.23 assert(_oop_null < C->unique(), "should be created already"); 1.24 @@ -182,7 +182,7 @@ 1.25 _processed.set(n->_idx); 1.26 } 1.27 1.28 -PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) { 1.29 +PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) { 1.30 uint idx = n->_idx; 1.31 PointsToNode::EscapeState es; 1.32 1.33 @@ -207,22 +207,26 @@ 1.34 if (n->uncast()->_idx >= nodes_size()) 1.35 return PointsToNode::UnknownEscape; 1.36 1.37 + PointsToNode::EscapeState orig_es = es; 1.38 + 1.39 // compute max escape state of anything this node could point to 1.40 VectorSet ptset(Thread::current()->resource_area()); 1.41 - PointsTo(ptset, n, phase); 1.42 + PointsTo(ptset, n); 1.43 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { 1.44 uint pt = i.elem; 1.45 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 1.46 if (pes > es) 1.47 es = pes; 1.48 } 1.49 - // cache the computed escape state 1.50 - assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 1.51 - ptnode_adr(idx)->set_escape_state(es); 1.52 + if (orig_es != es) { 1.53 + // cache the computed escape state 1.54 + assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 1.55 + ptnode_adr(idx)->set_escape_state(es); 1.56 + } // orig_es could be PointsToNode::UnknownEscape 1.57 return es; 1.58 } 1.59 1.60 -void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) { 1.61 +void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { 1.62 VectorSet visited(Thread::current()->resource_area()); 1.63 GrowableArray<uint> worklist; 1.64 1.65 @@ -990,7 +994,7 @@ 1.66 GrowableArray<Node *> memnode_worklist; 1.67 GrowableArray<PhiNode *> orig_phis; 1.68 1.69 - PhaseGVN *igvn = _compile->initial_gvn(); 1.70 + PhaseGVN *igvn = _igvn; 1.71 uint new_index_start = (uint) _compile->num_alias_types(); 1.72 Arena* arena = Thread::current()->resource_area(); 1.73 VectorSet visited(arena); 1.74 @@ -1012,7 +1016,7 @@ 1.75 CallNode *alloc = n->as_Call(); 1.76 // copy escape information to call node 1.77 PointsToNode* ptn = ptnode_adr(alloc->_idx); 1.78 - PointsToNode::EscapeState es = escape_state(alloc, igvn); 1.79 + PointsToNode::EscapeState es = escape_state(alloc); 1.80 // We have an allocation or call which returns a Java object, 1.81 // see if it is unescaped. 1.82 if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable) 1.83 @@ -1123,7 +1127,7 @@ 1.84 } 1.85 } else if (n->is_AddP()) { 1.86 ptset.Clear(); 1.87 - PointsTo(ptset, get_addp_base(n), igvn); 1.88 + PointsTo(ptset, get_addp_base(n)); 1.89 assert(ptset.Size() == 1, "AddP address is unique"); 1.90 uint elem = ptset.getelem(); // Allocation node's index 1.91 if (elem == _phantom_object) { 1.92 @@ -1143,7 +1147,7 @@ 1.93 continue; // already processed 1.94 } 1.95 ptset.Clear(); 1.96 - PointsTo(ptset, n, igvn); 1.97 + PointsTo(ptset, n); 1.98 if (ptset.Size() == 1) { 1.99 uint elem = ptset.getelem(); // Allocation node's index 1.100 if (elem == _phantom_object) { 1.101 @@ -1478,6 +1482,26 @@ 1.102 return false; 1.103 } 1.104 1.105 +void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) { 1.106 + // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction 1.107 + // to create space for them in ConnectionGraph::_nodes[]. 1.108 + Node* oop_null = igvn->zerocon(T_OBJECT); 1.109 + Node* noop_null = igvn->zerocon(T_NARROWOOP); 1.110 + 1.111 + ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn); 1.112 + // Perform escape analysis 1.113 + if (congraph->compute_escape()) { 1.114 + // There are non escaping objects. 1.115 + C->set_congraph(congraph); 1.116 + } 1.117 + 1.118 + // Cleanup. 1.119 + if (oop_null->outcnt() == 0) 1.120 + igvn->hash_delete(oop_null); 1.121 + if (noop_null->outcnt() == 0) 1.122 + igvn->hash_delete(noop_null); 1.123 +} 1.124 + 1.125 bool ConnectionGraph::compute_escape() { 1.126 Compile* C = _compile; 1.127 1.128 @@ -1492,7 +1516,7 @@ 1.129 } 1.130 1.131 GrowableArray<int> cg_worklist; 1.132 - PhaseGVN* igvn = C->initial_gvn(); 1.133 + PhaseGVN* igvn = _igvn; 1.134 bool has_allocations = false; 1.135 1.136 // Push all useful nodes onto CG list and set their type. 1.137 @@ -1661,6 +1685,12 @@ 1.138 _collecting = false; 1.139 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 1.140 1.141 +#ifndef PRODUCT 1.142 + if (PrintEscapeAnalysis) { 1.143 + dump(); // Dump ConnectionGraph 1.144 + } 1.145 +#endif 1.146 + 1.147 bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; 1.148 if ( has_scalar_replaceable_candidates && 1.149 C->AliasLevel() >= 3 && EliminateAllocations ) { 1.150 @@ -1671,10 +1701,6 @@ 1.151 1.152 if (C->failing()) return false; 1.153 1.154 - // Clean up after split unique types. 1.155 - ResourceMark rm; 1.156 - PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); 1.157 - 1.158 C->print_method("After Escape Analysis", 2); 1.159 1.160 #ifdef ASSERT 1.161 @@ -1711,7 +1737,7 @@ 1.162 int offset = ptn->offset(); 1.163 Node* base = get_addp_base(n); 1.164 ptset.Clear(); 1.165 - PointsTo(ptset, base, phase); 1.166 + PointsTo(ptset, base); 1.167 int ptset_size = ptset.Size(); 1.168 1.169 // Check if a oop field's initializing value is recorded and add 1.170 @@ -1889,7 +1915,7 @@ 1.171 arg = get_addp_base(arg); 1.172 } 1.173 ptset.Clear(); 1.174 - PointsTo(ptset, arg, phase); 1.175 + PointsTo(ptset, arg); 1.176 for( VectorSetI j(&ptset); j.test(); ++j ) { 1.177 uint pt = j.elem; 1.178 set_escape_state(pt, PointsToNode::ArgEscape); 1.179 @@ -1934,7 +1960,7 @@ 1.180 } 1.181 1.182 ptset.Clear(); 1.183 - PointsTo(ptset, arg, phase); 1.184 + PointsTo(ptset, arg); 1.185 for( VectorSetI j(&ptset); j.test(); ++j ) { 1.186 uint pt = j.elem; 1.187 if (global_escapes) { 1.188 @@ -1970,7 +1996,7 @@ 1.189 Node *arg = call->in(i)->uncast(); 1.190 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 1.191 ptset.Clear(); 1.192 - PointsTo(ptset, arg, phase); 1.193 + PointsTo(ptset, arg); 1.194 for( VectorSetI j(&ptset); j.test(); ++j ) { 1.195 uint pt = j.elem; 1.196 set_escape_state(pt, PointsToNode::GlobalEscape); 1.197 @@ -2433,7 +2459,7 @@ 1.198 Node *base = get_addp_base(n); 1.199 // Create a field edge to this node from everything base could point to. 1.200 VectorSet ptset(Thread::current()->resource_area()); 1.201 - PointsTo(ptset, base, phase); 1.202 + PointsTo(ptset, base); 1.203 for( VectorSetI i(&ptset); i.test(); ++i ) { 1.204 uint pt = i.elem; 1.205 add_field_edge(pt, n_idx, address_offset(n, phase)); 1.206 @@ -2501,7 +2527,7 @@ 1.207 // For everything "adr_base" could point to, create a deferred edge from 1.208 // this node to each field with the same offset. 1.209 VectorSet ptset(Thread::current()->resource_area()); 1.210 - PointsTo(ptset, adr_base, phase); 1.211 + PointsTo(ptset, adr_base); 1.212 int offset = address_offset(adr, phase); 1.213 for( VectorSetI i(&ptset); i.test(); ++i ) { 1.214 uint pt = i.elem; 1.215 @@ -2594,7 +2620,7 @@ 1.216 // For everything "adr_base" could point to, create a deferred edge 1.217 // to "val" from each field with the same offset. 1.218 VectorSet ptset(Thread::current()->resource_area()); 1.219 - PointsTo(ptset, adr_base, phase); 1.220 + PointsTo(ptset, adr_base); 1.221 for( VectorSetI i(&ptset); i.test(); ++i ) { 1.222 uint pt = i.elem; 1.223 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 1.224 @@ -2638,7 +2664,6 @@ 1.225 1.226 #ifndef PRODUCT 1.227 void ConnectionGraph::dump() { 1.228 - PhaseGVN *igvn = _compile->initial_gvn(); 1.229 bool first = true; 1.230 1.231 uint size = nodes_size(); 1.232 @@ -2648,7 +2673,7 @@ 1.233 1.234 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) 1.235 continue; 1.236 - PointsToNode::EscapeState es = escape_state(ptn->_node, igvn); 1.237 + PointsToNode::EscapeState es = escape_state(ptn->_node); 1.238 if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { 1.239 if (first) { 1.240 tty->cr();