1.1 --- a/src/share/vm/opto/escape.cpp Wed Jul 02 15:38:47 2008 -0400 1.2 +++ b/src/share/vm/opto/escape.cpp Thu Jul 03 18:02:47 2008 -0700 1.3 @@ -25,16 +25,6 @@ 1.4 #include "incls/_precompiled.incl" 1.5 #include "incls/_escape.cpp.incl" 1.6 1.7 -uint PointsToNode::edge_target(uint e) const { 1.8 - assert(_edges != NULL && e < (uint)_edges->length(), "valid edge index"); 1.9 - return (_edges->at(e) >> EdgeShift); 1.10 -} 1.11 - 1.12 -PointsToNode::EdgeType PointsToNode::edge_type(uint e) const { 1.13 - assert(_edges != NULL && e < (uint)_edges->length(), "valid edge index"); 1.14 - return (EdgeType) (_edges->at(e) & EdgeMask); 1.15 -} 1.16 - 1.17 void PointsToNode::add_edge(uint targIdx, PointsToNode::EdgeType et) { 1.18 uint v = (targIdx << EdgeShift) + ((uint) et); 1.19 if (_edges == NULL) { 1.20 @@ -87,12 +77,13 @@ 1.21 } 1.22 #endif 1.23 1.24 -ConnectionGraph::ConnectionGraph(Compile * C) : _processed(C->comp_arena()), _node_map(C->comp_arena()) { 1.25 - _collecting = true; 1.26 - this->_compile = C; 1.27 - const PointsToNode &dummy = PointsToNode(); 1.28 - int sz = C->unique(); 1.29 - _nodes = new(C->comp_arena()) GrowableArray<PointsToNode>(C->comp_arena(), sz, sz, dummy); 1.30 +ConnectionGraph::ConnectionGraph(Compile * C) : 1.31 + _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 1.32 + _processed(C->comp_arena()), 1.33 + _collecting(true), 1.34 + _compile(C), 1.35 + _node_map(C->comp_arena()) { 1.36 + 1.37 _phantom_object = C->top()->_idx; 1.38 PointsToNode *phn = ptnode_adr(_phantom_object); 1.39 phn->_node = C->top(); 1.40 @@ -182,32 +173,36 @@ 1.41 1.42 // If we are still collecting or there were no non-escaping allocations 1.43 // we don't know the answer yet 1.44 - if (_collecting || !_has_allocations) 1.45 + if (_collecting) 1.46 return PointsToNode::UnknownEscape; 1.47 1.48 // if the node was created after the escape computation, return 1.49 // UnknownEscape 1.50 - if (idx >= (uint)_nodes->length()) 1.51 + if (idx >= nodes_size()) 1.52 return PointsToNode::UnknownEscape; 1.53 1.54 - es = _nodes->at_grow(idx).escape_state(); 1.55 + es = ptnode_adr(idx)->escape_state(); 1.56 1.57 // if we have already computed a value, return it 1.58 if (es != PointsToNode::UnknownEscape) 1.59 return es; 1.60 1.61 + // PointsTo() calls n->uncast() which can return a new ideal node. 1.62 + if (n->uncast()->_idx >= nodes_size()) 1.63 + return PointsToNode::UnknownEscape; 1.64 + 1.65 // compute max escape state of anything this node could point to 1.66 VectorSet ptset(Thread::current()->resource_area()); 1.67 PointsTo(ptset, n, phase); 1.68 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { 1.69 uint pt = i.elem; 1.70 - PointsToNode::EscapeState pes = _nodes->adr_at(pt)->escape_state(); 1.71 + PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 1.72 if (pes > es) 1.73 es = pes; 1.74 } 1.75 // cache the computed escape state 1.76 assert(es != PointsToNode::UnknownEscape, "should have computed an escape state"); 1.77 - _nodes->adr_at(idx)->set_escape_state(es); 1.78 + ptnode_adr(idx)->set_escape_state(es); 1.79 return es; 1.80 } 1.81 1.82 @@ -220,48 +215,50 @@ 1.83 #endif 1.84 1.85 n = n->uncast(); 1.86 - PointsToNode npt = _nodes->at_grow(n->_idx); 1.87 + PointsToNode* npt = ptnode_adr(n->_idx); 1.88 1.89 // If we have a JavaObject, return just that object 1.90 - if (npt.node_type() == PointsToNode::JavaObject) { 1.91 + if (npt->node_type() == PointsToNode::JavaObject) { 1.92 ptset.set(n->_idx); 1.93 return; 1.94 } 1.95 #ifdef ASSERT 1.96 - if (npt._node == NULL) { 1.97 + if (npt->_node == NULL) { 1.98 if (orig_n != n) 1.99 orig_n->dump(); 1.100 n->dump(); 1.101 - assert(npt._node != NULL, "unregistered node"); 1.102 + assert(npt->_node != NULL, "unregistered node"); 1.103 } 1.104 #endif 1.105 worklist.push(n->_idx); 1.106 while(worklist.length() > 0) { 1.107 int ni = worklist.pop(); 1.108 - PointsToNode pn = _nodes->at_grow(ni); 1.109 - if (!visited.test_set(ni)) { 1.110 - // ensure that all inputs of a Phi have been processed 1.111 - assert(!_collecting || !pn._node->is_Phi() || _processed.test(ni),""); 1.112 + if (visited.test_set(ni)) 1.113 + continue; 1.114 1.115 - int edges_processed = 0; 1.116 - for (uint e = 0; e < pn.edge_count(); e++) { 1.117 - uint etgt = pn.edge_target(e); 1.118 - PointsToNode::EdgeType et = pn.edge_type(e); 1.119 - if (et == PointsToNode::PointsToEdge) { 1.120 - ptset.set(etgt); 1.121 - edges_processed++; 1.122 - } else if (et == PointsToNode::DeferredEdge) { 1.123 - worklist.push(etgt); 1.124 - edges_processed++; 1.125 - } else { 1.126 - assert(false,"neither PointsToEdge or DeferredEdge"); 1.127 - } 1.128 + PointsToNode* pn = ptnode_adr(ni); 1.129 + // ensure that all inputs of a Phi have been processed 1.130 + assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),""); 1.131 + 1.132 + int edges_processed = 0; 1.133 + uint e_cnt = pn->edge_count(); 1.134 + for (uint e = 0; e < e_cnt; e++) { 1.135 + uint etgt = pn->edge_target(e); 1.136 + PointsToNode::EdgeType et = pn->edge_type(e); 1.137 + if (et == PointsToNode::PointsToEdge) { 1.138 + ptset.set(etgt); 1.139 + edges_processed++; 1.140 + } else if (et == PointsToNode::DeferredEdge) { 1.141 + worklist.push(etgt); 1.142 + edges_processed++; 1.143 + } else { 1.144 + assert(false,"neither PointsToEdge or DeferredEdge"); 1.145 } 1.146 - if (edges_processed == 0) { 1.147 - // no deferred or pointsto edges found. Assume the value was set 1.148 - // outside this method. Add the phantom object to the pointsto set. 1.149 - ptset.set(_phantom_object); 1.150 - } 1.151 + } 1.152 + if (edges_processed == 0) { 1.153 + // no deferred or pointsto edges found. Assume the value was set 1.154 + // outside this method. Add the phantom object to the pointsto set. 1.155 + ptset.set(_phantom_object); 1.156 } 1.157 } 1.158 } 1.159 @@ -272,11 +269,11 @@ 1.160 deferred_edges->clear(); 1.161 visited->Clear(); 1.162 1.163 - uint i = 0; 1.164 + visited->set(ni); 1.165 PointsToNode *ptn = ptnode_adr(ni); 1.166 1.167 // Mark current edges as visited and move deferred edges to separate array. 1.168 - while (i < ptn->edge_count()) { 1.169 + for (uint i = 0; i < ptn->edge_count(); ) { 1.170 uint t = ptn->edge_target(i); 1.171 #ifdef ASSERT 1.172 assert(!visited->test_set(t), "expecting no duplications"); 1.173 @@ -293,24 +290,23 @@ 1.174 for (int next = 0; next < deferred_edges->length(); ++next) { 1.175 uint t = deferred_edges->at(next); 1.176 PointsToNode *ptt = ptnode_adr(t); 1.177 - for (uint j = 0; j < ptt->edge_count(); j++) { 1.178 - uint n1 = ptt->edge_target(j); 1.179 - if (visited->test_set(n1)) 1.180 + uint e_cnt = ptt->edge_count(); 1.181 + for (uint e = 0; e < e_cnt; e++) { 1.182 + uint etgt = ptt->edge_target(e); 1.183 + if (visited->test_set(etgt)) 1.184 continue; 1.185 - switch(ptt->edge_type(j)) { 1.186 - case PointsToNode::PointsToEdge: 1.187 - add_pointsto_edge(ni, n1); 1.188 - if(n1 == _phantom_object) { 1.189 - // Special case - field set outside (globally escaping). 1.190 - ptn->set_escape_state(PointsToNode::GlobalEscape); 1.191 - } 1.192 - break; 1.193 - case PointsToNode::DeferredEdge: 1.194 - deferred_edges->append(n1); 1.195 - break; 1.196 - case PointsToNode::FieldEdge: 1.197 - assert(false, "invalid connection graph"); 1.198 - break; 1.199 + 1.200 + PointsToNode::EdgeType et = ptt->edge_type(e); 1.201 + if (et == PointsToNode::PointsToEdge) { 1.202 + add_pointsto_edge(ni, etgt); 1.203 + if(etgt == _phantom_object) { 1.204 + // Special case - field set outside (globally escaping). 1.205 + ptn->set_escape_state(PointsToNode::GlobalEscape); 1.206 + } 1.207 + } else if (et == PointsToNode::DeferredEdge) { 1.208 + deferred_edges->append(etgt); 1.209 + } else { 1.210 + assert(false,"invalid connection graph"); 1.211 } 1.212 } 1.213 } 1.214 @@ -322,15 +318,15 @@ 1.215 // a pointsto edge is added if it is a JavaObject 1.216 1.217 void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { 1.218 - PointsToNode an = _nodes->at_grow(adr_i); 1.219 - PointsToNode to = _nodes->at_grow(to_i); 1.220 - bool deferred = (to.node_type() == PointsToNode::LocalVar); 1.221 + PointsToNode* an = ptnode_adr(adr_i); 1.222 + PointsToNode* to = ptnode_adr(to_i); 1.223 + bool deferred = (to->node_type() == PointsToNode::LocalVar); 1.224 1.225 - for (uint fe = 0; fe < an.edge_count(); fe++) { 1.226 - assert(an.edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 1.227 - int fi = an.edge_target(fe); 1.228 - PointsToNode pf = _nodes->at_grow(fi); 1.229 - int po = pf.offset(); 1.230 + for (uint fe = 0; fe < an->edge_count(); fe++) { 1.231 + assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 1.232 + int fi = an->edge_target(fe); 1.233 + PointsToNode* pf = ptnode_adr(fi); 1.234 + int po = pf->offset(); 1.235 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { 1.236 if (deferred) 1.237 add_deferred_edge(fi, to_i); 1.238 @@ -343,13 +339,13 @@ 1.239 // Add a deferred edge from node given by "from_i" to any field of adr_i 1.240 // whose offset matches "offset". 1.241 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { 1.242 - PointsToNode an = _nodes->at_grow(adr_i); 1.243 - for (uint fe = 0; fe < an.edge_count(); fe++) { 1.244 - assert(an.edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 1.245 - int fi = an.edge_target(fe); 1.246 - PointsToNode pf = _nodes->at_grow(fi); 1.247 - int po = pf.offset(); 1.248 - if (pf.edge_count() == 0) { 1.249 + PointsToNode* an = ptnode_adr(adr_i); 1.250 + for (uint fe = 0; fe < an->edge_count(); fe++) { 1.251 + assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 1.252 + int fi = an->edge_target(fe); 1.253 + PointsToNode* pf = ptnode_adr(fi); 1.254 + int po = pf->offset(); 1.255 + if (pf->edge_count() == 0) { 1.256 // we have not seen any stores to this field, assume it was set outside this method 1.257 add_pointsto_edge(fi, _phantom_object); 1.258 } 1.259 @@ -835,6 +831,11 @@ 1.260 1.261 // Phase 1: Process possible allocations from alloc_worklist. 1.262 // Create instance types for the CheckCastPP for allocations where possible. 1.263 + // 1.264 + // (Note: don't forget to change the order of the second AddP node on 1.265 + // the alloc_worklist if the order of the worklist processing is changed, 1.266 + // see the comment in find_second_addp().) 1.267 + // 1.268 while (alloc_worklist.length() != 0) { 1.269 Node *n = alloc_worklist.pop(); 1.270 uint ni = n->_idx; 1.271 @@ -842,7 +843,7 @@ 1.272 if (n->is_Call()) { 1.273 CallNode *alloc = n->as_Call(); 1.274 // copy escape information to call node 1.275 - PointsToNode* ptn = _nodes->adr_at(alloc->_idx); 1.276 + PointsToNode* ptn = ptnode_adr(alloc->_idx); 1.277 PointsToNode::EscapeState es = escape_state(alloc, igvn); 1.278 // We have an allocation or call which returns a Java object, 1.279 // see if it is unescaped. 1.280 @@ -899,7 +900,7 @@ 1.281 // First, put on the worklist all Field edges from Connection Graph 1.282 // which is more accurate then putting immediate users from Ideal Graph. 1.283 for (uint e = 0; e < ptn->edge_count(); e++) { 1.284 - Node *use = _nodes->adr_at(ptn->edge_target(e))->_node; 1.285 + Node *use = ptnode_adr(ptn->edge_target(e))->_node; 1.286 assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(), 1.287 "only AddP nodes are Field edges in CG"); 1.288 if (use->outcnt() > 0) { // Don't process dead nodes 1.289 @@ -1062,7 +1063,7 @@ 1.290 } 1.291 if (mem != n->in(MemNode::Memory)) { 1.292 set_map(n->_idx, mem); 1.293 - _nodes->adr_at(n->_idx)->_node = n; 1.294 + ptnode_adr(n->_idx)->_node = n; 1.295 } 1.296 if (n->is_Load()) { 1.297 continue; // don't push users 1.298 @@ -1223,10 +1224,10 @@ 1.299 1.300 // Update the memory inputs of MemNodes with the value we computed 1.301 // in Phase 2. 1.302 - for (int i = 0; i < _nodes->length(); i++) { 1.303 + for (uint i = 0; i < nodes_size(); i++) { 1.304 Node *nmem = get_map(i); 1.305 if (nmem != NULL) { 1.306 - Node *n = _nodes->adr_at(i)->_node; 1.307 + Node *n = ptnode_adr(i)->_node; 1.308 if (n != NULL && n->is_Mem()) { 1.309 igvn->hash_delete(n); 1.310 n->set_req(MemNode::Memory, nmem); 1.311 @@ -1237,28 +1238,48 @@ 1.312 } 1.313 } 1.314 1.315 -void ConnectionGraph::compute_escape() { 1.316 +bool ConnectionGraph::has_candidates(Compile *C) { 1.317 + // EA brings benefits only when the code has allocations and/or locks which 1.318 + // are represented by ideal Macro nodes. 1.319 + int cnt = C->macro_count(); 1.320 + for( int i=0; i < cnt; i++ ) { 1.321 + Node *n = C->macro_node(i); 1.322 + if ( n->is_Allocate() ) 1.323 + return true; 1.324 + if( n->is_Lock() ) { 1.325 + Node* obj = n->as_Lock()->obj_node()->uncast(); 1.326 + if( !(obj->is_Parm() || obj->is_Con()) ) 1.327 + return true; 1.328 + } 1.329 + } 1.330 + return false; 1.331 +} 1.332 + 1.333 +bool ConnectionGraph::compute_escape() { 1.334 + Compile* C = _compile; 1.335 1.336 // 1. Populate Connection Graph (CG) with Ideal nodes. 1.337 1.338 Unique_Node_List worklist_init; 1.339 - worklist_init.map(_compile->unique(), NULL); // preallocate space 1.340 + worklist_init.map(C->unique(), NULL); // preallocate space 1.341 1.342 // Initialize worklist 1.343 - if (_compile->root() != NULL) { 1.344 - worklist_init.push(_compile->root()); 1.345 + if (C->root() != NULL) { 1.346 + worklist_init.push(C->root()); 1.347 } 1.348 1.349 GrowableArray<int> cg_worklist; 1.350 - PhaseGVN* igvn = _compile->initial_gvn(); 1.351 + PhaseGVN* igvn = C->initial_gvn(); 1.352 bool has_allocations = false; 1.353 1.354 // Push all useful nodes onto CG list and set their type. 1.355 for( uint next = 0; next < worklist_init.size(); ++next ) { 1.356 Node* n = worklist_init.at(next); 1.357 record_for_escape_analysis(n, igvn); 1.358 - if (n->is_Call() && 1.359 - _nodes->adr_at(n->_idx)->node_type() == PointsToNode::JavaObject) { 1.360 + // Only allocations and java static calls results are checked 1.361 + // for an escape status. See process_call_result() below. 1.362 + if (n->is_Allocate() || n->is_CallStaticJava() && 1.363 + ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { 1.364 has_allocations = true; 1.365 } 1.366 if(n->is_AddP()) 1.367 @@ -1269,24 +1290,23 @@ 1.368 } 1.369 } 1.370 1.371 - if (has_allocations) { 1.372 - _has_allocations = true; 1.373 - } else { 1.374 - _has_allocations = false; 1.375 + if (!has_allocations) { 1.376 _collecting = false; 1.377 - return; // Nothing to do. 1.378 + return false; // Nothing to do. 1.379 } 1.380 1.381 // 2. First pass to create simple CG edges (doesn't require to walk CG). 1.382 - for( uint next = 0; next < _delayed_worklist.size(); ++next ) { 1.383 + uint delayed_size = _delayed_worklist.size(); 1.384 + for( uint next = 0; next < delayed_size; ++next ) { 1.385 Node* n = _delayed_worklist.at(next); 1.386 build_connection_graph(n, igvn); 1.387 } 1.388 1.389 // 3. Pass to create fields edges (Allocate -F-> AddP). 1.390 - for( int next = 0; next < cg_worklist.length(); ++next ) { 1.391 + uint cg_length = cg_worklist.length(); 1.392 + for( uint next = 0; next < cg_length; ++next ) { 1.393 int ni = cg_worklist.at(next); 1.394 - build_connection_graph(_nodes->adr_at(ni)->_node, igvn); 1.395 + build_connection_graph(ptnode_adr(ni)->_node, igvn); 1.396 } 1.397 1.398 cg_worklist.clear(); 1.399 @@ -1294,8 +1314,8 @@ 1.400 1.401 // 4. Build Connection Graph which need 1.402 // to walk the connection graph. 1.403 - for (uint ni = 0; ni < (uint)_nodes->length(); ni++) { 1.404 - PointsToNode* ptn = _nodes->adr_at(ni); 1.405 + for (uint ni = 0; ni < nodes_size(); ni++) { 1.406 + PointsToNode* ptn = ptnode_adr(ni); 1.407 Node *n = ptn->_node; 1.408 if (n != NULL) { // Call, AddP, LoadP, StoreP 1.409 build_connection_graph(n, igvn); 1.410 @@ -1305,20 +1325,19 @@ 1.411 } 1.412 1.413 VectorSet ptset(Thread::current()->resource_area()); 1.414 - GrowableArray<Node*> alloc_worklist; 1.415 - GrowableArray<int> worklist; 1.416 GrowableArray<uint> deferred_edges; 1.417 VectorSet visited(Thread::current()->resource_area()); 1.418 1.419 - // remove deferred edges from the graph and collect 1.420 - // information we will need for type splitting 1.421 - for( int next = 0; next < cg_worklist.length(); ++next ) { 1.422 + // 5. Remove deferred edges from the graph and collect 1.423 + // information needed for type splitting. 1.424 + cg_length = cg_worklist.length(); 1.425 + for( uint next = 0; next < cg_length; ++next ) { 1.426 int ni = cg_worklist.at(next); 1.427 - PointsToNode* ptn = _nodes->adr_at(ni); 1.428 + PointsToNode* ptn = ptnode_adr(ni); 1.429 PointsToNode::NodeType nt = ptn->node_type(); 1.430 - Node *n = ptn->_node; 1.431 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 1.432 remove_deferred(ni, &deferred_edges, &visited); 1.433 + Node *n = ptn->_node; 1.434 if (n->is_AddP()) { 1.435 // If this AddP computes an address which may point to more that one 1.436 // object or more then one field (array's element), nothing the address 1.437 @@ -1329,116 +1348,123 @@ 1.438 if (ptset.Size() > 1 || 1.439 (ptset.Size() != 0 && ptn->offset() == Type::OffsetBot)) { 1.440 for( VectorSetI j(&ptset); j.test(); ++j ) { 1.441 - uint pt = j.elem; 1.442 - ptnode_adr(pt)->_scalar_replaceable = false; 1.443 + ptnode_adr(j.elem)->_scalar_replaceable = false; 1.444 } 1.445 } 1.446 } 1.447 - } else if (nt == PointsToNode::JavaObject && n->is_Call()) { 1.448 - // Push call on alloc_worlist (alocations are calls) 1.449 - // for processing by split_unique_types(). 1.450 - alloc_worklist.append(n); 1.451 } 1.452 } 1.453 1.454 + // 6. Propagate escape states. 1.455 + GrowableArray<int> worklist; 1.456 + bool has_non_escaping_obj = false; 1.457 + 1.458 // push all GlobalEscape nodes on the worklist 1.459 - for( int next = 0; next < cg_worklist.length(); ++next ) { 1.460 + for( uint next = 0; next < cg_length; ++next ) { 1.461 int nk = cg_worklist.at(next); 1.462 - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::GlobalEscape) 1.463 - worklist.append(nk); 1.464 + if (ptnode_adr(nk)->escape_state() == PointsToNode::GlobalEscape) 1.465 + worklist.push(nk); 1.466 } 1.467 - // mark all node reachable from GlobalEscape nodes 1.468 + // mark all nodes reachable from GlobalEscape nodes 1.469 while(worklist.length() > 0) { 1.470 - PointsToNode n = _nodes->at(worklist.pop()); 1.471 - for (uint ei = 0; ei < n.edge_count(); ei++) { 1.472 - uint npi = n.edge_target(ei); 1.473 + PointsToNode* ptn = ptnode_adr(worklist.pop()); 1.474 + uint e_cnt = ptn->edge_count(); 1.475 + for (uint ei = 0; ei < e_cnt; ei++) { 1.476 + uint npi = ptn->edge_target(ei); 1.477 PointsToNode *np = ptnode_adr(npi); 1.478 if (np->escape_state() < PointsToNode::GlobalEscape) { 1.479 np->set_escape_state(PointsToNode::GlobalEscape); 1.480 - worklist.append_if_missing(npi); 1.481 + worklist.push(npi); 1.482 } 1.483 } 1.484 } 1.485 1.486 // push all ArgEscape nodes on the worklist 1.487 - for( int next = 0; next < cg_worklist.length(); ++next ) { 1.488 + for( uint next = 0; next < cg_length; ++next ) { 1.489 int nk = cg_worklist.at(next); 1.490 - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::ArgEscape) 1.491 + if (ptnode_adr(nk)->escape_state() == PointsToNode::ArgEscape) 1.492 worklist.push(nk); 1.493 } 1.494 - // mark all node reachable from ArgEscape nodes 1.495 + // mark all nodes reachable from ArgEscape nodes 1.496 while(worklist.length() > 0) { 1.497 - PointsToNode n = _nodes->at(worklist.pop()); 1.498 - for (uint ei = 0; ei < n.edge_count(); ei++) { 1.499 - uint npi = n.edge_target(ei); 1.500 + PointsToNode* ptn = ptnode_adr(worklist.pop()); 1.501 + if (ptn->node_type() == PointsToNode::JavaObject) 1.502 + has_non_escaping_obj = true; // Non GlobalEscape 1.503 + uint e_cnt = ptn->edge_count(); 1.504 + for (uint ei = 0; ei < e_cnt; ei++) { 1.505 + uint npi = ptn->edge_target(ei); 1.506 PointsToNode *np = ptnode_adr(npi); 1.507 if (np->escape_state() < PointsToNode::ArgEscape) { 1.508 np->set_escape_state(PointsToNode::ArgEscape); 1.509 - worklist.append_if_missing(npi); 1.510 + worklist.push(npi); 1.511 } 1.512 } 1.513 } 1.514 1.515 + GrowableArray<Node*> alloc_worklist; 1.516 + 1.517 // push all NoEscape nodes on the worklist 1.518 - for( int next = 0; next < cg_worklist.length(); ++next ) { 1.519 + for( uint next = 0; next < cg_length; ++next ) { 1.520 int nk = cg_worklist.at(next); 1.521 - if (_nodes->adr_at(nk)->escape_state() == PointsToNode::NoEscape) 1.522 + if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape) 1.523 worklist.push(nk); 1.524 } 1.525 - // mark all node reachable from NoEscape nodes 1.526 + // mark all nodes reachable from NoEscape nodes 1.527 while(worklist.length() > 0) { 1.528 - PointsToNode n = _nodes->at(worklist.pop()); 1.529 - for (uint ei = 0; ei < n.edge_count(); ei++) { 1.530 - uint npi = n.edge_target(ei); 1.531 + PointsToNode* ptn = ptnode_adr(worklist.pop()); 1.532 + if (ptn->node_type() == PointsToNode::JavaObject) 1.533 + has_non_escaping_obj = true; // Non GlobalEscape 1.534 + Node* n = ptn->_node; 1.535 + if (n->is_Allocate() && ptn->_scalar_replaceable ) { 1.536 + // Push scalar replaceable alocations on alloc_worklist 1.537 + // for processing in split_unique_types(). 1.538 + alloc_worklist.append(n); 1.539 + } 1.540 + uint e_cnt = ptn->edge_count(); 1.541 + for (uint ei = 0; ei < e_cnt; ei++) { 1.542 + uint npi = ptn->edge_target(ei); 1.543 PointsToNode *np = ptnode_adr(npi); 1.544 if (np->escape_state() < PointsToNode::NoEscape) { 1.545 np->set_escape_state(PointsToNode::NoEscape); 1.546 - worklist.append_if_missing(npi); 1.547 + worklist.push(npi); 1.548 } 1.549 } 1.550 } 1.551 1.552 _collecting = false; 1.553 + assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 1.554 1.555 - has_allocations = false; // Are there scalar replaceable allocations? 1.556 + bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; 1.557 + if ( has_scalar_replaceable_candidates && 1.558 + C->AliasLevel() >= 3 && EliminateAllocations ) { 1.559 1.560 - for( int next = 0; next < alloc_worklist.length(); ++next ) { 1.561 - Node* n = alloc_worklist.at(next); 1.562 - uint ni = n->_idx; 1.563 - PointsToNode* ptn = _nodes->adr_at(ni); 1.564 - PointsToNode::EscapeState es = ptn->escape_state(); 1.565 - if (ptn->escape_state() == PointsToNode::NoEscape && 1.566 - ptn->_scalar_replaceable) { 1.567 - has_allocations = true; 1.568 - break; 1.569 - } 1.570 - } 1.571 - if (!has_allocations) { 1.572 - return; // Nothing to do. 1.573 - } 1.574 + // Now use the escape information to create unique types for 1.575 + // scalar replaceable objects. 1.576 + split_unique_types(alloc_worklist); 1.577 1.578 - if(_compile->AliasLevel() >= 3 && EliminateAllocations) { 1.579 - // Now use the escape information to create unique types for 1.580 - // unescaped objects 1.581 - split_unique_types(alloc_worklist); 1.582 - if (_compile->failing()) return; 1.583 + if (C->failing()) return false; 1.584 1.585 // Clean up after split unique types. 1.586 ResourceMark rm; 1.587 - PhaseRemoveUseless pru(_compile->initial_gvn(), _compile->for_igvn()); 1.588 + PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); 1.589 + 1.590 + C->print_method("After Escape Analysis", 2); 1.591 1.592 #ifdef ASSERT 1.593 - } else if (PrintEscapeAnalysis || PrintEliminateAllocations) { 1.594 + } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { 1.595 tty->print("=== No allocations eliminated for "); 1.596 - C()->method()->print_short_name(); 1.597 + C->method()->print_short_name(); 1.598 if(!EliminateAllocations) { 1.599 tty->print(" since EliminateAllocations is off ==="); 1.600 - } else if(_compile->AliasLevel() < 3) { 1.601 + } else if(!has_scalar_replaceable_candidates) { 1.602 + tty->print(" since there are no scalar replaceable candidates ==="); 1.603 + } else if(C->AliasLevel() < 3) { 1.604 tty->print(" since AliasLevel < 3 ==="); 1.605 } 1.606 tty->cr(); 1.607 #endif 1.608 } 1.609 + return has_non_escaping_obj; 1.610 } 1.611 1.612 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { 1.613 @@ -1538,7 +1564,7 @@ 1.614 } 1.615 } 1.616 if (copy_dependencies) 1.617 - call_analyzer->copy_dependencies(C()->dependencies()); 1.618 + call_analyzer->copy_dependencies(_compile->dependencies()); 1.619 break; 1.620 } 1.621 } 1.622 @@ -1561,7 +1587,6 @@ 1.623 for( VectorSetI j(&ptset); j.test(); ++j ) { 1.624 uint pt = j.elem; 1.625 set_escape_state(pt, PointsToNode::GlobalEscape); 1.626 - PointsToNode *ptadr = ptnode_adr(pt); 1.627 } 1.628 } 1.629 } 1.630 @@ -1569,9 +1594,10 @@ 1.631 } 1.632 } 1.633 void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *phase) { 1.634 - PointsToNode *ptadr = ptnode_adr(resproj->_idx); 1.635 + CallNode *call = resproj->in(0)->as_Call(); 1.636 + uint call_idx = call->_idx; 1.637 + uint resproj_idx = resproj->_idx; 1.638 1.639 - CallNode *call = resproj->in(0)->as_Call(); 1.640 switch (call->Opcode()) { 1.641 case Op_Allocate: 1.642 { 1.643 @@ -1587,7 +1613,6 @@ 1.644 ciKlass* cik = kt->klass(); 1.645 ciInstanceKlass* ciik = cik->as_instance_klass(); 1.646 1.647 - PointsToNode *ptadr = ptnode_adr(call->_idx); 1.648 PointsToNode::EscapeState es; 1.649 uint edge_to; 1.650 if (cik->is_subclass_of(_compile->env()->Thread_klass()) || ciik->has_finalizer()) { 1.651 @@ -1595,25 +1620,24 @@ 1.652 edge_to = _phantom_object; // Could not be worse 1.653 } else { 1.654 es = PointsToNode::NoEscape; 1.655 - edge_to = call->_idx; 1.656 + edge_to = call_idx; 1.657 } 1.658 - set_escape_state(call->_idx, es); 1.659 - add_pointsto_edge(resproj->_idx, edge_to); 1.660 - _processed.set(resproj->_idx); 1.661 + set_escape_state(call_idx, es); 1.662 + add_pointsto_edge(resproj_idx, edge_to); 1.663 + _processed.set(resproj_idx); 1.664 break; 1.665 } 1.666 1.667 case Op_AllocateArray: 1.668 { 1.669 - PointsToNode *ptadr = ptnode_adr(call->_idx); 1.670 int length = call->in(AllocateNode::ALength)->find_int_con(-1); 1.671 if (length < 0 || length > EliminateAllocationArraySizeLimit) { 1.672 // Not scalar replaceable if the length is not constant or too big. 1.673 - ptadr->_scalar_replaceable = false; 1.674 + ptnode_adr(call_idx)->_scalar_replaceable = false; 1.675 } 1.676 - set_escape_state(call->_idx, PointsToNode::NoEscape); 1.677 - add_pointsto_edge(resproj->_idx, call->_idx); 1.678 - _processed.set(resproj->_idx); 1.679 + set_escape_state(call_idx, PointsToNode::NoEscape); 1.680 + add_pointsto_edge(resproj_idx, call_idx); 1.681 + _processed.set(resproj_idx); 1.682 break; 1.683 } 1.684 1.685 @@ -1631,19 +1655,17 @@ 1.686 // Note: we use isa_ptr() instead of isa_oopptr() here because the 1.687 // _multianewarray functions return a TypeRawPtr. 1.688 if (ret_type == NULL || ret_type->isa_ptr() == NULL) { 1.689 - _processed.set(resproj->_idx); 1.690 + _processed.set(resproj_idx); 1.691 break; // doesn't return a pointer type 1.692 } 1.693 ciMethod *meth = call->as_CallJava()->method(); 1.694 const TypeTuple * d = call->tf()->domain(); 1.695 if (meth == NULL) { 1.696 // not a Java method, assume global escape 1.697 - set_escape_state(call->_idx, PointsToNode::GlobalEscape); 1.698 - if (resproj != NULL) 1.699 - add_pointsto_edge(resproj->_idx, _phantom_object); 1.700 + set_escape_state(call_idx, PointsToNode::GlobalEscape); 1.701 + add_pointsto_edge(resproj_idx, _phantom_object); 1.702 } else { 1.703 BCEscapeAnalyzer *call_analyzer = meth->get_bcea(); 1.704 - VectorSet ptset(Thread::current()->resource_area()); 1.705 bool copy_dependencies = false; 1.706 1.707 if (call_analyzer->is_return_allocated()) { 1.708 @@ -1651,13 +1673,12 @@ 1.709 // update dependency information. 1.710 // Mark it as NoEscape so that objects referenced by 1.711 // it's fields will be marked as NoEscape at least. 1.712 - set_escape_state(call->_idx, PointsToNode::NoEscape); 1.713 - if (resproj != NULL) 1.714 - add_pointsto_edge(resproj->_idx, call->_idx); 1.715 + set_escape_state(call_idx, PointsToNode::NoEscape); 1.716 + add_pointsto_edge(resproj_idx, call_idx); 1.717 copy_dependencies = true; 1.718 - } else if (call_analyzer->is_return_local() && resproj != NULL) { 1.719 + } else if (call_analyzer->is_return_local()) { 1.720 // determine whether any arguments are returned 1.721 - set_escape_state(call->_idx, PointsToNode::NoEscape); 1.722 + set_escape_state(call_idx, PointsToNode::NoEscape); 1.723 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1.724 const Type* at = d->field_at(i); 1.725 1.726 @@ -1665,36 +1686,35 @@ 1.727 Node *arg = call->in(i)->uncast(); 1.728 1.729 if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) { 1.730 - PointsToNode *arg_esp = _nodes->adr_at(arg->_idx); 1.731 + PointsToNode *arg_esp = ptnode_adr(arg->_idx); 1.732 if (arg_esp->node_type() == PointsToNode::UnknownType) 1.733 done = false; 1.734 else if (arg_esp->node_type() == PointsToNode::JavaObject) 1.735 - add_pointsto_edge(resproj->_idx, arg->_idx); 1.736 + add_pointsto_edge(resproj_idx, arg->_idx); 1.737 else 1.738 - add_deferred_edge(resproj->_idx, arg->_idx); 1.739 + add_deferred_edge(resproj_idx, arg->_idx); 1.740 arg_esp->_hidden_alias = true; 1.741 } 1.742 } 1.743 } 1.744 copy_dependencies = true; 1.745 } else { 1.746 - set_escape_state(call->_idx, PointsToNode::GlobalEscape); 1.747 - if (resproj != NULL) 1.748 - add_pointsto_edge(resproj->_idx, _phantom_object); 1.749 + set_escape_state(call_idx, PointsToNode::GlobalEscape); 1.750 + add_pointsto_edge(resproj_idx, _phantom_object); 1.751 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1.752 const Type* at = d->field_at(i); 1.753 if (at->isa_oopptr() != NULL) { 1.754 Node *arg = call->in(i)->uncast(); 1.755 - PointsToNode *arg_esp = _nodes->adr_at(arg->_idx); 1.756 + PointsToNode *arg_esp = ptnode_adr(arg->_idx); 1.757 arg_esp->_hidden_alias = true; 1.758 } 1.759 } 1.760 } 1.761 if (copy_dependencies) 1.762 - call_analyzer->copy_dependencies(C()->dependencies()); 1.763 + call_analyzer->copy_dependencies(_compile->dependencies()); 1.764 } 1.765 if (done) 1.766 - _processed.set(resproj->_idx); 1.767 + _processed.set(resproj_idx); 1.768 break; 1.769 } 1.770 1.771 @@ -1709,13 +1729,11 @@ 1.772 // Note: we use isa_ptr() instead of isa_oopptr() here because the 1.773 // _multianewarray functions return a TypeRawPtr. 1.774 if (ret_type->isa_ptr() != NULL) { 1.775 - PointsToNode *ptadr = ptnode_adr(call->_idx); 1.776 - set_escape_state(call->_idx, PointsToNode::GlobalEscape); 1.777 - if (resproj != NULL) 1.778 - add_pointsto_edge(resproj->_idx, _phantom_object); 1.779 + set_escape_state(call_idx, PointsToNode::GlobalEscape); 1.780 + add_pointsto_edge(resproj_idx, _phantom_object); 1.781 } 1.782 } 1.783 - _processed.set(resproj->_idx); 1.784 + _processed.set(resproj_idx); 1.785 } 1.786 } 1.787 } 1.788 @@ -1743,7 +1761,7 @@ 1.789 1.790 // Check if a call returns an object. 1.791 const TypeTuple *r = n->as_Call()->tf()->range(); 1.792 - if (r->cnt() > TypeFunc::Parms && 1.793 + if (n->is_CallStaticJava() && r->cnt() > TypeFunc::Parms && 1.794 n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { 1.795 // Note: use isa_ptr() instead of isa_oopptr() here because 1.796 // the _multianewarray functions return a TypeRawPtr. 1.797 @@ -1776,7 +1794,7 @@ 1.798 { 1.799 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); 1.800 int ti = n->in(1)->_idx; 1.801 - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); 1.802 + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); 1.803 if (nt == PointsToNode::UnknownType) { 1.804 _delayed_worklist.push(n); // Process it later. 1.805 break; 1.806 @@ -1866,7 +1884,7 @@ 1.807 if (in->is_top() || in == n) 1.808 continue; // ignore top or inputs which go back this node 1.809 int ti = in->_idx; 1.810 - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); 1.811 + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); 1.812 if (nt == PointsToNode::UnknownType) { 1.813 break; 1.814 } else if (nt == PointsToNode::JavaObject) { 1.815 @@ -1904,7 +1922,7 @@ 1.816 // Treat Return value as LocalVar with GlobalEscape escape state. 1.817 add_node(n, PointsToNode::LocalVar, PointsToNode::GlobalEscape, false); 1.818 int ti = n->in(TypeFunc::Parms)->_idx; 1.819 - PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type(); 1.820 + PointsToNode::NodeType nt = ptnode_adr(ti)->node_type(); 1.821 if (nt == PointsToNode::UnknownType) { 1.822 _delayed_worklist.push(n); // Process it later. 1.823 break; 1.824 @@ -1968,17 +1986,17 @@ 1.825 } 1.826 1.827 void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { 1.828 + uint n_idx = n->_idx; 1.829 + 1.830 // Don't set processed bit for AddP, LoadP, StoreP since 1.831 // they may need more then one pass to process. 1.832 - if (_processed.test(n->_idx)) 1.833 + if (_processed.test(n_idx)) 1.834 return; // No need to redefine node's state. 1.835 1.836 - PointsToNode *ptadr = ptnode_adr(n->_idx); 1.837 - 1.838 if (n->is_Call()) { 1.839 CallNode *call = n->as_Call(); 1.840 process_call_arguments(call, phase); 1.841 - _processed.set(n->_idx); 1.842 + _processed.set(n_idx); 1.843 return; 1.844 } 1.845 1.846 @@ -1991,7 +2009,7 @@ 1.847 PointsTo(ptset, base, phase); 1.848 for( VectorSetI i(&ptset); i.test(); ++i ) { 1.849 uint pt = i.elem; 1.850 - add_field_edge(pt, n->_idx, address_offset(n, phase)); 1.851 + add_field_edge(pt, n_idx, address_offset(n, phase)); 1.852 } 1.853 break; 1.854 } 1.855 @@ -2006,12 +2024,12 @@ 1.856 case Op_DecodeN: 1.857 { 1.858 int ti = n->in(1)->_idx; 1.859 - if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) { 1.860 - add_pointsto_edge(n->_idx, ti); 1.861 + if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { 1.862 + add_pointsto_edge(n_idx, ti); 1.863 } else { 1.864 - add_deferred_edge(n->_idx, ti); 1.865 + add_deferred_edge(n_idx, ti); 1.866 } 1.867 - _processed.set(n->_idx); 1.868 + _processed.set(n_idx); 1.869 break; 1.870 } 1.871 case Op_ConP: 1.872 @@ -2060,7 +2078,7 @@ 1.873 int offset = address_offset(adr, phase); 1.874 for( VectorSetI i(&ptset); i.test(); ++i ) { 1.875 uint pt = i.elem; 1.876 - add_deferred_edge_to_fields(n->_idx, pt, offset); 1.877 + add_deferred_edge_to_fields(n_idx, pt, offset); 1.878 } 1.879 break; 1.880 } 1.881 @@ -2083,13 +2101,13 @@ 1.882 if (in->is_top() || in == n) 1.883 continue; // ignore top or inputs which go back this node 1.884 int ti = in->_idx; 1.885 - if (_nodes->adr_at(in->_idx)->node_type() == PointsToNode::JavaObject) { 1.886 - add_pointsto_edge(n->_idx, ti); 1.887 + if (ptnode_adr(in->_idx)->node_type() == PointsToNode::JavaObject) { 1.888 + add_pointsto_edge(n_idx, ti); 1.889 } else { 1.890 - add_deferred_edge(n->_idx, ti); 1.891 + add_deferred_edge(n_idx, ti); 1.892 } 1.893 } 1.894 - _processed.set(n->_idx); 1.895 + _processed.set(n_idx); 1.896 break; 1.897 } 1.898 case Op_Proj: 1.899 @@ -2097,7 +2115,7 @@ 1.900 // we are only interested in the result projection from a call 1.901 if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) { 1.902 process_call_result(n->as_Proj(), phase); 1.903 - assert(_processed.test(n->_idx), "all call results should be processed"); 1.904 + assert(_processed.test(n_idx), "all call results should be processed"); 1.905 } else { 1.906 assert(false, "Op_Proj"); 1.907 } 1.908 @@ -2112,12 +2130,12 @@ 1.909 } 1.910 #endif 1.911 int ti = n->in(TypeFunc::Parms)->_idx; 1.912 - if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) { 1.913 - add_pointsto_edge(n->_idx, ti); 1.914 + if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) { 1.915 + add_pointsto_edge(n_idx, ti); 1.916 } else { 1.917 - add_deferred_edge(n->_idx, ti); 1.918 + add_deferred_edge(n_idx, ti); 1.919 } 1.920 - _processed.set(n->_idx); 1.921 + _processed.set(n_idx); 1.922 break; 1.923 } 1.924 case Op_StoreP: 1.925 @@ -2162,9 +2180,9 @@ 1.926 PhaseGVN *igvn = _compile->initial_gvn(); 1.927 bool first = true; 1.928 1.929 - uint size = (uint)_nodes->length(); 1.930 + uint size = nodes_size(); 1.931 for (uint ni = 0; ni < size; ni++) { 1.932 - PointsToNode *ptn = _nodes->adr_at(ni); 1.933 + PointsToNode *ptn = ptnode_adr(ni); 1.934 PointsToNode::NodeType ptn_type = ptn->node_type(); 1.935 1.936 if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL) 1.937 @@ -2174,7 +2192,7 @@ 1.938 if (first) { 1.939 tty->cr(); 1.940 tty->print("======== Connection graph for "); 1.941 - C()->method()->print_short_name(); 1.942 + _compile->method()->print_short_name(); 1.943 tty->cr(); 1.944 first = false; 1.945 } 1.946 @@ -2182,12 +2200,12 @@ 1.947 ptn->dump(); 1.948 // Print all locals which reference this allocation 1.949 for (uint li = ni; li < size; li++) { 1.950 - PointsToNode *ptn_loc = _nodes->adr_at(li); 1.951 + PointsToNode *ptn_loc = ptnode_adr(li); 1.952 PointsToNode::NodeType ptn_loc_type = ptn_loc->node_type(); 1.953 if ( ptn_loc_type == PointsToNode::LocalVar && ptn_loc->_node != NULL && 1.954 ptn_loc->edge_count() == 1 && ptn_loc->edge_target(0) == ni ) { 1.955 tty->print("%6d LocalVar [[%d]]", li, ni); 1.956 - _nodes->adr_at(li)->_node->dump(); 1.957 + ptnode_adr(li)->_node->dump(); 1.958 } 1.959 } 1.960 if (Verbose) { 1.961 @@ -2195,7 +2213,7 @@ 1.962 for (uint i = 0; i < ptn->edge_count(); i++) { 1.963 uint ei = ptn->edge_target(i); 1.964 tty->print("%6d Field [[%d]]", ei, ni); 1.965 - _nodes->adr_at(ei)->_node->dump(); 1.966 + ptnode_adr(ei)->_node->dump(); 1.967 } 1.968 } 1.969 tty->cr();