src/share/vm/opto/escape.cpp

changeset 3254
59e515ee9354
parent 3242
e69a66a1457b
child 3309
8c57262447d3
equal deleted inserted replaced
3253:1feb272af3a7 3254:59e515ee9354
376 376
377 // Add a deferred edge from node given by "from_i" to any field of adr_i 377 // Add a deferred edge from node given by "from_i" to any field of adr_i
378 // whose offset matches "offset". 378 // whose offset matches "offset".
379 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) { 379 void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) {
380 PointsToNode* an = ptnode_adr(adr_i); 380 PointsToNode* an = ptnode_adr(adr_i);
381 bool is_alloc = an->_node->is_Allocate();
381 for (uint fe = 0; fe < an->edge_count(); fe++) { 382 for (uint fe = 0; fe < an->edge_count(); fe++) {
382 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge"); 383 assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
383 int fi = an->edge_target(fe); 384 int fi = an->edge_target(fe);
384 PointsToNode* pf = ptnode_adr(fi); 385 PointsToNode* pf = ptnode_adr(fi);
385 int po = pf->offset(); 386 int offset = pf->offset();
386 if (pf->edge_count() == 0) { 387 if (!is_alloc) {
387 // we have not seen any stores to this field, assume it was set outside this method 388 // Assume the field was set outside this method if it is not Allocation
388 add_pointsto_edge(fi, _phantom_object); 389 add_pointsto_edge(fi, _phantom_object);
389 } 390 }
390 if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) { 391 if (offset == offs || offset == Type::OffsetBot || offs == Type::OffsetBot) {
391 add_deferred_edge(from_i, fi); 392 add_deferred_edge(from_i, fi);
392 } 393 }
393 } 394 }
394 } 395 }
395 396
1039 // copy escape information to call node 1040 // copy escape information to call node
1040 PointsToNode* ptn = ptnode_adr(alloc->_idx); 1041 PointsToNode* ptn = ptnode_adr(alloc->_idx);
1041 PointsToNode::EscapeState es = escape_state(alloc); 1042 PointsToNode::EscapeState es = escape_state(alloc);
1042 // We have an allocation or call which returns a Java object, 1043 // We have an allocation or call which returns a Java object,
1043 // see if it is unescaped. 1044 // see if it is unescaped.
1044 if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable) 1045 if (es != PointsToNode::NoEscape || !ptn->scalar_replaceable())
1045 continue; 1046 continue;
1046 1047
1047 // Find CheckCastPP for the allocate or for the return value of a call 1048 // Find CheckCastPP for the allocate or for the return value of a call
1048 n = alloc->result_cast(); 1049 n = alloc->result_cast();
1049 if (n == NULL) { // No uses except Initialize node 1050 if (n == NULL) { // No uses except Initialize node
1088 if (alloc->is_Allocate()) { 1089 if (alloc->is_Allocate()) {
1089 // Set the scalar_replaceable flag for allocation 1090 // Set the scalar_replaceable flag for allocation
1090 // so it could be eliminated. 1091 // so it could be eliminated.
1091 alloc->as_Allocate()->_is_scalar_replaceable = true; 1092 alloc->as_Allocate()->_is_scalar_replaceable = true;
1092 } 1093 }
1093 set_escape_state(n->_idx, es); 1094 set_escape_state(n->_idx, es); // CheckCastPP escape state
1094 // in order for an object to be scalar-replaceable, it must be: 1095 // in order for an object to be scalar-replaceable, it must be:
1095 // - a direct allocation (not a call returning an object) 1096 // - a direct allocation (not a call returning an object)
1096 // - non-escaping 1097 // - non-escaping
1097 // - eligible to be a unique type 1098 // - eligible to be a unique type
1098 // - not determined to be ineligible by escape analysis 1099 // - not determined to be ineligible by escape analysis
1100 ptnode_adr(n->_idx)->_node != NULL, "should be registered"); 1101 ptnode_adr(n->_idx)->_node != NULL, "should be registered");
1101 set_map(alloc->_idx, n); 1102 set_map(alloc->_idx, n);
1102 set_map(n->_idx, alloc); 1103 set_map(n->_idx, alloc);
1103 const TypeOopPtr *t = igvn->type(n)->isa_oopptr(); 1104 const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
1104 if (t == NULL) 1105 if (t == NULL)
1105 continue; // not a TypeInstPtr 1106 continue; // not a TypeOopPtr
1106 tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni); 1107 tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni);
1107 igvn->hash_delete(n); 1108 igvn->hash_delete(n);
1108 igvn->set_type(n, tinst); 1109 igvn->set_type(n, tinst);
1109 n->raise_bottom_type(tinst); 1110 n->raise_bottom_type(tinst);
1110 igvn->hash_insert(n); 1111 igvn->hash_insert(n);
1111 record_for_optimizer(n); 1112 record_for_optimizer(n);
1112 if (alloc->is_Allocate() && ptn->_scalar_replaceable && 1113 if (alloc->is_Allocate() && (t->isa_instptr() || t->isa_aryptr())) {
1113 (t->isa_instptr() || t->isa_aryptr())) {
1114 1114
1115 // First, put on the worklist all Field edges from Connection Graph 1115 // First, put on the worklist all Field edges from Connection Graph
1116 // which is more accurate then putting immediate users from Ideal Graph. 1116 // which is more accurate then putting immediate users from Ideal Graph.
1117 for (uint e = 0; e < ptn->edge_count(); e++) { 1117 for (uint e = 0; e < ptn->edge_count(); e++) {
1118 Node *use = ptnode_adr(ptn->edge_target(e))->_node; 1118 Node *use = ptnode_adr(ptn->edge_target(e))->_node;
1536 // Initialize worklist 1536 // Initialize worklist
1537 if (C->root() != NULL) { 1537 if (C->root() != NULL) {
1538 worklist_init.push(C->root()); 1538 worklist_init.push(C->root());
1539 } 1539 }
1540 1540
1541 GrowableArray<int> cg_worklist; 1541 GrowableArray<Node*> alloc_worklist;
1542 GrowableArray<Node*> addp_worklist;
1542 PhaseGVN* igvn = _igvn; 1543 PhaseGVN* igvn = _igvn;
1543 bool has_allocations = false; 1544 bool has_allocations = false;
1544 1545
1545 // Push all useful nodes onto CG list and set their type. 1546 // Push all useful nodes onto CG list and set their type.
1546 for( uint next = 0; next < worklist_init.size(); ++next ) { 1547 for( uint next = 0; next < worklist_init.size(); ++next ) {
1549 // Only allocations and java static calls results are checked 1550 // Only allocations and java static calls results are checked
1550 // for an escape status. See process_call_result() below. 1551 // for an escape status. See process_call_result() below.
1551 if (n->is_Allocate() || n->is_CallStaticJava() && 1552 if (n->is_Allocate() || n->is_CallStaticJava() &&
1552 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) { 1553 ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) {
1553 has_allocations = true; 1554 has_allocations = true;
1555 if (n->is_Allocate())
1556 alloc_worklist.append(n);
1554 } 1557 }
1555 if(n->is_AddP()) { 1558 if(n->is_AddP()) {
1556 // Collect address nodes. Use them during stage 3 below 1559 // Collect address nodes. Use them during stage 3 below
1557 // to build initial connection graph field edges. 1560 // to build initial connection graph field edges.
1558 cg_worklist.append(n->_idx); 1561 addp_worklist.append(n);
1559 } else if (n->is_MergeMem()) { 1562 } else if (n->is_MergeMem()) {
1560 // Collect all MergeMem nodes to add memory slices for 1563 // Collect all MergeMem nodes to add memory slices for
1561 // scalar replaceable objects in split_unique_types(). 1564 // scalar replaceable objects in split_unique_types().
1562 _mergemem_worklist.append(n->as_MergeMem()); 1565 _mergemem_worklist.append(n->as_MergeMem());
1563 } 1566 }
1579 build_connection_graph(n, igvn); 1582 build_connection_graph(n, igvn);
1580 } 1583 }
1581 1584
1582 // 3. Pass to create initial fields edges (JavaObject -F-> AddP) 1585 // 3. Pass to create initial fields edges (JavaObject -F-> AddP)
1583 // to reduce number of iterations during stage 4 below. 1586 // to reduce number of iterations during stage 4 below.
1584 uint cg_length = cg_worklist.length(); 1587 uint addp_length = addp_worklist.length();
1585 for( uint next = 0; next < cg_length; ++next ) { 1588 for( uint next = 0; next < addp_length; ++next ) {
1586 int ni = cg_worklist.at(next); 1589 Node* n = addp_worklist.at(next);
1587 Node* n = ptnode_adr(ni)->_node;
1588 Node* base = get_addp_base(n); 1590 Node* base = get_addp_base(n);
1589 if (base->is_Proj()) 1591 if (base->is_Proj())
1590 base = base->in(0); 1592 base = base->in(0);
1591 PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type(); 1593 PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type();
1592 if (nt == PointsToNode::JavaObject) { 1594 if (nt == PointsToNode::JavaObject) {
1593 build_connection_graph(n, igvn); 1595 build_connection_graph(n, igvn);
1594 } 1596 }
1595 } 1597 }
1596 1598
1597 cg_worklist.clear(); 1599 GrowableArray<int> cg_worklist;
1598 cg_worklist.append(_phantom_object); 1600 cg_worklist.append(_phantom_object);
1599 GrowableArray<uint> worklist; 1601 GrowableArray<uint> worklist;
1600 1602
1601 // 4. Build Connection Graph which need 1603 // 4. Build Connection Graph which need
1602 // to walk the connection graph. 1604 // to walk the connection graph.
1651 } 1653 }
1652 #undef CG_BUILD_ITER_LIMIT 1654 #undef CG_BUILD_ITER_LIMIT
1653 1655
1654 Arena* arena = Thread::current()->resource_area(); 1656 Arena* arena = Thread::current()->resource_area();
1655 VectorSet visited(arena); 1657 VectorSet visited(arena);
1658
1659 // 5. Find fields initializing values for not escaped allocations
1660 uint alloc_length = alloc_worklist.length();
1661 for (uint next = 0; next < alloc_length; ++next) {
1662 Node* n = alloc_worklist.at(next);
1663 if (ptnode_adr(n->_idx)->escape_state() == PointsToNode::NoEscape) {
1664 find_init_values(n, &visited, igvn);
1665 }
1666 }
1667
1656 worklist.clear(); 1668 worklist.clear();
1657 1669
1658 // 5. Remove deferred edges from the graph and adjust 1670 // 6. Remove deferred edges from the graph.
1659 // escape state of nonescaping objects. 1671 uint cg_length = cg_worklist.length();
1660 cg_length = cg_worklist.length(); 1672 for (uint next = 0; next < cg_length; ++next) {
1661 for( uint next = 0; next < cg_length; ++next ) {
1662 int ni = cg_worklist.at(next); 1673 int ni = cg_worklist.at(next);
1663 PointsToNode* ptn = ptnode_adr(ni); 1674 PointsToNode* ptn = ptnode_adr(ni);
1664 PointsToNode::NodeType nt = ptn->node_type(); 1675 PointsToNode::NodeType nt = ptn->node_type();
1665 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { 1676 if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
1666 remove_deferred(ni, &worklist, &visited); 1677 remove_deferred(ni, &worklist, &visited);
1667 Node *n = ptn->_node; 1678 Node *n = ptn->_node;
1668 if (n->is_AddP()) { 1679 }
1669 // Search for objects which are not scalar replaceable 1680 }
1670 // and adjust their escape state. 1681
1671 adjust_escape_state(ni, igvn); 1682 // 7. Adjust escape state of nonescaping objects.
1672 } 1683 for (uint next = 0; next < addp_length; ++next) {
1673 } 1684 Node* n = addp_worklist.at(next);
1674 } 1685 adjust_escape_state(n);
1675 1686 }
1676 // 6. Propagate escape states. 1687
1688 // 8. Propagate escape states.
1677 worklist.clear(); 1689 worklist.clear();
1678 bool has_non_escaping_obj = false; 1690
1679
1680 // push all GlobalEscape nodes on the worklist
1681 for( uint next = 0; next < cg_length; ++next ) {
1682 int nk = cg_worklist.at(next);
1683 if (ptnode_adr(nk)->escape_state() == PointsToNode::GlobalEscape)
1684 worklist.push(nk);
1685 }
1686 // mark all nodes reachable from GlobalEscape nodes 1691 // mark all nodes reachable from GlobalEscape nodes
1687 while(worklist.length() > 0) { 1692 (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape);
1688 PointsToNode* ptn = ptnode_adr(worklist.pop()); 1693
1689 uint e_cnt = ptn->edge_count();
1690 for (uint ei = 0; ei < e_cnt; ei++) {
1691 uint npi = ptn->edge_target(ei);
1692 PointsToNode *np = ptnode_adr(npi);
1693 if (np->escape_state() < PointsToNode::GlobalEscape) {
1694 set_escape_state(npi, PointsToNode::GlobalEscape);
1695 worklist.push(npi);
1696 }
1697 }
1698 }
1699
1700 // push all ArgEscape nodes on the worklist
1701 for( uint next = 0; next < cg_length; ++next ) {
1702 int nk = cg_worklist.at(next);
1703 if (ptnode_adr(nk)->escape_state() == PointsToNode::ArgEscape)
1704 worklist.push(nk);
1705 }
1706 // mark all nodes reachable from ArgEscape nodes 1694 // mark all nodes reachable from ArgEscape nodes
1707 while(worklist.length() > 0) { 1695 bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape);
1708 PointsToNode* ptn = ptnode_adr(worklist.pop());
1709 if (ptn->node_type() == PointsToNode::JavaObject)
1710 has_non_escaping_obj = true; // Non GlobalEscape
1711 uint e_cnt = ptn->edge_count();
1712 for (uint ei = 0; ei < e_cnt; ei++) {
1713 uint npi = ptn->edge_target(ei);
1714 PointsToNode *np = ptnode_adr(npi);
1715 if (np->escape_state() < PointsToNode::ArgEscape) {
1716 set_escape_state(npi, PointsToNode::ArgEscape);
1717 worklist.push(npi);
1718 }
1719 }
1720 }
1721
1722 GrowableArray<Node*> alloc_worklist;
1723 1696
1724 // push all NoEscape nodes on the worklist 1697 // push all NoEscape nodes on the worklist
1725 for( uint next = 0; next < cg_length; ++next ) { 1698 for( uint next = 0; next < cg_length; ++next ) {
1726 int nk = cg_worklist.at(next); 1699 int nk = cg_worklist.at(next);
1727 if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape) 1700 if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape)
1728 worklist.push(nk); 1701 worklist.push(nk);
1729 } 1702 }
1703 alloc_worklist.clear();
1730 // mark all nodes reachable from NoEscape nodes 1704 // mark all nodes reachable from NoEscape nodes
1731 while(worklist.length() > 0) { 1705 while(worklist.length() > 0) {
1732 uint nk = worklist.pop(); 1706 uint nk = worklist.pop();
1733 PointsToNode* ptn = ptnode_adr(nk); 1707 PointsToNode* ptn = ptnode_adr(nk);
1734 if (ptn->node_type() == PointsToNode::JavaObject && 1708 if (ptn->node_type() == PointsToNode::JavaObject &&
1735 !(nk == _noop_null || nk == _oop_null)) 1709 !(nk == _noop_null || nk == _oop_null))
1736 has_non_escaping_obj = true; // Non Escape 1710 has_non_escaping_obj = true; // Non Escape
1737 Node* n = ptn->_node; 1711 Node* n = ptn->_node;
1738 if (n->is_Allocate() && ptn->_scalar_replaceable ) { 1712 bool scalar_replaceable = ptn->scalar_replaceable();
1713 if (n->is_Allocate() && scalar_replaceable) {
1739 // Push scalar replaceable allocations on alloc_worklist 1714 // Push scalar replaceable allocations on alloc_worklist
1740 // for processing in split_unique_types(). 1715 // for processing in split_unique_types(). Note,
1716 // following code may change scalar_replaceable value.
1741 alloc_worklist.append(n); 1717 alloc_worklist.append(n);
1742 } 1718 }
1743 uint e_cnt = ptn->edge_count(); 1719 uint e_cnt = ptn->edge_count();
1744 for (uint ei = 0; ei < e_cnt; ei++) { 1720 for (uint ei = 0; ei < e_cnt; ei++) {
1745 uint npi = ptn->edge_target(ei); 1721 uint npi = ptn->edge_target(ei);
1746 PointsToNode *np = ptnode_adr(npi); 1722 PointsToNode *np = ptnode_adr(npi);
1747 if (np->escape_state() < PointsToNode::NoEscape) { 1723 if (np->escape_state() < PointsToNode::NoEscape) {
1748 set_escape_state(npi, PointsToNode::NoEscape); 1724 set_escape_state(npi, PointsToNode::NoEscape);
1725 if (!scalar_replaceable) {
1726 np->set_scalar_replaceable(false);
1727 }
1728 worklist.push(npi);
1729 } else if (np->scalar_replaceable() && !scalar_replaceable) {
1730 // Propagate scalar_replaceable value.
1731 np->set_scalar_replaceable(false);
1749 worklist.push(npi); 1732 worklist.push(npi);
1750 } 1733 }
1751 } 1734 }
1752 } 1735 }
1753 1736
1757 assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 1740 assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape, "sanity");
1758 if (UseCompressedOops) { 1741 if (UseCompressedOops) {
1759 assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape, "sanity"); 1742 assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape, "sanity");
1760 } 1743 }
1761 1744
1762 if (EliminateLocks) { 1745 if (EliminateLocks && has_non_escaping_obj) {
1763 // Mark locks before changing ideal graph. 1746 // Mark locks before changing ideal graph.
1764 int cnt = C->macro_count(); 1747 int cnt = C->macro_count();
1765 for( int i=0; i < cnt; i++ ) { 1748 for( int i=0; i < cnt; i++ ) {
1766 Node *n = C->macro_node(i); 1749 Node *n = C->macro_node(i);
1767 if (n->is_AbstractLock()) { // Lock and Unlock nodes 1750 if (n->is_AbstractLock()) { // Lock and Unlock nodes
1782 if (PrintEscapeAnalysis) { 1765 if (PrintEscapeAnalysis) {
1783 dump(); // Dump ConnectionGraph 1766 dump(); // Dump ConnectionGraph
1784 } 1767 }
1785 #endif 1768 #endif
1786 1769
1787 bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0; 1770 bool has_scalar_replaceable_candidates = false;
1771 alloc_length = alloc_worklist.length();
1772 for (uint next = 0; next < alloc_length; ++next) {
1773 Node* n = alloc_worklist.at(next);
1774 PointsToNode* ptn = ptnode_adr(n->_idx);
1775 assert(ptn->escape_state() == PointsToNode::NoEscape, "sanity");
1776 if (ptn->scalar_replaceable()) {
1777 has_scalar_replaceable_candidates = true;
1778 break;
1779 }
1780 }
1781
1788 if ( has_scalar_replaceable_candidates && 1782 if ( has_scalar_replaceable_candidates &&
1789 C->AliasLevel() >= 3 && EliminateAllocations ) { 1783 C->AliasLevel() >= 3 && EliminateAllocations ) {
1790 1784
1791 // Now use the escape information to create unique types for 1785 // Now use the escape information to create unique types for
1792 // scalar replaceable objects. 1786 // scalar replaceable objects.
1811 #endif 1805 #endif
1812 } 1806 }
1813 return has_non_escaping_obj; 1807 return has_non_escaping_obj;
1814 } 1808 }
1815 1809
1816 // Adjust escape state after Connection Graph is built. 1810 // Find fields initializing values for allocations.
1817 void ConnectionGraph::adjust_escape_state(int nidx, PhaseTransform* phase) { 1811 void ConnectionGraph::find_init_values(Node* alloc, VectorSet* visited, PhaseTransform* phase) {
1818 PointsToNode* ptn = ptnode_adr(nidx); 1812 assert(alloc->is_Allocate(), "Should be called for Allocate nodes only");
1819 Node* n = ptn->_node; 1813 PointsToNode* pta = ptnode_adr(alloc->_idx);
1820 assert(n->is_AddP(), "Should be called for AddP nodes only"); 1814 assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
1821 // Search for objects which are not scalar replaceable. 1815 InitializeNode* ini = alloc->as_Allocate()->initialization();
1822 // Mark their escape state as ArgEscape to propagate the state
1823 // to referenced objects.
1824 // Note: currently there are no difference in compiler optimizations
1825 // for ArgEscape objects and NoEscape objects which are not
1826 // scalar replaceable.
1827 1816
1828 Compile* C = _compile; 1817 Compile* C = _compile;
1829 1818 visited->Reset();
1830 int offset = ptn->offset();
1831 Node* base = get_addp_base(n);
1832 VectorSet* ptset = PointsTo(base);
1833 int ptset_size = ptset->Size();
1834
1835 // Check if a oop field's initializing value is recorded and add 1819 // Check if a oop field's initializing value is recorded and add
1836 // a corresponding NULL field's value if it is not recorded. 1820 // a corresponding NULL field's value if it is not recorded.
1837 // Connection Graph does not record a default initialization by NULL 1821 // Connection Graph does not record a default initialization by NULL
1838 // captured by Initialize node. 1822 // captured by Initialize node.
1839 // 1823 //
1840 // Note: it will disable scalar replacement in some cases: 1824 uint ae_cnt = pta->edge_count();
1841 // 1825 for (uint ei = 0; ei < ae_cnt; ei++) {
1842 // Point p[] = new Point[1]; 1826 uint nidx = pta->edge_target(ei); // Field (AddP)
1843 // p[0] = new Point(); // Will be not scalar replaced 1827 PointsToNode* ptn = ptnode_adr(nidx);
1844 // 1828 assert(ptn->_node->is_AddP(), "Should be AddP nodes only");
1845 // but it will save us from incorrect optimizations in next cases: 1829 int offset = ptn->offset();
1846 // 1830 if (offset != Type::OffsetBot &&
1847 // Point p[] = new Point[1]; 1831 offset != oopDesc::klass_offset_in_bytes() &&
1848 // if ( x ) p[0] = new Point(); // Will be not scalar replaced 1832 !visited->test_set(offset)) {
1849 //
1850 // Do a simple control flow analysis to distinguish above cases.
1851 //
1852 if (offset != Type::OffsetBot && ptset_size == 1) {
1853 uint elem = ptset->getelem(); // Allocation node's index
1854 // It does not matter if it is not Allocation node since
1855 // only non-escaping allocations are scalar replaced.
1856 if (ptnode_adr(elem)->_node->is_Allocate() &&
1857 ptnode_adr(elem)->escape_state() == PointsToNode::NoEscape) {
1858 AllocateNode* alloc = ptnode_adr(elem)->_node->as_Allocate();
1859 InitializeNode* ini = alloc->initialization();
1860 1833
1861 // Check only oop fields. 1834 // Check only oop fields.
1862 const Type* adr_type = n->as_AddP()->bottom_type(); 1835 const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
1863 BasicType basic_field_type = T_INT; 1836 BasicType basic_field_type = T_INT;
1864 if (adr_type->isa_instptr()) { 1837 if (adr_type->isa_instptr()) {
1865 ciField* field = C->alias_type(adr_type->isa_instptr())->field(); 1838 ciField* field = C->alias_type(adr_type->isa_instptr())->field();
1866 if (field != NULL) { 1839 if (field != NULL) {
1867 basic_field_type = field->layout_type(); 1840 basic_field_type = field->layout_type();
1868 } else { 1841 } else {
1869 // Ignore non field load (for example, klass load) 1842 // Ignore non field load (for example, klass load)
1870 } 1843 }
1871 } else if (adr_type->isa_aryptr()) { 1844 } else if (adr_type->isa_aryptr()) {
1872 const Type* elemtype = adr_type->isa_aryptr()->elem(); 1845 if (offset != arrayOopDesc::length_offset_in_bytes()) {
1873 basic_field_type = elemtype->array_element_basic_type(); 1846 const Type* elemtype = adr_type->isa_aryptr()->elem();
1847 basic_field_type = elemtype->array_element_basic_type();
1848 } else {
1849 // Ignore array length load
1850 }
1851 #ifdef ASSERT
1874 } else { 1852 } else {
1875 // Raw pointers are used for initializing stores so skip it. 1853 // Raw pointers are used for initializing stores so skip it
1854 // since it should be recorded already
1855 Node* base = get_addp_base(ptn->_node);
1876 assert(adr_type->isa_rawptr() && base->is_Proj() && 1856 assert(adr_type->isa_rawptr() && base->is_Proj() &&
1877 (base->in(0) == alloc),"unexpected pointer type"); 1857 (base->in(0) == alloc),"unexpected pointer type");
1858 #endif
1878 } 1859 }
1879 if (basic_field_type == T_OBJECT || 1860 if (basic_field_type == T_OBJECT ||
1880 basic_field_type == T_NARROWOOP || 1861 basic_field_type == T_NARROWOOP ||
1881 basic_field_type == T_ARRAY) { 1862 basic_field_type == T_ARRAY) {
1882 Node* value = NULL; 1863 Node* value = NULL;
1887 value = store->in(MemNode::ValueIn); 1868 value = store->in(MemNode::ValueIn);
1888 } else if (ptn->edge_count() > 0) { // Are there oop stores? 1869 } else if (ptn->edge_count() > 0) { // Are there oop stores?
1889 // Check for a store which follows allocation without branches. 1870 // Check for a store which follows allocation without branches.
1890 // For example, a volatile field store is not collected 1871 // For example, a volatile field store is not collected
1891 // by Initialize node. TODO: it would be nice to use idom() here. 1872 // by Initialize node. TODO: it would be nice to use idom() here.
1892 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { 1873 //
1893 store = n->fast_out(i); 1874 // Search all references to the same field which use different
1894 if (store->is_Store() && store->in(0) != NULL) { 1875 // AddP nodes, for example, in the next case:
1895 Node* ctrl = store->in(0); 1876 //
1896 while(!(ctrl == ini || ctrl == alloc || ctrl == NULL || 1877 // Point p[] = new Point[1];
1897 ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() || 1878 // if ( x ) { p[0] = new Point(); p[0].x = x; }
1898 ctrl->is_IfTrue() || ctrl->is_IfFalse())) { 1879 // if ( p[0] != null ) { y = p[0].x; } // has CastPP
1899 ctrl = ctrl->in(0); 1880 //
1900 } 1881 for (uint next = ei; (next < ae_cnt) && (value == NULL); next++) {
1901 if (ctrl == ini || ctrl == alloc) { 1882 uint fpi = pta->edge_target(next); // Field (AddP)
1902 value = store->in(MemNode::ValueIn); 1883 PointsToNode *ptf = ptnode_adr(fpi);
1903 break; 1884 if (ptf->offset() == offset) {
1885 Node* nf = ptf->_node;
1886 for (DUIterator_Fast imax, i = nf->fast_outs(imax); i < imax; i++) {
1887 store = nf->fast_out(i);
1888 if (store->is_Store() && store->in(0) != NULL) {
1889 Node* ctrl = store->in(0);
1890 while(!(ctrl == ini || ctrl == alloc || ctrl == NULL ||
1891 ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() ||
1892 ctrl->is_IfTrue() || ctrl->is_IfFalse())) {
1893 ctrl = ctrl->in(0);
1894 }
1895 if (ctrl == ini || ctrl == alloc) {
1896 value = store->in(MemNode::ValueIn);
1897 break;
1898 }
1899 }
1904 } 1900 }
1905 } 1901 }
1906 } 1902 }
1907 } 1903 }
1908 } 1904 }
1909 if (value == NULL || value != ptnode_adr(value->_idx)->_node) { 1905 if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
1910 // A field's initializing value was not recorded. Add NULL. 1906 // A field's initializing value was not recorded. Add NULL.
1911 uint null_idx = UseCompressedOops ? _noop_null : _oop_null; 1907 uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
1912 add_pointsto_edge(nidx, null_idx); 1908 add_edge_from_fields(alloc->_idx, null_idx, offset);
1913 } 1909 }
1914 } 1910 }
1915 } 1911 }
1916 } 1912 }
1913 }
1914
1915 // Adjust escape state after Connection Graph is built.
1916 void ConnectionGraph::adjust_escape_state(Node* n) {
1917 PointsToNode* ptn = ptnode_adr(n->_idx);
1918 assert(n->is_AddP(), "Should be called for AddP nodes only");
1919 // Search for objects which are not scalar replaceable
1920 // and mark them to propagate the state to referenced objects.
1921 //
1922
1923 int offset = ptn->offset();
1924 Node* base = get_addp_base(n);
1925 VectorSet* ptset = PointsTo(base);
1926 int ptset_size = ptset->Size();
1917 1927
1918 // An object is not scalar replaceable if the field which may point 1928 // An object is not scalar replaceable if the field which may point
1919 // to it has unknown offset (unknown element of an array of objects). 1929 // to it has unknown offset (unknown element of an array of objects).
1920 // 1930 //
1931
1921 if (offset == Type::OffsetBot) { 1932 if (offset == Type::OffsetBot) {
1922 uint e_cnt = ptn->edge_count(); 1933 uint e_cnt = ptn->edge_count();
1923 for (uint ei = 0; ei < e_cnt; ei++) { 1934 for (uint ei = 0; ei < e_cnt; ei++) {
1924 uint npi = ptn->edge_target(ei); 1935 uint npi = ptn->edge_target(ei);
1925 set_escape_state(npi, PointsToNode::ArgEscape); 1936 ptnode_adr(npi)->set_scalar_replaceable(false);
1926 ptnode_adr(npi)->_scalar_replaceable = false;
1927 } 1937 }
1928 } 1938 }
1929 1939
1930 // Currently an object is not scalar replaceable if a LoadStore node 1940 // Currently an object is not scalar replaceable if a LoadStore node
1931 // access its field since the field value is unknown after it. 1941 // access its field since the field value is unknown after it.
1940 } 1950 }
1941 // An object is not scalar replaceable if the address points 1951 // An object is not scalar replaceable if the address points
1942 // to unknown field (unknown element for arrays, offset is OffsetBot). 1952 // to unknown field (unknown element for arrays, offset is OffsetBot).
1943 // 1953 //
1944 // Or the address may point to more then one object. This may produce 1954 // Or the address may point to more then one object. This may produce
1945 // the false positive result (set scalar_replaceable to false) 1955 // the false positive result (set not scalar replaceable)
1946 // since the flow-insensitive escape analysis can't separate 1956 // since the flow-insensitive escape analysis can't separate
1947 // the case when stores overwrite the field's value from the case 1957 // the case when stores overwrite the field's value from the case
1948 // when stores happened on different control branches. 1958 // when stores happened on different control branches.
1949 // 1959 //
1960 // Note: it will disable scalar replacement in some cases:
1961 //
1962 // Point p[] = new Point[1];
1963 // p[0] = new Point(); // Will be not scalar replaced
1964 //
1965 // but it will save us from incorrect optimizations in next cases:
1966 //
1967 // Point p[] = new Point[1];
1968 // if ( x ) p[0] = new Point(); // Will be not scalar replaced
1969 //
1950 if (ptset_size > 1 || ptset_size != 0 && 1970 if (ptset_size > 1 || ptset_size != 0 &&
1951 (has_LoadStore || offset == Type::OffsetBot)) { 1971 (has_LoadStore || offset == Type::OffsetBot)) {
1952 for( VectorSetI j(ptset); j.test(); ++j ) { 1972 for( VectorSetI j(ptset); j.test(); ++j ) {
1953 set_escape_state(j.elem, PointsToNode::ArgEscape); 1973 ptnode_adr(j.elem)->set_scalar_replaceable(false);
1954 ptnode_adr(j.elem)->_scalar_replaceable = false; 1974 }
1955 } 1975 }
1956 } 1976 }
1977
1978 // Propagate escape states to referenced nodes.
1979 bool ConnectionGraph::propagate_escape_state(GrowableArray<int>* cg_worklist,
1980 GrowableArray<uint>* worklist,
1981 PointsToNode::EscapeState esc_state) {
1982 bool has_java_obj = false;
1983
1984 // push all nodes with the same escape state on the worklist
1985 uint cg_length = cg_worklist->length();
1986 for (uint next = 0; next < cg_length; ++next) {
1987 int nk = cg_worklist->at(next);
1988 if (ptnode_adr(nk)->escape_state() == esc_state)
1989 worklist->push(nk);
1990 }
1991 // mark all reachable nodes
1992 while (worklist->length() > 0) {
1993 PointsToNode* ptn = ptnode_adr(worklist->pop());
1994 if (ptn->node_type() == PointsToNode::JavaObject) {
1995 has_java_obj = true;
1996 }
1997 uint e_cnt = ptn->edge_count();
1998 for (uint ei = 0; ei < e_cnt; ei++) {
1999 uint npi = ptn->edge_target(ei);
2000 PointsToNode *np = ptnode_adr(npi);
2001 if (np->escape_state() < esc_state) {
2002 set_escape_state(npi, esc_state);
2003 worklist->push(npi);
2004 }
2005 }
2006 }
2007 // Has not escaping java objects
2008 return has_java_obj && (esc_state < PointsToNode::GlobalEscape);
1957 } 2009 }
1958 2010
1959 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) { 2011 void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) {
1960 2012
1961 switch (call->Opcode()) { 2013 switch (call->Opcode()) {
2110 es = PointsToNode::GlobalEscape; 2162 es = PointsToNode::GlobalEscape;
2111 edge_to = _phantom_object; // Could not be worse 2163 edge_to = _phantom_object; // Could not be worse
2112 } else { 2164 } else {
2113 es = PointsToNode::NoEscape; 2165 es = PointsToNode::NoEscape;
2114 edge_to = call_idx; 2166 edge_to = call_idx;
2167 assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
2115 } 2168 }
2116 set_escape_state(call_idx, es); 2169 set_escape_state(call_idx, es);
2117 add_pointsto_edge(resproj_idx, edge_to); 2170 add_pointsto_edge(resproj_idx, edge_to);
2118 _processed.set(resproj_idx); 2171 _processed.set(resproj_idx);
2119 break; 2172 break;
2133 es = PointsToNode::GlobalEscape; 2186 es = PointsToNode::GlobalEscape;
2134 edge_to = _phantom_object; 2187 edge_to = _phantom_object;
2135 } else { 2188 } else {
2136 es = PointsToNode::NoEscape; 2189 es = PointsToNode::NoEscape;
2137 edge_to = call_idx; 2190 edge_to = call_idx;
2191 assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
2138 int length = call->in(AllocateNode::ALength)->find_int_con(-1); 2192 int length = call->in(AllocateNode::ALength)->find_int_con(-1);
2139 if (length < 0 || length > EliminateAllocationArraySizeLimit) { 2193 if (length < 0 || length > EliminateAllocationArraySizeLimit) {
2140 // Not scalar replaceable if the length is not constant or too big. 2194 // Not scalar replaceable if the length is not constant or too big.
2141 ptnode_adr(call_idx)->_scalar_replaceable = false; 2195 ptnode_adr(call_idx)->set_scalar_replaceable(false);
2142 } 2196 }
2143 } 2197 }
2144 set_escape_state(call_idx, es); 2198 set_escape_state(call_idx, es);
2145 add_pointsto_edge(resproj_idx, edge_to); 2199 add_pointsto_edge(resproj_idx, edge_to);
2146 _processed.set(resproj_idx); 2200 _processed.set(resproj_idx);
2178 // Returns a newly allocated unescaped object, simply 2232 // Returns a newly allocated unescaped object, simply
2179 // update dependency information. 2233 // update dependency information.
2180 // Mark it as NoEscape so that objects referenced by 2234 // Mark it as NoEscape so that objects referenced by
2181 // it's fields will be marked as NoEscape at least. 2235 // it's fields will be marked as NoEscape at least.
2182 set_escape_state(call_idx, PointsToNode::NoEscape); 2236 set_escape_state(call_idx, PointsToNode::NoEscape);
2237 ptnode_adr(call_idx)->set_scalar_replaceable(false);
2183 add_pointsto_edge(resproj_idx, call_idx); 2238 add_pointsto_edge(resproj_idx, call_idx);
2184 copy_dependencies = true; 2239 copy_dependencies = true;
2185 } else if (call_analyzer->is_return_local()) { 2240 } else if (call_analyzer->is_return_local()) {
2186 // determine whether any arguments are returned 2241 // determine whether any arguments are returned
2187 set_escape_state(call_idx, PointsToNode::NoEscape); 2242 set_escape_state(call_idx, PointsToNode::ArgEscape);
2188 bool ret_arg = false; 2243 bool ret_arg = false;
2189 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { 2244 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
2190 const Type* at = d->field_at(i); 2245 const Type* at = d->field_at(i);
2191 2246
2192 if (at->isa_oopptr() != NULL) { 2247 if (at->isa_oopptr() != NULL) {
2199 done = false; 2254 done = false;
2200 else if (arg_esp->node_type() == PointsToNode::JavaObject) 2255 else if (arg_esp->node_type() == PointsToNode::JavaObject)
2201 add_pointsto_edge(resproj_idx, arg->_idx); 2256 add_pointsto_edge(resproj_idx, arg->_idx);
2202 else 2257 else
2203 add_deferred_edge(resproj_idx, arg->_idx); 2258 add_deferred_edge(resproj_idx, arg->_idx);
2204 arg_esp->_hidden_alias = true;
2205 } 2259 }
2206 } 2260 }
2207 } 2261 }
2208 if (done && !ret_arg) { 2262 if (done && !ret_arg) {
2209 // Returns unknown object. 2263 // Returns unknown object.
2210 set_escape_state(call_idx, PointsToNode::GlobalEscape); 2264 set_escape_state(call_idx, PointsToNode::GlobalEscape);
2211 add_pointsto_edge(resproj_idx, _phantom_object); 2265 add_pointsto_edge(resproj_idx, _phantom_object);
2212 } 2266 }
2213 copy_dependencies = true; 2267 if (done) {
2268 copy_dependencies = true;
2269 }
2214 } else { 2270 } else {
2215 set_escape_state(call_idx, PointsToNode::GlobalEscape); 2271 set_escape_state(call_idx, PointsToNode::GlobalEscape);
2216 add_pointsto_edge(resproj_idx, _phantom_object); 2272 add_pointsto_edge(resproj_idx, _phantom_object);
2217 for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
2218 const Type* at = d->field_at(i);
2219 if (at->isa_oopptr() != NULL) {
2220 Node *arg = call->in(i)->uncast();
2221 PointsToNode *arg_esp = ptnode_adr(arg->_idx);
2222 arg_esp->_hidden_alias = true;
2223 }
2224 }
2225 } 2273 }
2226 if (copy_dependencies) 2274 if (copy_dependencies)
2227 call_analyzer->copy_dependencies(_compile->dependencies()); 2275 call_analyzer->copy_dependencies(_compile->dependencies());
2228 } 2276 }
2229 if (done) 2277 if (done)

mercurial