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 |
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; |
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 |
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()) { |
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) |