1.1 --- a/src/share/vm/opto/escape.cpp Mon Feb 07 09:46:01 2011 -0800 1.2 +++ b/src/share/vm/opto/escape.cpp Mon Feb 07 10:25:39 2011 -0800 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -93,6 +93,9 @@ 1.11 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : 1.12 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 1.13 _processed(C->comp_arena()), 1.14 + pt_ptset(C->comp_arena()), 1.15 + pt_visited(C->comp_arena()), 1.16 + pt_worklist(C->comp_arena(), 4, 0, 0), 1.17 _collecting(true), 1.18 _progress(false), 1.19 _compile(C), 1.20 @@ -220,9 +223,7 @@ 1.21 PointsToNode::EscapeState orig_es = es; 1.22 1.23 // compute max escape state of anything this node could point to 1.24 - VectorSet ptset(Thread::current()->resource_area()); 1.25 - PointsTo(ptset, n); 1.26 - for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) { 1.27 + for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) { 1.28 uint pt = i.elem; 1.29 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 1.30 if (pes > es) 1.31 @@ -236,9 +237,10 @@ 1.32 return es; 1.33 } 1.34 1.35 -void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { 1.36 - VectorSet visited(Thread::current()->resource_area()); 1.37 - GrowableArray<uint> worklist; 1.38 +VectorSet* ConnectionGraph::PointsTo(Node * n) { 1.39 + pt_ptset.Reset(); 1.40 + pt_visited.Reset(); 1.41 + pt_worklist.clear(); 1.42 1.43 #ifdef ASSERT 1.44 Node *orig_n = n; 1.45 @@ -249,8 +251,8 @@ 1.46 1.47 // If we have a JavaObject, return just that object 1.48 if (npt->node_type() == PointsToNode::JavaObject) { 1.49 - ptset.set(n->_idx); 1.50 - return; 1.51 + pt_ptset.set(n->_idx); 1.52 + return &pt_ptset; 1.53 } 1.54 #ifdef ASSERT 1.55 if (npt->_node == NULL) { 1.56 @@ -260,10 +262,10 @@ 1.57 assert(npt->_node != NULL, "unregistered node"); 1.58 } 1.59 #endif 1.60 - worklist.push(n->_idx); 1.61 - while(worklist.length() > 0) { 1.62 - int ni = worklist.pop(); 1.63 - if (visited.test_set(ni)) 1.64 + pt_worklist.push(n->_idx); 1.65 + while(pt_worklist.length() > 0) { 1.66 + int ni = pt_worklist.pop(); 1.67 + if (pt_visited.test_set(ni)) 1.68 continue; 1.69 1.70 PointsToNode* pn = ptnode_adr(ni); 1.71 @@ -276,10 +278,10 @@ 1.72 uint etgt = pn->edge_target(e); 1.73 PointsToNode::EdgeType et = pn->edge_type(e); 1.74 if (et == PointsToNode::PointsToEdge) { 1.75 - ptset.set(etgt); 1.76 + pt_ptset.set(etgt); 1.77 edges_processed++; 1.78 } else if (et == PointsToNode::DeferredEdge) { 1.79 - worklist.push(etgt); 1.80 + pt_worklist.push(etgt); 1.81 edges_processed++; 1.82 } else { 1.83 assert(false,"neither PointsToEdge or DeferredEdge"); 1.84 @@ -288,16 +290,17 @@ 1.85 if (edges_processed == 0) { 1.86 // no deferred or pointsto edges found. Assume the value was set 1.87 // outside this method. Add the phantom object to the pointsto set. 1.88 - ptset.set(_phantom_object); 1.89 + pt_ptset.set(_phantom_object); 1.90 } 1.91 } 1.92 + return &pt_ptset; 1.93 } 1.94 1.95 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) { 1.96 // This method is most expensive during ConnectionGraph construction. 1.97 // Reuse vectorSet and an additional growable array for deferred edges. 1.98 deferred_edges->clear(); 1.99 - visited->Clear(); 1.100 + visited->Reset(); 1.101 1.102 visited->set(ni); 1.103 PointsToNode *ptn = ptnode_adr(ni); 1.104 @@ -1009,7 +1012,6 @@ 1.105 uint new_index_start = (uint) _compile->num_alias_types(); 1.106 Arena* arena = Thread::current()->resource_area(); 1.107 VectorSet visited(arena); 1.108 - VectorSet ptset(arena); 1.109 1.110 1.111 // Phase 1: Process possible allocations from alloc_worklist. 1.112 @@ -1137,10 +1139,9 @@ 1.113 } 1.114 } 1.115 } else if (n->is_AddP()) { 1.116 - ptset.Clear(); 1.117 - PointsTo(ptset, get_addp_base(n)); 1.118 - assert(ptset.Size() == 1, "AddP address is unique"); 1.119 - uint elem = ptset.getelem(); // Allocation node's index 1.120 + VectorSet* ptset = PointsTo(get_addp_base(n)); 1.121 + assert(ptset->Size() == 1, "AddP address is unique"); 1.122 + uint elem = ptset->getelem(); // Allocation node's index 1.123 if (elem == _phantom_object) { 1.124 assert(false, "escaped allocation"); 1.125 continue; // Assume the value was set outside this method. 1.126 @@ -1157,10 +1158,9 @@ 1.127 assert(n->is_Phi(), "loops only through Phi's"); 1.128 continue; // already processed 1.129 } 1.130 - ptset.Clear(); 1.131 - PointsTo(ptset, n); 1.132 - if (ptset.Size() == 1) { 1.133 - uint elem = ptset.getelem(); // Allocation node's index 1.134 + VectorSet* ptset = PointsTo(n); 1.135 + if (ptset->Size() == 1) { 1.136 + uint elem = ptset->getelem(); // Allocation node's index 1.137 if (elem == _phantom_object) { 1.138 assert(false, "escaped allocation"); 1.139 continue; // Assume the value was set outside this method. 1.140 @@ -1434,7 +1434,7 @@ 1.141 // Update the memory inputs of MemNodes with the value we computed 1.142 // in Phase 2 and move stores memory users to corresponding memory slices. 1.143 #ifdef ASSERT 1.144 - visited.Clear(); 1.145 + visited.Reset(); 1.146 Node_Stack old_mems(arena, _compile->unique() >> 2); 1.147 #endif 1.148 for (uint i = 0; i < nodes_size(); i++) { 1.149 @@ -1640,7 +1640,6 @@ 1.150 #undef CG_BUILD_ITER_LIMIT 1.151 1.152 Arena* arena = Thread::current()->resource_area(); 1.153 - VectorSet ptset(arena); 1.154 VectorSet visited(arena); 1.155 worklist.clear(); 1.156 1.157 @@ -1657,7 +1656,7 @@ 1.158 if (n->is_AddP()) { 1.159 // Search for objects which are not scalar replaceable 1.160 // and adjust their escape state. 1.161 - verify_escape_state(ni, ptset, igvn); 1.162 + adjust_escape_state(ni, igvn); 1.163 } 1.164 } 1.165 } 1.166 @@ -1776,8 +1775,8 @@ 1.167 return has_non_escaping_obj; 1.168 } 1.169 1.170 -// Search for objects which are not scalar replaceable. 1.171 -void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { 1.172 +// Adjust escape state after Connection Graph is built. 1.173 +void ConnectionGraph::adjust_escape_state(int nidx, PhaseTransform* phase) { 1.174 PointsToNode* ptn = ptnode_adr(nidx); 1.175 Node* n = ptn->_node; 1.176 assert(n->is_AddP(), "Should be called for AddP nodes only"); 1.177 @@ -1792,9 +1791,8 @@ 1.178 1.179 int offset = ptn->offset(); 1.180 Node* base = get_addp_base(n); 1.181 - ptset.Clear(); 1.182 - PointsTo(ptset, base); 1.183 - int ptset_size = ptset.Size(); 1.184 + VectorSet* ptset = PointsTo(base); 1.185 + int ptset_size = ptset->Size(); 1.186 1.187 // Check if a oop field's initializing value is recorded and add 1.188 // a corresponding NULL field's value if it is not recorded. 1.189 @@ -1814,7 +1812,7 @@ 1.190 // Do a simple control flow analysis to distinguish above cases. 1.191 // 1.192 if (offset != Type::OffsetBot && ptset_size == 1) { 1.193 - uint elem = ptset.getelem(); // Allocation node's index 1.194 + uint elem = ptset->getelem(); // Allocation node's index 1.195 // It does not matter if it is not Allocation node since 1.196 // only non-escaping allocations are scalar replaced. 1.197 if (ptnode_adr(elem)->_node->is_Allocate() && 1.198 @@ -1913,7 +1911,7 @@ 1.199 // 1.200 if (ptset_size > 1 || ptset_size != 0 && 1.201 (has_LoadStore || offset == Type::OffsetBot)) { 1.202 - for( VectorSetI j(&ptset); j.test(); ++j ) { 1.203 + for( VectorSetI j(ptset); j.test(); ++j ) { 1.204 set_escape_state(j.elem, PointsToNode::ArgEscape); 1.205 ptnode_adr(j.elem)->_scalar_replaceable = false; 1.206 } 1.207 @@ -1937,7 +1935,6 @@ 1.208 // Stub calls, objects do not escape but they are not scale replaceable. 1.209 // Adjust escape state for outgoing arguments. 1.210 const TypeTuple * d = call->tf()->domain(); 1.211 - VectorSet ptset(Thread::current()->resource_area()); 1.212 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1.213 const Type* at = d->field_at(i); 1.214 Node *arg = call->in(i)->uncast(); 1.215 @@ -1970,9 +1967,7 @@ 1.216 // 1.217 arg = get_addp_base(arg); 1.218 } 1.219 - ptset.Clear(); 1.220 - PointsTo(ptset, arg); 1.221 - for( VectorSetI j(&ptset); j.test(); ++j ) { 1.222 + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 1.223 uint pt = j.elem; 1.224 set_escape_state(pt, PointsToNode::ArgEscape); 1.225 } 1.226 @@ -1990,7 +1985,6 @@ 1.227 // fall-through if not a Java method or no analyzer information 1.228 if (call_analyzer != NULL) { 1.229 const TypeTuple * d = call->tf()->domain(); 1.230 - VectorSet ptset(Thread::current()->resource_area()); 1.231 bool copy_dependencies = false; 1.232 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1.233 const Type* at = d->field_at(i); 1.234 @@ -2015,9 +2009,7 @@ 1.235 copy_dependencies = true; 1.236 } 1.237 1.238 - ptset.Clear(); 1.239 - PointsTo(ptset, arg); 1.240 - for( VectorSetI j(&ptset); j.test(); ++j ) { 1.241 + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 1.242 uint pt = j.elem; 1.243 if (global_escapes) { 1.244 //The argument global escapes, mark everything it could point to 1.245 @@ -2045,15 +2037,12 @@ 1.246 { 1.247 // adjust escape state for outgoing arguments 1.248 const TypeTuple * d = call->tf()->domain(); 1.249 - VectorSet ptset(Thread::current()->resource_area()); 1.250 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1.251 const Type* at = d->field_at(i); 1.252 if (at->isa_oopptr() != NULL) { 1.253 Node *arg = call->in(i)->uncast(); 1.254 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 1.255 - ptset.Clear(); 1.256 - PointsTo(ptset, arg); 1.257 - for( VectorSetI j(&ptset); j.test(); ++j ) { 1.258 + for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 1.259 uint pt = j.elem; 1.260 set_escape_state(pt, PointsToNode::GlobalEscape); 1.261 } 1.262 @@ -2515,9 +2504,7 @@ 1.263 { 1.264 Node *base = get_addp_base(n); 1.265 // Create a field edge to this node from everything base could point to. 1.266 - VectorSet ptset(Thread::current()->resource_area()); 1.267 - PointsTo(ptset, base); 1.268 - for( VectorSetI i(&ptset); i.test(); ++i ) { 1.269 + for( VectorSetI i(PointsTo(base)); i.test(); ++i ) { 1.270 uint pt = i.elem; 1.271 add_field_edge(pt, n_idx, address_offset(n, phase)); 1.272 } 1.273 @@ -2583,10 +2570,8 @@ 1.274 1.275 // For everything "adr_base" could point to, create a deferred edge from 1.276 // this node to each field with the same offset. 1.277 - VectorSet ptset(Thread::current()->resource_area()); 1.278 - PointsTo(ptset, adr_base); 1.279 int offset = address_offset(adr, phase); 1.280 - for( VectorSetI i(&ptset); i.test(); ++i ) { 1.281 + for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { 1.282 uint pt = i.elem; 1.283 add_deferred_edge_to_fields(n_idx, pt, offset); 1.284 } 1.285 @@ -2676,9 +2661,7 @@ 1.286 Node *val = n->in(MemNode::ValueIn)->uncast(); 1.287 // For everything "adr_base" could point to, create a deferred edge 1.288 // to "val" from each field with the same offset. 1.289 - VectorSet ptset(Thread::current()->resource_area()); 1.290 - PointsTo(ptset, adr_base); 1.291 - for( VectorSetI i(&ptset); i.test(); ++i ) { 1.292 + for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) { 1.293 uint pt = i.elem; 1.294 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 1.295 }