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 } |