src/share/vm/opto/escape.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6689060 Sdiff src/share/vm/opto

src/share/vm/opto/escape.cpp

Print this page




 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     {


src/share/vm/opto/escape.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File