comparison src/share/vm/opto/escape.cpp @ 4122:cc81b9c09bbb

7112478: after 7105605 JRuby bench_define_method_methods.rb fails with NPE Summary: Fixed several EA issues with Connection Graph construction. Reviewed-by: never, twisti
author kvn
date Mon, 28 Nov 2011 15:46:31 -0800
parents 1bd45abaa507
children 1dc233a8c7fe
comparison
equal deleted inserted replaced
4121:db2e64ca2d5a 4122:cc81b9c09bbb
128 PointsToNode *t = ptnode_adr(to_i); 128 PointsToNode *t = ptnode_adr(to_i);
129 129
130 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); 130 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
131 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge"); 131 assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge");
132 assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge"); 132 assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge");
133 if (to_i == _phantom_object) { // Quick test for most common object
134 if (f->has_unknown_ptr()) {
135 return;
136 } else {
137 f->set_has_unknown_ptr();
138 }
139 }
133 add_edge(f, to_i, PointsToNode::PointsToEdge); 140 add_edge(f, to_i, PointsToNode::PointsToEdge);
134 } 141 }
135 142
136 void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) { 143 void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) {
137 PointsToNode *f = ptnode_adr(from_i); 144 PointsToNode *f = ptnode_adr(from_i);
163 assert(t_ptr != NULL, "must be a pointer type"); 170 assert(t_ptr != NULL, "must be a pointer type");
164 return t_ptr->offset(); 171 return t_ptr->offset();
165 } 172 }
166 173
167 void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) { 174 void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) {
175 // Don't add fields to NULL pointer.
176 if (is_null_ptr(from_i))
177 return;
168 PointsToNode *f = ptnode_adr(from_i); 178 PointsToNode *f = ptnode_adr(from_i);
169 PointsToNode *t = ptnode_adr(to_i); 179 PointsToNode *t = ptnode_adr(to_i);
170 180
171 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set"); 181 assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
172 assert(f->node_type() == PointsToNode::JavaObject, "invalid destination of Field edge"); 182 assert(f->node_type() == PointsToNode::JavaObject, "invalid destination of Field edge");
177 add_edge(f, to_i, PointsToNode::FieldEdge); 187 add_edge(f, to_i, PointsToNode::FieldEdge);
178 } 188 }
179 189
180 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) { 190 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) {
181 // Don't change non-escaping state of NULL pointer. 191 // Don't change non-escaping state of NULL pointer.
182 if (ni == _noop_null || ni == _oop_null) 192 if (is_null_ptr(ni))
183 return; 193 return;
184 PointsToNode *npt = ptnode_adr(ni); 194 PointsToNode *npt = ptnode_adr(ni);
185 PointsToNode::EscapeState old_es = npt->escape_state(); 195 PointsToNode::EscapeState old_es = npt->escape_state();
186 if (es > old_es) 196 if (es > old_es)
187 npt->set_escape_state(es); 197 npt->set_escape_state(es);
309 deferred_edges->clear(); 319 deferred_edges->clear();
310 visited->Reset(); 320 visited->Reset();
311 321
312 visited->set(ni); 322 visited->set(ni);
313 PointsToNode *ptn = ptnode_adr(ni); 323 PointsToNode *ptn = ptnode_adr(ni);
314 if (ptn->edge_count() == 0) { 324 assert(ptn->node_type() == PointsToNode::LocalVar ||
315 // No deferred or pointsto edges found. Assume the value was set 325 ptn->node_type() == PointsToNode::Field, "sanity");
316 // outside this method. Add edge to phantom object. 326 assert(ptn->edge_count() != 0, "should have at least phantom_object");
317 add_pointsto_edge(ni, _phantom_object);
318 }
319 327
320 // Mark current edges as visited and move deferred edges to separate array. 328 // Mark current edges as visited and move deferred edges to separate array.
321 for (uint i = 0; i < ptn->edge_count(); ) { 329 for (uint i = 0; i < ptn->edge_count(); ) {
322 uint t = ptn->edge_target(i); 330 uint t = ptn->edge_target(i);
323 #ifdef ASSERT 331 #ifdef ASSERT
334 } 342 }
335 for (int next = 0; next < deferred_edges->length(); ++next) { 343 for (int next = 0; next < deferred_edges->length(); ++next) {
336 uint t = deferred_edges->at(next); 344 uint t = deferred_edges->at(next);
337 PointsToNode *ptt = ptnode_adr(t); 345 PointsToNode *ptt = ptnode_adr(t);
338 uint e_cnt = ptt->edge_count(); 346 uint e_cnt = ptt->edge_count();
339 if (e_cnt == 0) { 347 assert(e_cnt != 0, "should have at least phantom_object");
340 // No deferred or pointsto edges found. Assume the value was set
341 // outside this method. Add edge to phantom object.
342 add_pointsto_edge(t, _phantom_object);
343 add_pointsto_edge(ni, _phantom_object);
344 }
345 for (uint e = 0; e < e_cnt; e++) { 348 for (uint e = 0; e < e_cnt; e++) {
346 uint etgt = ptt->edge_target(e); 349 uint etgt = ptt->edge_target(e);
347 if (visited->test_set(etgt)) 350 if (visited->test_set(etgt))
348 continue; 351 continue;
349 352
350 PointsToNode::EdgeType et = ptt->edge_type(e); 353 PointsToNode::EdgeType et = ptt->edge_type(e);
351 if (et == PointsToNode::PointsToEdge) { 354 if (et == PointsToNode::PointsToEdge) {
352 add_pointsto_edge(ni, etgt); 355 add_pointsto_edge(ni, etgt);
353 if(etgt == _phantom_object) {
354 // Special case - field set outside (globally escaping).
355 set_escape_state(ni, PointsToNode::GlobalEscape);
356 }
357 } else if (et == PointsToNode::DeferredEdge) { 356 } else if (et == PointsToNode::DeferredEdge) {
358 deferred_edges->append(etgt); 357 deferred_edges->append(etgt);
359 } else { 358 } else {
360 assert(false,"invalid connection graph"); 359 assert(false,"invalid connection graph");
361 } 360 }
362 } 361 }
363 } 362 }
363 if (ptn->edge_count() == 0) {
364 // No pointsto edges found after deferred edges are removed.
365 // For example, in the next case where call is replaced
366 // with uncommon trap and as result array's load references
367 // itself through deferred edges:
368 //
369 // A a = b[i];
370 // if (c!=null) a = c.foo();
371 // b[i] = a;
372 //
373 // Assume the value was set outside this method and
374 // add edge to phantom object.
375 add_pointsto_edge(ni, _phantom_object);
376 }
364 } 377 }
365 378
366 379
367 // Add an edge to node given by "to_i" from any field of adr_i whose offset 380 // Add an edge to node given by "to_i" from any field of adr_i whose offset
368 // matches "offset" A deferred edge is added if to_i is a LocalVar, and 381 // matches "offset" A deferred edge is added if to_i is a LocalVar, and
369 // a pointsto edge is added if it is a JavaObject 382 // a pointsto edge is added if it is a JavaObject
370 383
371 void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) { 384 void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) {
385 // No fields for NULL pointer.
386 if (is_null_ptr(adr_i)) {
387 return;
388 }
372 PointsToNode* an = ptnode_adr(adr_i); 389 PointsToNode* an = ptnode_adr(adr_i);
373 PointsToNode* to = ptnode_adr(to_i); 390 PointsToNode* to = ptnode_adr(to_i);
374 bool deferred = (to->node_type() == PointsToNode::LocalVar); 391 bool deferred = (to->node_type() == PointsToNode::LocalVar);
375 392 bool escaped = (to_i == _phantom_object) && (offs == Type::OffsetTop);
393 if (escaped) {
394 // Values in fields escaped during call.
395 assert(an->escape_state() >= PointsToNode::ArgEscape, "sanity");
396 offs = Type::OffsetBot;
397 }
376 for (uint fe = 0; fe < an->edge_count(); fe++) { 398 for (uint fe = 0; fe < an->edge_count(); fe++) {
377 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 399 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
378 int fi = an->edge_target(fe); 400 int fi = an->edge_target(fe);
401 if (escaped) {
402 set_escape_state(fi, PointsToNode::GlobalEscape);
403 }
379 PointsToNode* pf = ptnode_adr(fi); 404 PointsToNode* pf = ptnode_adr(fi);
380 int po = pf->offset(); 405 int po = pf->offset();
381 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { 406 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) {
382 if (deferred) 407 if (deferred)
383 add_deferred_edge(fi, to_i); 408 add_deferred_edge(fi, to_i);
388 } 413 }
389 414
390 // Add a deferred edge from node given by "from_i" to any field of adr_i 415 // Add a deferred edge from node given by "from_i" to any field of adr_i
391 // whose offset matches "offset". 416 // whose offset matches "offset".
392 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { 417 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) {
418 // No fields for NULL pointer.
419 if (is_null_ptr(adr_i)) {
420 return;
421 }
422 if (adr_i == _phantom_object) {
423 // Add only one edge for unknown object.
424 add_pointsto_edge(from_i, _phantom_object);
425 return;
426 }
393 PointsToNode* an = ptnode_adr(adr_i); 427 PointsToNode* an = ptnode_adr(adr_i);
394 bool is_alloc = an->_node->is_Allocate(); 428 bool is_alloc = an->_node->is_Allocate();
395 for (uint fe = 0; fe < an->edge_count(); fe++) { 429 for (uint fe = 0; fe < an->edge_count(); fe++) {
396 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 430 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
397 int fi = an->edge_target(fe); 431 int fi = an->edge_target(fe);
1560 1594
1561 GrowableArray<Node*> alloc_worklist; 1595 GrowableArray<Node*> alloc_worklist;
1562 GrowableArray<Node*> addp_worklist; 1596 GrowableArray<Node*> addp_worklist;
1563 GrowableArray<Node*> ptr_cmp_worklist; 1597 GrowableArray<Node*> ptr_cmp_worklist;
1564 PhaseGVN* igvn = _igvn; 1598 PhaseGVN* igvn = _igvn;
1565 bool has_allocations = false;
1566 1599
1567 // Push all useful nodes onto CG list and set their type. 1600 // Push all useful nodes onto CG list and set their type.
1568 for( uint next = 0; next < worklist_init.size(); ++next ) { 1601 for( uint next = 0; next < worklist_init.size(); ++next ) {
1569 Node* n = worklist_init.at(next); 1602 Node* n = worklist_init.at(next);
1570 record_for_escape_analysis(n, igvn); 1603 record_for_escape_analysis(n, igvn);
1571 // Only allocations and java static calls results are checked 1604 // Only allocations and java static calls results are checked
1572 // for an escape status. See process_call_result() below. 1605 // for an escape status. See process_call_result() below.
1573 if (n->is_Allocate() || n->is_CallStaticJava() && 1606 if (n->is_Allocate() || n->is_CallStaticJava() &&
1574 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { 1607 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) {
1575 has_allocations = true; 1608 alloc_worklist.append(n);
1576 if (n->is_Allocate())
1577 alloc_worklist.append(n);
1578 } else if(n->is_AddP()) { 1609 } else if(n->is_AddP()) {
1579 // Collect address nodes. Use them during stage 3 below 1610 // Collect address nodes. Use them during stage 3 below
1580 // to build initial connection graph field edges. 1611 // to build initial connection graph field edges.
1581 addp_worklist.append(n); 1612 addp_worklist.append(n);
1582 } else if (n->is_MergeMem()) { 1613 } else if (n->is_MergeMem()) {
1592 Node* m = n->fast_out(i); // Get user 1623 Node* m = n->fast_out(i); // Get user
1593 worklist_init.push(m); 1624 worklist_init.push(m);
1594 } 1625 }
1595 } 1626 }
1596 1627
1597 if (!has_allocations) { 1628 if (alloc_worklist.length() == 0) {
1598 _collecting = false; 1629 _collecting = false;
1599 return false; // Nothing to do. 1630 return false; // Nothing to do.
1600 } 1631 }
1601 1632
1602 // 2. First pass to create simple CG edges (doesn't require to walk CG). 1633 // 2. First pass to create simple CG edges (doesn't require to walk CG).
1675 _collecting = false; 1706 _collecting = false;
1676 return false; 1707 return false;
1677 } 1708 }
1678 #undef CG_BUILD_ITER_LIMIT 1709 #undef CG_BUILD_ITER_LIMIT
1679 1710
1711 // 5. Propagate escaped states.
1712 worklist.clear();
1713
1714 // mark all nodes reachable from GlobalEscape nodes
1715 (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape);
1716
1717 // mark all nodes reachable from ArgEscape nodes
1718 bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape);
1719
1680 Arena* arena = Thread::current()->resource_area(); 1720 Arena* arena = Thread::current()->resource_area();
1681 VectorSet visited(arena); 1721 VectorSet visited(arena);
1682 1722
1683 // 5. Find fields initializing values for not escaped allocations 1723 // 6. Find fields initializing values for not escaped allocations
1684 uint alloc_length = alloc_worklist.length(); 1724 uint alloc_length = alloc_worklist.length();
1685 for (uint next = 0; next < alloc_length; ++next) { 1725 for (uint next = 0; next < alloc_length; ++next) {
1686 Node* n = alloc_worklist.at(next); 1726 Node* n = alloc_worklist.at(next);
1687 if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) { 1727 if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) {
1688 find_init_values(n, &visited, igvn); 1728 has_non_escaping_obj = true;
1689 } 1729 if (n->is_Allocate()) {
1690 } 1730 find_init_values(n, &visited, igvn);
1691 1731 }
1692 worklist.clear(); 1732 }
1693 1733 }
1694 // 6. Remove deferred edges from the graph. 1734
1695 uint cg_length = cg_worklist.length(); 1735 uint cg_length = cg_worklist.length();
1736
1737 // Skip the rest of code if all objects escaped.
1738 if (!has_non_escaping_obj) {
1739 cg_length = 0;
1740 addp_length = 0;
1741 }
1742
1743 for (uint next = 0; next < cg_length; ++next) {
1744 int ni = cg_worklist.at(next);
1745 PointsToNode* ptn = ptnode_adr(ni);
1746 PointsToNode::NodeType nt = ptn->node_type();
1747 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
1748 if (ptn->edge_count() == 0) {
1749 // No values were found. Assume the value was set
1750 // outside this method - add edge to phantom object.
1751 add_pointsto_edge(ni, _phantom_object);
1752 }
1753 }
1754 }
1755
1756 // 7. Remove deferred edges from the graph.
1696 for (uint next = 0; next < cg_length; ++next) { 1757 for (uint next = 0; next < cg_length; ++next) {
1697 int ni = cg_worklist.at(next); 1758 int ni = cg_worklist.at(next);
1698 PointsToNode* ptn = ptnode_adr(ni); 1759 PointsToNode* ptn = ptnode_adr(ni);
1699 PointsToNode::NodeType nt = ptn->node_type(); 1760 PointsToNode::NodeType nt = ptn->node_type();
1700 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 1761 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
1701 remove_deferred(ni, &worklist, &visited); 1762 remove_deferred(ni, &worklist, &visited);
1702 } 1763 }
1703 } 1764 }
1704 1765
1705 // 7. Adjust escape state of nonescaping objects. 1766 // 8. Adjust escape state of nonescaping objects.
1706 for (uint next = 0; next < addp_length; ++next) { 1767 for (uint next = 0; next < addp_length; ++next) {
1707 Node* n = addp_worklist.at(next); 1768 Node* n = addp_worklist.at(next);
1708 adjust_escape_state(n); 1769 adjust_escape_state(n);
1709 } 1770 }
1710 1771
1711 // 8. Propagate escape states. 1772 // push all NoEscape nodes on the worklist
1712 worklist.clear(); 1773 worklist.clear();
1713
1714 // mark all nodes reachable from GlobalEscape nodes
1715 (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape);
1716
1717 // mark all nodes reachable from ArgEscape nodes
1718 bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape);
1719
1720 // push all NoEscape nodes on the worklist
1721 for( uint next = 0; next < cg_length; ++next ) { 1774 for( uint next = 0; next < cg_length; ++next ) {
1722 int nk = cg_worklist.at(next); 1775 int nk = cg_worklist.at(next);
1723 if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape) 1776 if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape &&
1777 !is_null_ptr(nk))
1724 worklist.push(nk); 1778 worklist.push(nk);
1725 } 1779 }
1780
1726 alloc_worklist.clear(); 1781 alloc_worklist.clear();
1727 // mark all nodes reachable from NoEscape nodes 1782 // Propagate scalar_replaceable value.
1728 while(worklist.length() > 0) { 1783 while(worklist.length() > 0) {
1729 uint nk = worklist.pop(); 1784 uint nk = worklist.pop();
1730 PointsToNode* ptn = ptnode_adr(nk); 1785 PointsToNode* ptn = ptnode_adr(nk);
1731 if (ptn->node_type() == PointsToNode::JavaObject &&
1732 !(nk == _noop_null || nk == _oop_null))
1733 has_non_escaping_obj = true; // Non Escape
1734 Node* n = ptn->_node; 1786 Node* n = ptn->_node;
1735 bool scalar_replaceable = ptn->scalar_replaceable(); 1787 bool scalar_replaceable = ptn->scalar_replaceable();
1736 if (n->is_Allocate() && scalar_replaceable) { 1788 if (n->is_Allocate() && scalar_replaceable) {
1737 // Push scalar replaceable allocations on alloc_worklist 1789 // Push scalar replaceable allocations on alloc_worklist
1738 // for processing in split_unique_types(). Note, 1790 // for processing in split_unique_types(). Note,
1740 alloc_worklist.append(n); 1792 alloc_worklist.append(n);
1741 } 1793 }
1742 uint e_cnt = ptn->edge_count(); 1794 uint e_cnt = ptn->edge_count();
1743 for (uint ei = 0; ei < e_cnt; ei++) { 1795 for (uint ei = 0; ei < e_cnt; ei++) {
1744 uint npi = ptn->edge_target(ei); 1796 uint npi = ptn->edge_target(ei);
1797 if (is_null_ptr(npi))
1798 continue;
1745 PointsToNode *np = ptnode_adr(npi); 1799 PointsToNode *np = ptnode_adr(npi);
1746 if (np->escape_state() < PointsToNode::NoEscape) { 1800 if (np->escape_state() < PointsToNode::NoEscape) {
1747 set_escape_state(npi, PointsToNode::NoEscape); 1801 set_escape_state(npi, PointsToNode::NoEscape);
1748 if (!scalar_replaceable) { 1802 if (!scalar_replaceable) {
1749 np->set_scalar_replaceable(false); 1803 np->set_scalar_replaceable(false);
1750 } 1804 }
1751 worklist.push(npi); 1805 worklist.push(npi);
1752 } else if (np->scalar_replaceable() && !scalar_replaceable) { 1806 } else if (np->scalar_replaceable() && !scalar_replaceable) {
1753 // Propagate scalar_replaceable value.
1754 np->set_scalar_replaceable(false); 1807 np->set_scalar_replaceable(false);
1755 worklist.push(npi); 1808 worklist.push(npi);
1756 } 1809 }
1757 } 1810 }
1758 } 1811 }
1759 1812
1760 _collecting = false; 1813 _collecting = false;
1761 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 1814 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
1762 1815
1763 assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 1816 assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape &&
1817 ptnode_adr(_oop_null)->edge_count() == 0, "sanity");
1764 if (UseCompressedOops) { 1818 if (UseCompressedOops) {
1765 assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 1819 assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape &&
1820 ptnode_adr(_noop_null)->edge_count() == 0, "sanity");
1766 } 1821 }
1767 1822
1768 if (EliminateLocks && has_non_escaping_obj) { 1823 if (EliminateLocks && has_non_escaping_obj) {
1769 // Mark locks before changing ideal graph. 1824 // Mark locks before changing ideal graph.
1770 int cnt = C->macro_count(); 1825 int cnt = C->macro_count();
1877 // Check if a oop field's initializing value is recorded and add 1932 // Check if a oop field's initializing value is recorded and add
1878 // a corresponding NULL field's value if it is not recorded. 1933 // a corresponding NULL field's value if it is not recorded.
1879 // Connection Graph does not record a default initialization by NULL 1934 // Connection Graph does not record a default initialization by NULL
1880 // captured by Initialize node. 1935 // captured by Initialize node.
1881 // 1936 //
1937 uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
1882 uint ae_cnt = pta->edge_count(); 1938 uint ae_cnt = pta->edge_count();
1939 bool visited_bottom_offset = false;
1883 for (uint ei = 0; ei < ae_cnt; ei++) { 1940 for (uint ei = 0; ei < ae_cnt; ei++) {
1884 uint nidx = pta->edge_target(ei); // Field (AddP) 1941 uint nidx = pta->edge_target(ei); // Field (AddP)
1885 PointsToNode* ptn = ptnode_adr(nidx); 1942 PointsToNode* ptn = ptnode_adr(nidx);
1886 assert(ptn->_node->is_AddP(), "Should be AddP nodes only"); 1943 assert(ptn->_node->is_AddP(), "Should be AddP nodes only");
1887 int offset = ptn->offset(); 1944 int offset = ptn->offset();
1888 if (offset != Type::OffsetBot && 1945 if (offset == Type::OffsetBot) {
1889 offset != oopDesc::klass_offset_in_bytes() && 1946 if (!visited_bottom_offset) {
1890 !visited->test_set(offset)) { 1947 visited_bottom_offset = true;
1948 // Check only oop fields.
1949 const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
1950 if (!adr_type->isa_aryptr() ||
1951 (adr_type->isa_aryptr()->klass() == NULL) ||
1952 adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
1953 // OffsetBot is used to reference array's element,
1954 // always add reference to NULL since we don't
1955 // known which element is referenced.
1956 add_edge_from_fields(alloc->_idx, null_idx, offset);
1957 }
1958 }
1959 } else if (offset != oopDesc::klass_offset_in_bytes() &&
1960 !visited->test_set(offset)) {
1891 1961
1892 // Check only oop fields. 1962 // Check only oop fields.
1893 const Type* adr_type = ptn->_node->as_AddP()->bottom_type(); 1963 const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
1894 BasicType basic_field_type = T_INT; 1964 BasicType basic_field_type = T_INT;
1895 if (adr_type->isa_instptr()) { 1965 if (adr_type->isa_instptr()) {
1960 } 2030 }
1961 } 2031 }
1962 } 2032 }
1963 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { 2033 if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
1964 // A field's initializing value was not recorded. Add NULL. 2034 // A field's initializing value was not recorded. Add NULL.
1965 uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
1966 add_edge_from_fields(alloc->_idx, null_idx, offset); 2035 add_edge_from_fields(alloc->_idx, null_idx, offset);
1967 } 2036 }
1968 } 2037 }
1969 } 2038 }
1970 } 2039 }
2046 if (ptnode_adr(nk)->escape_state() == esc_state) 2115 if (ptnode_adr(nk)->escape_state() == esc_state)
2047 worklist->push(nk); 2116 worklist->push(nk);
2048 } 2117 }
2049 // mark all reachable nodes 2118 // mark all reachable nodes
2050 while (worklist->length() > 0) { 2119 while (worklist->length() > 0) {
2051 PointsToNode* ptn = ptnode_adr(worklist->pop()); 2120 int pt = worklist->pop();
2052 if (ptn->node_type() == PointsToNode::JavaObject) { 2121 PointsToNode* ptn = ptnode_adr(pt);
2122 if (ptn->node_type() == PointsToNode::JavaObject &&
2123 !is_null_ptr(pt)) {
2053 has_java_obj = true; 2124 has_java_obj = true;
2125 if (esc_state > PointsToNode::NoEscape) {
2126 // fields values are unknown if object escapes
2127 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
2128 }
2054 } 2129 }
2055 uint e_cnt = ptn->edge_count(); 2130 uint e_cnt = ptn->edge_count();
2056 for (uint ei = 0; ei < e_cnt; ei++) { 2131 for (uint ei = 0; ei < e_cnt; ei++) {
2057 uint npi = ptn->edge_target(ei); 2132 uint npi = ptn->edge_target(ei);
2133 if (is_null_ptr(npi))
2134 continue;
2058 PointsToNode *np = ptnode_adr(npi); 2135 PointsToNode *np = ptnode_adr(npi);
2059 if (np->escape_state() < esc_state) { 2136 if (np->escape_state() < esc_state) {
2060 set_escape_state(npi, esc_state); 2137 set_escape_state(npi, esc_state);
2061 worklist->push(npi); 2138 worklist->push(npi);
2062 } 2139 }
2157 } 2234 }
2158 return NULL; 2235 return NULL;
2159 } 2236 }
2160 2237
2161 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { 2238 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) {
2162 2239 bool is_arraycopy = false;
2163 switch (call->Opcode()) { 2240 switch (call->Opcode()) {
2164 #ifdef ASSERT 2241 #ifdef ASSERT
2165 case Op_Allocate: 2242 case Op_Allocate:
2166 case Op_AllocateArray: 2243 case Op_AllocateArray:
2167 case Op_Lock: 2244 case Op_Lock:
2168 case Op_Unlock: 2245 case Op_Unlock:
2169 assert(false, "should be done already"); 2246 assert(false, "should be done already");
2170 break; 2247 break;
2171 #endif 2248 #endif
2249 case Op_CallLeafNoFP:
2250 is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
2251 strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
2252 // fall through
2172 case Op_CallLeaf: 2253 case Op_CallLeaf:
2173 case Op_CallLeafNoFP:
2174 { 2254 {
2175 // Stub calls, objects do not escape but they are not scale replaceable. 2255 // Stub calls, objects do not escape but they are not scale replaceable.
2176 // Adjust escape state for outgoing arguments. 2256 // Adjust escape state for outgoing arguments.
2177 const TypeTuple * d = call->tf()->domain(); 2257 const TypeTuple * d = call->tf()->domain();
2258 bool src_has_oops = false;
2178 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 2259 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
2179 const Type* at = d->field_at(i); 2260 const Type* at = d->field_at(i);
2180 Node *arg = call->in(i)->uncast(); 2261 Node *arg = call->in(i)->uncast();
2181 const Type *aat = phase->type(arg); 2262 const Type *aat = phase->type(arg);
2263 PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state();
2182 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && 2264 if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
2183 ptnode_adr(arg->_idx)->escape_state() < PointsToNode::ArgEscape) { 2265 (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) {
2184 2266
2185 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || 2267 assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
2186 aat->isa_ptr() != NULL, "expecting an Ptr"); 2268 aat->isa_ptr() != NULL, "expecting an Ptr");
2269 bool arg_has_oops = aat->isa_oopptr() &&
2270 (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
2271 (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
2272 if (i == TypeFunc::Parms) {
2273 src_has_oops = arg_has_oops;
2274 }
2275 //
2276 // src or dst could be j.l.Object when other is basic type array:
2277 //
2278 // arraycopy(char[],0,Object*,0,size);
2279 // arraycopy(Object*,0,char[],0,size);
2280 //
2281 // Don't add edges from dst's fields in such cases.
2282 //
2283 bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy &&
2284 arg_has_oops && (i > TypeFunc::Parms);
2187 #ifdef ASSERT 2285 #ifdef ASSERT
2188 if (!(call->Opcode() == Op_CallLeafNoFP && 2286 if (!(is_arraycopy ||
2189 call->as_CallLeaf()->_name != NULL &&
2190 (strstr(call->as_CallLeaf()->_name, "arraycopy") != 0) ||
2191 call->as_CallLeaf()->_name != NULL && 2287 call->as_CallLeaf()->_name != NULL &&
2192 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || 2288 (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 ||
2193 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) 2289 strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
2194 ) { 2290 ) {
2195 call->dump(); 2291 call->dump();
2196 assert(false, "EA: unexpected CallLeaf"); 2292 assert(false, "EA: unexpected CallLeaf");
2197 } 2293 }
2198 #endif 2294 #endif
2295 // Always process arraycopy's destination object since
2296 // we need to add all possible edges to references in
2297 // source object.
2298 if (arg_esc >= PointsToNode::ArgEscape &&
2299 !arg_is_arraycopy_dest) {
2300 continue;
2301 }
2199 set_escape_state(arg->_idx, PointsToNode::ArgEscape); 2302 set_escape_state(arg->_idx, PointsToNode::ArgEscape);
2303 Node* arg_base = arg;
2200 if (arg->is_AddP()) { 2304 if (arg->is_AddP()) {
2201 // 2305 //
2202 // The inline_native_clone() case when the arraycopy stub is called 2306 // The inline_native_clone() case when the arraycopy stub is called
2203 // after the allocation before Initialize and CheckCastPP nodes. 2307 // after the allocation before Initialize and CheckCastPP nodes.
2308 // Or normal arraycopy for object arrays case.
2204 // 2309 //
2205 // Set AddP's base (Allocate) as not scalar replaceable since 2310 // Set AddP's base (Allocate) as not scalar replaceable since
2206 // pointer to the base (with offset) is passed as argument. 2311 // pointer to the base (with offset) is passed as argument.
2207 // 2312 //
2208 arg = get_addp_base(arg); 2313 arg_base = get_addp_base(arg);
2209 } 2314 }
2210 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 2315 VectorSet argset = *PointsTo(arg_base); // Clone set
2211 uint pt = j.elem; 2316 for( VectorSetI j(&argset); j.test(); ++j ) {
2212 set_escape_state(pt, PointsToNode::ArgEscape); 2317 uint pd = j.elem; // Destination object
2318 set_escape_state(pd, PointsToNode::ArgEscape);
2319
2320 if (arg_is_arraycopy_dest) {
2321 PointsToNode* ptd = ptnode_adr(pd);
2322 // Conservatively reference an unknown object since
2323 // not all source's fields/elements may be known.
2324 add_edge_from_fields(pd, _phantom_object, Type::OffsetBot);
2325
2326 Node *src = call->in(TypeFunc::Parms)->uncast();
2327 Node* src_base = src;
2328 if (src->is_AddP()) {
2329 src_base = get_addp_base(src);
2330 }
2331 // Create edges from destination's fields to
2332 // everything known source's fields could point to.
2333 for( VectorSetI s(PointsTo(src_base)); s.test(); ++s ) {
2334 uint ps = s.elem;
2335 bool has_bottom_offset = false;
2336 for (uint fd = 0; fd < ptd->edge_count(); fd++) {
2337 assert(ptd->edge_type(fd) == PointsToNode::FieldEdge, "expecting a field edge");
2338 int fdi = ptd->edge_target(fd);
2339 PointsToNode* pfd = ptnode_adr(fdi);
2340 int offset = pfd->offset();
2341 if (offset == Type::OffsetBot)
2342 has_bottom_offset = true;
2343 assert(offset != -1, "offset should be set");
2344 add_deferred_edge_to_fields(fdi, ps, offset);
2345 }
2346 // Destination object may not have access (no field edge)
2347 // to fields which are accessed in source object.
2348 // As result no edges will be created to those source's
2349 // fields and escape state of destination object will
2350 // not be propagated to those fields.
2351 //
2352 // Mark source object as global escape except in
2353 // the case with Type::OffsetBot field (which is
2354 // common case for array elements access) when
2355 // edges are created to all source's fields.
2356 if (!has_bottom_offset) {
2357 set_escape_state(ps, PointsToNode::GlobalEscape);
2358 }
2359 }
2360 }
2213 } 2361 }
2214 } 2362 }
2215 } 2363 }
2216 break; 2364 break;
2217 } 2365 }
2250 } 2398 }
2251 2399
2252 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 2400 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
2253 uint pt = j.elem; 2401 uint pt = j.elem;
2254 if (global_escapes) { 2402 if (global_escapes) {
2255 //The argument global escapes, mark everything it could point to 2403 // The argument global escapes, mark everything it could point to
2256 set_escape_state(pt, PointsToNode::GlobalEscape); 2404 set_escape_state(pt, PointsToNode::GlobalEscape);
2405 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
2257 } else { 2406 } else {
2407 set_escape_state(pt, PointsToNode::ArgEscape);
2258 if (fields_escapes) { 2408 if (fields_escapes) {
2259 // The argument itself doesn't escape, but any fields might 2409 // The argument itself doesn't escape, but any fields might.
2260 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot); 2410 // Use OffsetTop to indicate such case.
2411 add_edge_from_fields(pt, _phantom_object, Type::OffsetTop);
2261 } 2412 }
2262 set_escape_state(pt, PointsToNode::ArgEscape);
2263 } 2413 }
2264 } 2414 }
2265 } 2415 }
2266 } 2416 }
2267 if (copy_dependencies) 2417 if (copy_dependencies)
2283 Node *arg = call->in(i)->uncast(); 2433 Node *arg = call->in(i)->uncast();
2284 set_escape_state(arg->_idx, PointsToNode::GlobalEscape); 2434 set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
2285 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) { 2435 for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
2286 uint pt = j.elem; 2436 uint pt = j.elem;
2287 set_escape_state(pt, PointsToNode::GlobalEscape); 2437 set_escape_state(pt, PointsToNode::GlobalEscape);
2438 add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
2288 } 2439 }
2289 } 2440 }
2290 } 2441 }
2291 } 2442 }
2292 } 2443 }
2383 // update dependency information. 2534 // update dependency information.
2384 // Mark it as NoEscape so that objects referenced by 2535 // Mark it as NoEscape so that objects referenced by
2385 // it's fields will be marked as NoEscape at least. 2536 // it's fields will be marked as NoEscape at least.
2386 set_escape_state(call_idx, PointsToNode::NoEscape); 2537 set_escape_state(call_idx, PointsToNode::NoEscape);
2387 ptnode_adr(call_idx)->set_scalar_replaceable(false); 2538 ptnode_adr(call_idx)->set_scalar_replaceable(false);
2539 // Fields values are unknown
2540 add_edge_from_fields(call_idx, _phantom_object, Type::OffsetBot);
2388 add_pointsto_edge(resproj_idx, call_idx); 2541 add_pointsto_edge(resproj_idx, call_idx);
2389 copy_dependencies = true; 2542 copy_dependencies = true;
2390 } else if (call_analyzer->is_return_local()) { 2543 } else {
2391 // determine whether any arguments are returned 2544 // determine whether any arguments are returned
2392 set_escape_state(call_idx, PointsToNode::ArgEscape); 2545 set_escape_state(call_idx, PointsToNode::ArgEscape);
2393 bool ret_arg = false; 2546 bool ret_arg = false;
2394 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 2547 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
2395 const Type* at = d->field_at(i); 2548 const Type* at = d->field_at(i);
2396
2397 if (at->isa_oopptr() != NULL) { 2549 if (at->isa_oopptr() != NULL) {
2398 Node *arg = call->in(i)->uncast(); 2550 Node *arg = call->in(i)->uncast();
2399 2551
2400 if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) { 2552 if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
2401 ret_arg = true; 2553 ret_arg = true;
2407 else 2559 else
2408 add_deferred_edge(resproj_idx, arg->_idx); 2560 add_deferred_edge(resproj_idx, arg->_idx);
2409 } 2561 }
2410 } 2562 }
2411 } 2563 }
2412 if (done && !ret_arg) {
2413 // Returns unknown object.
2414 set_escape_state(call_idx, PointsToNode::GlobalEscape);
2415 add_pointsto_edge(resproj_idx, _phantom_object);
2416 }
2417 if (done) { 2564 if (done) {
2418 copy_dependencies = true; 2565 copy_dependencies = true;
2566 // is_return_local() is true when only arguments are returned.
2567 if (!ret_arg || !call_analyzer->is_return_local()) {
2568 // Returns unknown object.
2569 add_pointsto_edge(resproj_idx, _phantom_object);
2570 }
2419 } 2571 }
2420 } else {
2421 set_escape_state(call_idx, PointsToNode::GlobalEscape);
2422 add_pointsto_edge(resproj_idx, _phantom_object);
2423 } 2572 }
2424 if (copy_dependencies) 2573 if (copy_dependencies)
2425 call_analyzer->copy_dependencies(_compile->dependencies()); 2574 call_analyzer->copy_dependencies(_compile->dependencies());
2426 } 2575 }
2427 if (done) 2576 if (done)