src/share/vm/opto/escape.cpp

changeset 2556
3763ca6579b7
parent 2409
a21ff35351ec
child 2741
55973726c600
equal deleted inserted replaced
2555:194c9fdee631 2556:3763ca6579b7
1 /* 1 /*
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
91 #endif 91 #endif
92 92
93 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : 93 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
94 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()), 94 _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
95 _processed(C->comp_arena()), 95 _processed(C->comp_arena()),
96 pt_ptset(C->comp_arena()),
97 pt_visited(C->comp_arena()),
98 pt_worklist(C->comp_arena(), 4, 0, 0),
96 _collecting(true), 99 _collecting(true),
97 _progress(false), 100 _progress(false),
98 _compile(C), 101 _compile(C),
99 _igvn(igvn), 102 _igvn(igvn),
100 _node_map(C->comp_arena()) { 103 _node_map(C->comp_arena()) {
218 return PointsToNode::UnknownEscape; 221 return PointsToNode::UnknownEscape;
219 222
220 PointsToNode::EscapeState orig_es = es; 223 PointsToNode::EscapeState orig_es = es;
221 224
222 // compute max escape state of anything this node could point to 225 // compute max escape state of anything this node could point to
223 VectorSet ptset(Thread::current()->resource_area()); 226 for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) {
224 PointsTo(ptset, n);
225 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
226 uint pt = i.elem; 227 uint pt = i.elem;
227 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state(); 228 PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
228 if (pes > es) 229 if (pes > es)
229 es = pes; 230 es = pes;
230 } 231 }
234 ptnode_adr(idx)->set_escape_state(es); 235 ptnode_adr(idx)->set_escape_state(es);
235 } // orig_es could be PointsToNode::UnknownEscape 236 } // orig_es could be PointsToNode::UnknownEscape
236 return es; 237 return es;
237 } 238 }
238 239
239 void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) { 240 VectorSet* ConnectionGraph::PointsTo(Node * n) {
240 VectorSet visited(Thread::current()->resource_area()); 241 pt_ptset.Reset();
241 GrowableArray<uint> worklist; 242 pt_visited.Reset();
243 pt_worklist.clear();
242 244
243 #ifdef ASSERT 245 #ifdef ASSERT
244 Node *orig_n = n; 246 Node *orig_n = n;
245 #endif 247 #endif
246 248
247 n = n->uncast(); 249 n = n->uncast();
248 PointsToNode* npt = ptnode_adr(n->_idx); 250 PointsToNode* npt = ptnode_adr(n->_idx);
249 251
250 // If we have a JavaObject, return just that object 252 // If we have a JavaObject, return just that object
251 if (npt->node_type() == PointsToNode::JavaObject) { 253 if (npt->node_type() == PointsToNode::JavaObject) {
252 ptset.set(n->_idx); 254 pt_ptset.set(n->_idx);
253 return; 255 return &pt_ptset;
254 } 256 }
255 #ifdef ASSERT 257 #ifdef ASSERT
256 if (npt->_node == NULL) { 258 if (npt->_node == NULL) {
257 if (orig_n != n) 259 if (orig_n != n)
258 orig_n->dump(); 260 orig_n->dump();
259 n->dump(); 261 n->dump();
260 assert(npt->_node != NULL, "unregistered node"); 262 assert(npt->_node != NULL, "unregistered node");
261 } 263 }
262 #endif 264 #endif
263 worklist.push(n->_idx); 265 pt_worklist.push(n->_idx);
264 while(worklist.length() > 0) { 266 while(pt_worklist.length() > 0) {
265 int ni = worklist.pop(); 267 int ni = pt_worklist.pop();
266 if (visited.test_set(ni)) 268 if (pt_visited.test_set(ni))
267 continue; 269 continue;
268 270
269 PointsToNode* pn = ptnode_adr(ni); 271 PointsToNode* pn = ptnode_adr(ni);
270 // ensure that all inputs of a Phi have been processed 272 // ensure that all inputs of a Phi have been processed
271 assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),""); 273 assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),"");
274 uint e_cnt = pn->edge_count(); 276 uint e_cnt = pn->edge_count();
275 for (uint e = 0; e < e_cnt; e++) { 277 for (uint e = 0; e < e_cnt; e++) {
276 uint etgt = pn->edge_target(e); 278 uint etgt = pn->edge_target(e);
277 PointsToNode::EdgeType et = pn->edge_type(e); 279 PointsToNode::EdgeType et = pn->edge_type(e);
278 if (et == PointsToNode::PointsToEdge) { 280 if (et == PointsToNode::PointsToEdge) {
279 ptset.set(etgt); 281 pt_ptset.set(etgt);
280 edges_processed++; 282 edges_processed++;
281 } else if (et == PointsToNode::DeferredEdge) { 283 } else if (et == PointsToNode::DeferredEdge) {
282 worklist.push(etgt); 284 pt_worklist.push(etgt);
283 edges_processed++; 285 edges_processed++;
284 } else { 286 } else {
285 assert(false,"neither PointsToEdge or DeferredEdge"); 287 assert(false,"neither PointsToEdge or DeferredEdge");
286 } 288 }
287 } 289 }
288 if (edges_processed == 0) { 290 if (edges_processed == 0) {
289 // no deferred or pointsto edges found. Assume the value was set 291 // no deferred or pointsto edges found. Assume the value was set
290 // outside this method. Add the phantom object to the pointsto set. 292 // outside this method. Add the phantom object to the pointsto set.
291 ptset.set(_phantom_object); 293 pt_ptset.set(_phantom_object);
292 } 294 }
293 } 295 }
296 return &pt_ptset;
294 } 297 }
295 298
296 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) { 299 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
297 // This method is most expensive during ConnectionGraph construction. 300 // This method is most expensive during ConnectionGraph construction.
298 // Reuse vectorSet and an additional growable array for deferred edges. 301 // Reuse vectorSet and an additional growable array for deferred edges.
299 deferred_edges->clear(); 302 deferred_edges->clear();
300 visited->Clear(); 303 visited->Reset();
301 304
302 visited->set(ni); 305 visited->set(ni);
303 PointsToNode *ptn = ptnode_adr(ni); 306 PointsToNode *ptn = ptnode_adr(ni);
304 307
305 // Mark current edges as visited and move deferred edges to separate array. 308 // Mark current edges as visited and move deferred edges to separate array.
1007 1010
1008 PhaseIterGVN *igvn = _igvn; 1011 PhaseIterGVN *igvn = _igvn;
1009 uint new_index_start = (uint) _compile->num_alias_types(); 1012 uint new_index_start = (uint) _compile->num_alias_types();
1010 Arena* arena = Thread::current()->resource_area(); 1013 Arena* arena = Thread::current()->resource_area();
1011 VectorSet visited(arena); 1014 VectorSet visited(arena);
1012 VectorSet ptset(arena);
1013 1015
1014 1016
1015 // Phase 1: Process possible allocations from alloc_worklist. 1017 // Phase 1: Process possible allocations from alloc_worklist.
1016 // Create instance types for the CheckCastPP for allocations where possible. 1018 // Create instance types for the CheckCastPP for allocations where possible.
1017 // 1019 //
1135 memnode_worklist.append_if_missing(use); 1137 memnode_worklist.append_if_missing(use);
1136 } 1138 }
1137 } 1139 }
1138 } 1140 }
1139 } else if (n->is_AddP()) { 1141 } else if (n->is_AddP()) {
1140 ptset.Clear(); 1142 VectorSet* ptset = PointsTo(get_addp_base(n));
1141 PointsTo(ptset, get_addp_base(n)); 1143 assert(ptset->Size() == 1, "AddP address is unique");
1142 assert(ptset.Size() == 1, "AddP address is unique"); 1144 uint elem = ptset->getelem(); // Allocation node's index
1143 uint elem = ptset.getelem(); // Allocation node's index
1144 if (elem == _phantom_object) { 1145 if (elem == _phantom_object) {
1145 assert(false, "escaped allocation"); 1146 assert(false, "escaped allocation");
1146 continue; // Assume the value was set outside this method. 1147 continue; // Assume the value was set outside this method.
1147 } 1148 }
1148 Node *base = get_map(elem); // CheckCastPP node 1149 Node *base = get_map(elem); // CheckCastPP node
1155 (n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) { 1156 (n->is_ConstraintCast() && n->Opcode() == Op_CastPP)) {
1156 if (visited.test_set(n->_idx)) { 1157 if (visited.test_set(n->_idx)) {
1157 assert(n->is_Phi(), "loops only through Phi's"); 1158 assert(n->is_Phi(), "loops only through Phi's");
1158 continue; // already processed 1159 continue; // already processed
1159 } 1160 }
1160 ptset.Clear(); 1161 VectorSet* ptset = PointsTo(n);
1161 PointsTo(ptset, n); 1162 if (ptset->Size() == 1) {
1162 if (ptset.Size() == 1) { 1163 uint elem = ptset->getelem(); // Allocation node's index
1163 uint elem = ptset.getelem(); // Allocation node's index
1164 if (elem == _phantom_object) { 1164 if (elem == _phantom_object) {
1165 assert(false, "escaped allocation"); 1165 assert(false, "escaped allocation");
1166 continue; // Assume the value was set outside this method. 1166 continue; // Assume the value was set outside this method.
1167 } 1167 }
1168 Node *val = get_map(elem); // CheckCastPP node 1168 Node *val = get_map(elem); // CheckCastPP node
1432 } 1432 }
1433 1433
1434 // Update the memory inputs of MemNodes with the value we computed 1434 // Update the memory inputs of MemNodes with the value we computed
1435 // in Phase 2 and move stores memory users to corresponding memory slices. 1435 // in Phase 2 and move stores memory users to corresponding memory slices.
1436 #ifdef ASSERT 1436 #ifdef ASSERT
1437 visited.Clear(); 1437 visited.Reset();
1438 Node_Stack old_mems(arena, _compile->unique() >> 2); 1438 Node_Stack old_mems(arena, _compile->unique() >> 2);
1439 #endif 1439 #endif
1440 for (uint i = 0; i < nodes_size(); i++) { 1440 for (uint i = 0; i < nodes_size(); i++) {
1441 Node *nmem = get_map(i); 1441 Node *nmem = get_map(i);
1442 if (nmem != NULL) { 1442 if (nmem != NULL) {
1638 return false; 1638 return false;
1639 } 1639 }
1640 #undef CG_BUILD_ITER_LIMIT 1640 #undef CG_BUILD_ITER_LIMIT
1641 1641
1642 Arena* arena = Thread::current()->resource_area(); 1642 Arena* arena = Thread::current()->resource_area();
1643 VectorSet ptset(arena);
1644 VectorSet visited(arena); 1643 VectorSet visited(arena);
1645 worklist.clear(); 1644 worklist.clear();
1646 1645
1647 // 5. Remove deferred edges from the graph and adjust 1646 // 5. Remove deferred edges from the graph and adjust
1648 // escape state of nonescaping objects. 1647 // escape state of nonescaping objects.
1655 remove_deferred(ni, &worklist, &visited); 1654 remove_deferred(ni, &worklist, &visited);
1656 Node *n = ptn->_node; 1655 Node *n = ptn->_node;
1657 if (n->is_AddP()) { 1656 if (n->is_AddP()) {
1658 // Search for objects which are not scalar replaceable 1657 // Search for objects which are not scalar replaceable
1659 // and adjust their escape state. 1658 // and adjust their escape state.
1660 verify_escape_state(ni, ptset, igvn); 1659 adjust_escape_state(ni, igvn);
1661 } 1660 }
1662 } 1661 }
1663 } 1662 }
1664 1663
1665 // 6. Propagate escape states. 1664 // 6. Propagate escape states.
1774 #endif 1773 #endif
1775 } 1774 }
1776 return has_non_escaping_obj; 1775 return has_non_escaping_obj;
1777 } 1776 }
1778 1777
1779 // Search for objects which are not scalar replaceable. 1778 // Adjust escape state after Connection Graph is built.
1780 void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase) { 1779 void ConnectionGraph::adjust_escape_state(int nidx, PhaseTransform* phase) {
1781 PointsToNode* ptn = ptnode_adr(nidx); 1780 PointsToNode* ptn = ptnode_adr(nidx);
1782 Node* n = ptn->_node; 1781 Node* n = ptn->_node;
1783 assert(n->is_AddP(), "Should be called for AddP nodes only"); 1782 assert(n->is_AddP(), "Should be called for AddP nodes only");
1784 // Search for objects which are not scalar replaceable. 1783 // Search for objects which are not scalar replaceable.
1785 // Mark their escape state as ArgEscape to propagate the state 1784 // Mark their escape state as ArgEscape to propagate the state
1790 1789
1791 Compile* C = _compile; 1790 Compile* C = _compile;
1792 1791
1793 int offset = ptn->offset(); 1792 int offset = ptn->offset();
1794 Node* base = get_addp_base(n); 1793 Node* base = get_addp_base(n);
1795 ptset.Clear(); 1794 VectorSet* ptset = PointsTo(base);
1796 PointsTo(ptset, base); 1795 int ptset_size = ptset->Size();
1797 int ptset_size = ptset.Size();
1798 1796
1799 // Check if a oop field's initializing value is recorded and add 1797 // Check if a oop field's initializing value is recorded and add
1800 // a corresponding NULL field's value if it is not recorded. 1798 // a corresponding NULL field's value if it is not recorded.
1801 // Connection Graph does not record a default initialization by NULL 1799 // Connection Graph does not record a default initialization by NULL
1802 // captured by Initialize node. 1800 // captured by Initialize node.
1812 // if ( x ) p[0] = new Point(); // Will be not scalar replaced 1810 // if ( x ) p[0] = new Point(); // Will be not scalar replaced
1813 // 1811 //
1814 // Do a simple control flow analysis to distinguish above cases. 1812 // Do a simple control flow analysis to distinguish above cases.
1815 // 1813 //
1816 if (offset != Type::OffsetBot && ptset_size == 1) { 1814 if (offset != Type::OffsetBot && ptset_size == 1) {
1817 uint elem = ptset.getelem(); // Allocation node's index 1815 uint elem = ptset->getelem(); // Allocation node's index
1818 // It does not matter if it is not Allocation node since 1816 // It does not matter if it is not Allocation node since
1819 // only non-escaping allocations are scalar replaced. 1817 // only non-escaping allocations are scalar replaced.
1820 if (ptnode_adr(elem)->_node->is_Allocate() && 1818 if (ptnode_adr(elem)->_node->is_Allocate() &&
1821 ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) { 1819 ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) {
1822 AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate(); 1820 AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate();
1911 // the case when stores overwrite the field's value from the case 1909 // the case when stores overwrite the field's value from the case
1912 // when stores happened on different control branches. 1910 // when stores happened on different control branches.
1913 // 1911 //
1914 if (ptset_size > 1 || ptset_size != 0 && 1912 if (ptset_size > 1 || ptset_size != 0 &&
1915 (has_LoadStore || offset == Type::OffsetBot)) { 1913 (has_LoadStore || offset == Type::OffsetBot)) {
1916 for( VectorSetI j(&ptset); j.test(); ++j ) { 1914 for( VectorSetI j(ptset); j.test(); ++j ) {
1917 set_escape_state(j.elem, PointsToNode::ArgEscape); 1915 set_escape_state(j.elem, PointsToNode::ArgEscape);
1918 ptnode_adr(j.elem)->_scalar_replaceable = false; 1916 ptnode_adr(j.elem)->_scalar_replaceable = false;
1919 } 1917 }
1920 } 1918 }
1921 } 1919 }
1935 case Op_CallLeafNoFP: 1933 case Op_CallLeafNoFP:
1936 { 1934 {
1937 // Stub calls, objects do not escape but they are not scale replaceable. 1935 // Stub calls, objects do not escape but they are not scale replaceable.
1938 // Adjust escape state for outgoing arguments. 1936 // Adjust escape state for outgoing arguments.
1939 const TypeTuple * d = call->tf()->domain(); 1937 const TypeTuple * d = call->tf()->domain();
1940 VectorSet ptset(Thread::current()->resource_area());
1941 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1938 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
1942 const Type* at = d->field_at(i); 1939 const Type* at = d->field_at(i);
1943 Node *arg = call->in(i)->uncast(); 1940 Node *arg = call->in(i)->uncast();
1944 const Type *aat = phase->type(arg); 1941 const Type *aat = phase->type(arg);
1945 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && 1942 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
1968 // Set AddP's base (Allocate) as not scalar replaceable since 1965 // Set AddP's base (Allocate) as not scalar replaceable since
1969 // pointer to the base (with offset) is passed as argument. 1966 // pointer to the base (with offset) is passed as argument.
1970 // 1967 //
1971 arg = get_addp_base(arg); 1968 arg = get_addp_base(arg);
1972 } 1969 }
1973 ptset.Clear(); 1970 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
1974 PointsTo(ptset, arg);
1975 for( VectorSetI j(&ptset); j.test(); ++j ) {
1976 uint pt = j.elem; 1971 uint pt = j.elem;
1977 set_escape_state(pt, PointsToNode::ArgEscape); 1972 set_escape_state(pt, PointsToNode::ArgEscape);
1978 } 1973 }
1979 } 1974 }
1980 } 1975 }
1988 ciMethod *meth = call->as_CallJava()->method(); 1983 ciMethod *meth = call->as_CallJava()->method();
1989 BCEscapeAnalyzer *call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL; 1984 BCEscapeAnalyzer *call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
1990 // fall-through if not a Java method or no analyzer information 1985 // fall-through if not a Java method or no analyzer information
1991 if (call_analyzer != NULL) { 1986 if (call_analyzer != NULL) {
1992 const TypeTuple * d = call->tf()->domain(); 1987 const TypeTuple * d = call->tf()->domain();
1993 VectorSet ptset(Thread::current()->resource_area());
1994 bool copy_dependencies = false; 1988 bool copy_dependencies = false;
1995 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 1989 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
1996 const Type* at = d->field_at(i); 1990 const Type* at = d->field_at(i);
1997 int k = i - TypeFunc::Parms; 1991 int k = i - TypeFunc::Parms;
1998 Node *arg = call->in(i)->uncast(); 1992 Node *arg = call->in(i)->uncast();
2013 } 2007 }
2014 set_escape_state(arg->_idx, PointsToNode::ArgEscape); 2008 set_escape_state(arg->_idx, PointsToNode::ArgEscape);
2015 copy_dependencies = true; 2009 copy_dependencies = true;
2016 } 2010 }
2017 2011
2018 ptset.Clear(); 2012 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
2019 PointsTo(ptset, arg);
2020 for( VectorSetI j(&ptset); j.test(); ++j ) {
2021 uint pt = j.elem; 2013 uint pt = j.elem;
2022 if (global_escapes) { 2014 if (global_escapes) {
2023 //The argument global escapes, mark everything it could point to 2015 //The argument global escapes, mark everything it could point to
2024 set_escape_state(pt, PointsToNode::GlobalEscape); 2016 set_escape_state(pt, PointsToNode::GlobalEscape);
2025 } else { 2017 } else {
2043 // or some other type of call, assume the worst case: all arguments 2035 // or some other type of call, assume the worst case: all arguments
2044 // globally escape. 2036 // globally escape.
2045 { 2037 {
2046 // adjust escape state for outgoing arguments 2038 // adjust escape state for outgoing arguments
2047 const TypeTuple * d = call->tf()->domain(); 2039 const TypeTuple * d = call->tf()->domain();
2048 VectorSet ptset(Thread::current()->resource_area());
2049 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 2040 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
2050 const Type* at = d->field_at(i); 2041 const Type* at = d->field_at(i);
2051 if (at->isa_oopptr() != NULL) { 2042 if (at->isa_oopptr() != NULL) {
2052 Node *arg = call->in(i)->uncast(); 2043 Node *arg = call->in(i)->uncast();
2053 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 2044 set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
2054 ptset.Clear(); 2045 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
2055 PointsTo(ptset, arg);
2056 for( VectorSetI j(&ptset); j.test(); ++j ) {
2057 uint pt = j.elem; 2046 uint pt = j.elem;
2058 set_escape_state(pt, PointsToNode::GlobalEscape); 2047 set_escape_state(pt, PointsToNode::GlobalEscape);
2059 } 2048 }
2060 } 2049 }
2061 } 2050 }
2513 switch (n->Opcode()) { 2502 switch (n->Opcode()) {
2514 case Op_AddP: 2503 case Op_AddP:
2515 { 2504 {
2516 Node *base = get_addp_base(n); 2505 Node *base = get_addp_base(n);
2517 // Create a field edge to this node from everything base could point to. 2506 // Create a field edge to this node from everything base could point to.
2518 VectorSet ptset(Thread::current()->resource_area()); 2507 for( VectorSetI i(PointsTo(base)); i.test(); ++i ) {
2519 PointsTo(ptset, base);
2520 for( VectorSetI i(&ptset); i.test(); ++i ) {
2521 uint pt = i.elem; 2508 uint pt = i.elem;
2522 add_field_edge(pt, n_idx, address_offset(n, phase)); 2509 add_field_edge(pt, n_idx, address_offset(n, phase));
2523 } 2510 }
2524 break; 2511 break;
2525 } 2512 }
2581 adr_base = adr; 2568 adr_base = adr;
2582 } 2569 }
2583 2570
2584 // For everything "adr_base" could point to, create a deferred edge from 2571 // For everything "adr_base" could point to, create a deferred edge from
2585 // this node to each field with the same offset. 2572 // this node to each field with the same offset.
2586 VectorSet ptset(Thread::current()->resource_area());
2587 PointsTo(ptset, adr_base);
2588 int offset = address_offset(adr, phase); 2573 int offset = address_offset(adr, phase);
2589 for( VectorSetI i(&ptset); i.test(); ++i ) { 2574 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
2590 uint pt = i.elem; 2575 uint pt = i.elem;
2591 add_deferred_edge_to_fields(n_idx, pt, offset); 2576 add_deferred_edge_to_fields(n_idx, pt, offset);
2592 } 2577 }
2593 break; 2578 break;
2594 } 2579 }
2674 assert(adr->is_AddP(), "expecting an AddP"); 2659 assert(adr->is_AddP(), "expecting an AddP");
2675 Node *adr_base = get_addp_base(adr); 2660 Node *adr_base = get_addp_base(adr);
2676 Node *val = n->in(MemNode::ValueIn)->uncast(); 2661 Node *val = n->in(MemNode::ValueIn)->uncast();
2677 // For everything "adr_base" could point to, create a deferred edge 2662 // For everything "adr_base" could point to, create a deferred edge
2678 // to "val" from each field with the same offset. 2663 // to "val" from each field with the same offset.
2679 VectorSet ptset(Thread::current()->resource_area()); 2664 for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
2680 PointsTo(ptset, adr_base);
2681 for( VectorSetI i(&ptset); i.test(); ++i ) {
2682 uint pt = i.elem; 2665 uint pt = i.elem;
2683 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase)); 2666 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
2684 } 2667 }
2685 break; 2668 break;
2686 } 2669 }

mercurial