198
199 // compute max escape state of anything this node could point to
200 VectorSet ptset(Thread::current()->resource_area());
201 PointsTo(ptset, n, phase);
202 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
203 uint pt = i.elem;
204 PointsToNode::EscapeState pes = _nodes->adr_at(pt)->escape_state();
205 if (pes > es)
206 es = pes;
207 }
208 // cache the computed escape state
209 assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
210 _nodes->adr_at(idx)->set_escape_state(es);
211 return es;
212 }
213
214 void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
215 VectorSet visited(Thread::current()->resource_area());
216 GrowableArray<uint> worklist;
217
218 n = n->uncast();
219 PointsToNode npt = _nodes->at_grow(n->_idx);
220
221 // If we have a JavaObject, return just that object
222 if (npt.node_type() == PointsToNode::JavaObject) {
223 ptset.set(n->_idx);
224 return;
225 }
226 assert(npt._node != NULL, "unregistered node");
227
228 worklist.push(n->_idx);
229 while(worklist.length() > 0) {
230 int ni = worklist.pop();
231 PointsToNode pn = _nodes->at_grow(ni);
232 if (!visited.test_set(ni)) {
233 // ensure that all inputs of a Phi have been processed
234 assert(!_collecting || !pn._node->is_Phi() || _processed.test(ni),"");
235
236 int edges_processed = 0;
237 for (uint e = 0; e < pn.edge_count(); e++) {
238 uint etgt = pn.edge_target(e);
239 PointsToNode::EdgeType et = pn.edge_type(e);
240 if (et == PointsToNode::PointsToEdge) {
241 ptset.set(etgt);
242 edges_processed++;
243 } else if (et == PointsToNode::DeferredEdge) {
244 worklist.push(etgt);
245 edges_processed++;
246 } else {
247 assert(false,"neither PointsToEdge or DeferredEdge");
249 }
250 if (edges_processed == 0) {
251 // no deferred or pointsto edges found. Assume the value was set
252 // outside this method. Add the phantom object to the pointsto set.
253 ptset.set(_phantom_object);
254 }
255 }
256 }
257 }
258
259 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
260 // This method is most expensive during ConnectionGraph construction.
261 // Reuse vectorSet and an additional growable array for deferred edges.
262 deferred_edges->clear();
263 visited->Clear();
264
265 uint i = 0;
266 PointsToNode *ptn = ptnode_adr(ni);
267
268 // Mark current edges as visited and move deferred edges to separate array.
269 for (; i < ptn->edge_count(); i++) {
270 uint t = ptn->edge_target(i);
271 #ifdef ASSERT
272 assert(!visited->test_set(t), "expecting no duplications");
273 #else
274 visited->set(t);
275 #endif
276 if (ptn->edge_type(i) == PointsToNode::DeferredEdge) {
277 ptn->remove_edge(t, PointsToNode::DeferredEdge);
278 deferred_edges->append(t);
279 }
280 }
281 for (int next = 0; next < deferred_edges->length(); ++next) {
282 uint t = deferred_edges->at(next);
283 PointsToNode *ptt = ptnode_adr(t);
284 for (uint j = 0; j < ptt->edge_count(); j++) {
285 uint n1 = ptt->edge_target(j);
286 if (visited->test_set(n1))
287 continue;
288 switch(ptt->edge_type(j)) {
289 case PointsToNode::PointsToEdge:
290 add_pointsto_edge(ni, n1);
291 if(n1 == _phantom_object) {
292 // Special case - field set outside (globally escaping).
293 ptn->set_escape_state(PointsToNode::GlobalEscape);
294 }
295 break;
296 case PointsToNode::DeferredEdge:
297 deferred_edges->append(n1);
298 break;
1699 add_node(n, nt, PointsToNode::UnknownEscape, false);
1700 }
1701 return;
1702 }
1703
1704 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
1705 // ThreadLocal has RawPrt type.
1706 switch (n->Opcode()) {
1707 case Op_AddP:
1708 {
1709 add_node(n, PointsToNode::Field, PointsToNode::UnknownEscape, false);
1710 break;
1711 }
1712 case Op_CastX2P:
1713 { // "Unsafe" memory access.
1714 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1715 break;
1716 }
1717 case Op_CastPP:
1718 case Op_CheckCastPP:
1719 {
1720 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
1721 int ti = n->in(1)->_idx;
1722 PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type();
1723 if (nt == PointsToNode::UnknownType) {
1724 _delayed_worklist.push(n); // Process it later.
1725 break;
1726 } else if (nt == PointsToNode::JavaObject) {
1727 add_pointsto_edge(n->_idx, ti);
1728 } else {
1729 add_deferred_edge(n->_idx, ti);
1730 }
1731 _processed.set(n->_idx);
1732 break;
1733 }
1734 case Op_ConP:
1735 {
1736 // assume all pointer constants globally escape except for null
1737 PointsToNode::EscapeState es;
1738 if (phase->type(n) == TypePtr::NULL_PTR)
1739 es = PointsToNode::NoEscape;
1740 else
1741 es = PointsToNode::GlobalEscape;
1742
1743 add_node(n, PointsToNode::JavaObject, es, true);
1744 break;
1745 }
1746 case Op_CreateEx:
1747 {
1748 // assume that all exception objects globally escape
1749 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1750 break;
1751 }
1752 case Op_ConN:
1753 {
1754 // assume all narrow oop constants globally escape except for null
1755 PointsToNode::EscapeState es;
1756 if (phase->type(n) == TypeNarrowOop::NULL_PTR)
1757 es = PointsToNode::NoEscape;
1758 else
1759 es = PointsToNode::GlobalEscape;
1760
1761 add_node(n, PointsToNode::JavaObject, es, true);
1762 break;
1763 }
1764 case Op_LoadKlass:
1765 {
1766 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1767 break;
1768 }
1769 case Op_LoadP:
1770 case Op_LoadN:
1771 {
1772 const Type *t = phase->type(n);
1773 if (!t->isa_narrowoop() && t->isa_ptr() == NULL) {
1774 _processed.set(n->_idx);
1775 return;
1776 }
1777 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
1778 break;
1779 }
1780 case Op_Parm:
1781 {
1782 _processed.set(n->_idx); // No need to redefine it state.
1783 uint con = n->as_Proj()->_con;
1959 }
1960 _processed.set(n->_idx);
1961 break;
1962 }
1963 case Op_ConP:
1964 {
1965 assert(false, "Op_ConP");
1966 break;
1967 }
1968 case Op_CreateEx:
1969 {
1970 assert(false, "Op_CreateEx");
1971 break;
1972 }
1973 case Op_LoadKlass:
1974 {
1975 assert(false, "Op_LoadKlass");
1976 break;
1977 }
1978 case Op_LoadP:
1979 {
1980 const Type *t = phase->type(n);
1981 #ifdef ASSERT
1982 if (t->isa_ptr() == NULL)
1983 assert(false, "Op_LoadP");
1984 #endif
1985
1986 Node* adr = n->in(MemNode::Address)->uncast();
1987 const Type *adr_type = phase->type(adr);
1988 Node* adr_base;
1989 if (adr->is_AddP()) {
1990 adr_base = get_addp_base(adr);
1991 } else {
1992 adr_base = adr;
1993 }
1994
1995 // For everything "adr_base" could point to, create a deferred edge from
1996 // this node to each field with the same offset.
1997 VectorSet ptset(Thread::current()->resource_area());
1998 PointsTo(ptset, adr_base, phase);
1999 int offset = address_offset(adr, phase);
2000 for( VectorSetI i(&ptset); i.test(); ++i ) {
2001 uint pt = i.elem;
2002 add_deferred_edge_to_fields(n->_idx, pt, offset);
2043 break;
2044 }
2045 case Op_Return:
2046 {
2047 #ifdef ASSERT
2048 if( n->req() <= TypeFunc::Parms ||
2049 !phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
2050 assert(false, "Op_Return");
2051 }
2052 #endif
2053 int ti = n->in(TypeFunc::Parms)->_idx;
2054 if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) {
2055 add_pointsto_edge(n->_idx, ti);
2056 } else {
2057 add_deferred_edge(n->_idx, ti);
2058 }
2059 _processed.set(n->_idx);
2060 break;
2061 }
2062 case Op_StoreP:
2063 case Op_StorePConditional:
2064 case Op_CompareAndSwapP:
2065 {
2066 Node *adr = n->in(MemNode::Address);
2067 const Type *adr_type = phase->type(adr);
2068 #ifdef ASSERT
2069 if (!adr_type->isa_oopptr())
2070 assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP");
2071 #endif
2072
2073 assert(adr->is_AddP(), "expecting an AddP");
2074 Node *adr_base = get_addp_base(adr);
2075 Node *val = n->in(MemNode::ValueIn)->uncast();
2076 // For everything "adr_base" could point to, create a deferred edge
2077 // to "val" from each field with the same offset.
2078 VectorSet ptset(Thread::current()->resource_area());
2079 PointsTo(ptset, adr_base, phase);
2080 for( VectorSetI i(&ptset); i.test(); ++i ) {
2081 uint pt = i.elem;
2082 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
2083 }
2084 break;
2085 }
2086 case Op_ThreadLocal:
2087 {
|
198
199 // compute max escape state of anything this node could point to
200 VectorSet ptset(Thread::current()->resource_area());
201 PointsTo(ptset, n, phase);
202 for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
203 uint pt = i.elem;
204 PointsToNode::EscapeState pes = _nodes->adr_at(pt)->escape_state();
205 if (pes > es)
206 es = pes;
207 }
208 // cache the computed escape state
209 assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
210 _nodes->adr_at(idx)->set_escape_state(es);
211 return es;
212 }
213
214 void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
215 VectorSet visited(Thread::current()->resource_area());
216 GrowableArray<uint> worklist;
217
218 #ifdef ASSERT
219 Node *orig_n = n;
220 #endif
221
222 n = n->uncast();
223 PointsToNode npt = _nodes->at_grow(n->_idx);
224
225 // If we have a JavaObject, return just that object
226 if (npt.node_type() == PointsToNode::JavaObject) {
227 ptset.set(n->_idx);
228 return;
229 }
230 #ifdef ASSERT
231 if (npt._node == NULL) {
232 if (orig_n != n)
233 orig_n->dump();
234 n->dump();
235 assert(npt._node != NULL, "unregistered node");
236 }
237 #endif
238 worklist.push(n->_idx);
239 while(worklist.length() > 0) {
240 int ni = worklist.pop();
241 PointsToNode pn = _nodes->at_grow(ni);
242 if (!visited.test_set(ni)) {
243 // ensure that all inputs of a Phi have been processed
244 assert(!_collecting || !pn._node->is_Phi() || _processed.test(ni),"");
245
246 int edges_processed = 0;
247 for (uint e = 0; e < pn.edge_count(); e++) {
248 uint etgt = pn.edge_target(e);
249 PointsToNode::EdgeType et = pn.edge_type(e);
250 if (et == PointsToNode::PointsToEdge) {
251 ptset.set(etgt);
252 edges_processed++;
253 } else if (et == PointsToNode::DeferredEdge) {
254 worklist.push(etgt);
255 edges_processed++;
256 } else {
257 assert(false,"neither PointsToEdge or DeferredEdge");
259 }
260 if (edges_processed == 0) {
261 // no deferred or pointsto edges found. Assume the value was set
262 // outside this method. Add the phantom object to the pointsto set.
263 ptset.set(_phantom_object);
264 }
265 }
266 }
267 }
268
269 void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
270 // This method is most expensive during ConnectionGraph construction.
271 // Reuse vectorSet and an additional growable array for deferred edges.
272 deferred_edges->clear();
273 visited->Clear();
274
275 uint i = 0;
276 PointsToNode *ptn = ptnode_adr(ni);
277
278 // Mark current edges as visited and move deferred edges to separate array.
279 while (i < ptn->edge_count()) {
280 uint t = ptn->edge_target(i);
281 #ifdef ASSERT
282 assert(!visited->test_set(t), "expecting no duplications");
283 #else
284 visited->set(t);
285 #endif
286 if (ptn->edge_type(i) == PointsToNode::DeferredEdge) {
287 ptn->remove_edge(t, PointsToNode::DeferredEdge);
288 deferred_edges->append(t);
289 } else {
290 i++;
291 }
292 }
293 for (int next = 0; next < deferred_edges->length(); ++next) {
294 uint t = deferred_edges->at(next);
295 PointsToNode *ptt = ptnode_adr(t);
296 for (uint j = 0; j < ptt->edge_count(); j++) {
297 uint n1 = ptt->edge_target(j);
298 if (visited->test_set(n1))
299 continue;
300 switch(ptt->edge_type(j)) {
301 case PointsToNode::PointsToEdge:
302 add_pointsto_edge(ni, n1);
303 if(n1 == _phantom_object) {
304 // Special case - field set outside (globally escaping).
305 ptn->set_escape_state(PointsToNode::GlobalEscape);
306 }
307 break;
308 case PointsToNode::DeferredEdge:
309 deferred_edges->append(n1);
310 break;
1711 add_node(n, nt, PointsToNode::UnknownEscape, false);
1712 }
1713 return;
1714 }
1715
1716 // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
1717 // ThreadLocal has RawPrt type.
1718 switch (n->Opcode()) {
1719 case Op_AddP:
1720 {
1721 add_node(n, PointsToNode::Field, PointsToNode::UnknownEscape, false);
1722 break;
1723 }
1724 case Op_CastX2P:
1725 { // "Unsafe" memory access.
1726 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1727 break;
1728 }
1729 case Op_CastPP:
1730 case Op_CheckCastPP:
1731 case Op_EncodeP:
1732 case Op_DecodeN:
1733 {
1734 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
1735 int ti = n->in(1)->_idx;
1736 PointsToNode::NodeType nt = _nodes->adr_at(ti)->node_type();
1737 if (nt == PointsToNode::UnknownType) {
1738 _delayed_worklist.push(n); // Process it later.
1739 break;
1740 } else if (nt == PointsToNode::JavaObject) {
1741 add_pointsto_edge(n->_idx, ti);
1742 } else {
1743 add_deferred_edge(n->_idx, ti);
1744 }
1745 _processed.set(n->_idx);
1746 break;
1747 }
1748 case Op_ConP:
1749 {
1750 // assume all pointer constants globally escape except for null
1751 PointsToNode::EscapeState es;
1752 if (phase->type(n) == TypePtr::NULL_PTR)
1753 es = PointsToNode::NoEscape;
1754 else
1755 es = PointsToNode::GlobalEscape;
1756
1757 add_node(n, PointsToNode::JavaObject, es, true);
1758 break;
1759 }
1760 case Op_ConN:
1761 {
1762 // assume all narrow oop constants globally escape except for null
1763 PointsToNode::EscapeState es;
1764 if (phase->type(n) == TypeNarrowOop::NULL_PTR)
1765 es = PointsToNode::NoEscape;
1766 else
1767 es = PointsToNode::GlobalEscape;
1768
1769 add_node(n, PointsToNode::JavaObject, es, true);
1770 break;
1771 }
1772 case Op_CreateEx:
1773 {
1774 // assume that all exception objects globally escape
1775 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1776 break;
1777 }
1778 case Op_LoadKlass:
1779 {
1780 add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
1781 break;
1782 }
1783 case Op_LoadP:
1784 case Op_LoadN:
1785 {
1786 const Type *t = phase->type(n);
1787 if (!t->isa_narrowoop() && t->isa_ptr() == NULL) {
1788 _processed.set(n->_idx);
1789 return;
1790 }
1791 add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
1792 break;
1793 }
1794 case Op_Parm:
1795 {
1796 _processed.set(n->_idx); // No need to redefine it state.
1797 uint con = n->as_Proj()->_con;
1973 }
1974 _processed.set(n->_idx);
1975 break;
1976 }
1977 case Op_ConP:
1978 {
1979 assert(false, "Op_ConP");
1980 break;
1981 }
1982 case Op_CreateEx:
1983 {
1984 assert(false, "Op_CreateEx");
1985 break;
1986 }
1987 case Op_LoadKlass:
1988 {
1989 assert(false, "Op_LoadKlass");
1990 break;
1991 }
1992 case Op_LoadP:
1993 case Op_LoadN:
1994 {
1995 const Type *t = phase->type(n);
1996 #ifdef ASSERT
1997 if (!t->isa_narrowoop() && t->isa_ptr() == NULL)
1998 assert(false, "Op_LoadP");
1999 #endif
2000
2001 Node* adr = n->in(MemNode::Address)->uncast();
2002 const Type *adr_type = phase->type(adr);
2003 Node* adr_base;
2004 if (adr->is_AddP()) {
2005 adr_base = get_addp_base(adr);
2006 } else {
2007 adr_base = adr;
2008 }
2009
2010 // For everything "adr_base" could point to, create a deferred edge from
2011 // this node to each field with the same offset.
2012 VectorSet ptset(Thread::current()->resource_area());
2013 PointsTo(ptset, adr_base, phase);
2014 int offset = address_offset(adr, phase);
2015 for( VectorSetI i(&ptset); i.test(); ++i ) {
2016 uint pt = i.elem;
2017 add_deferred_edge_to_fields(n->_idx, pt, offset);
2058 break;
2059 }
2060 case Op_Return:
2061 {
2062 #ifdef ASSERT
2063 if( n->req() <= TypeFunc::Parms ||
2064 !phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
2065 assert(false, "Op_Return");
2066 }
2067 #endif
2068 int ti = n->in(TypeFunc::Parms)->_idx;
2069 if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) {
2070 add_pointsto_edge(n->_idx, ti);
2071 } else {
2072 add_deferred_edge(n->_idx, ti);
2073 }
2074 _processed.set(n->_idx);
2075 break;
2076 }
2077 case Op_StoreP:
2078 case Op_StoreN:
2079 case Op_StorePConditional:
2080 case Op_CompareAndSwapP:
2081 case Op_CompareAndSwapN:
2082 {
2083 Node *adr = n->in(MemNode::Address);
2084 const Type *adr_type = phase->type(adr);
2085 if (adr_type->isa_narrowoop()) {
2086 adr_type = adr_type->is_narrowoop()->make_oopptr();
2087 }
2088 #ifdef ASSERT
2089 if (!adr_type->isa_oopptr())
2090 assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP");
2091 #endif
2092
2093 assert(adr->is_AddP(), "expecting an AddP");
2094 Node *adr_base = get_addp_base(adr);
2095 Node *val = n->in(MemNode::ValueIn)->uncast();
2096 // For everything "adr_base" could point to, create a deferred edge
2097 // to "val" from each field with the same offset.
2098 VectorSet ptset(Thread::current()->resource_area());
2099 PointsTo(ptset, adr_base, phase);
2100 for( VectorSetI i(&ptset); i.test(); ++i ) {
2101 uint pt = i.elem;
2102 add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
2103 }
2104 break;
2105 }
2106 case Op_ThreadLocal:
2107 {
|