Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/macro.cpp @ 4777:e9a5e0a812c8
7125896: Eliminate nested locks
Summary: Nested locks elimination done before lock nodes expansion by looking for outer locks of the same object.
Reviewed-by: never, twisti
author | kvn |
---|---|
date | Sat, 07 Jan 2012 13:26:43 -0800 |
parents | 9c87bcb3b4dd |
children | 35acf8f0a2e4 |
comparison
equal
deleted
inserted
replaced
4776:5da7201222d5 | 4777:e9a5e0a812c8 |
---|---|
1787 expand_allocate_common(alloc, length, | 1787 expand_allocate_common(alloc, length, |
1788 OptoRuntime::new_array_Type(), | 1788 OptoRuntime::new_array_Type(), |
1789 slow_call_address); | 1789 slow_call_address); |
1790 } | 1790 } |
1791 | 1791 |
1792 //-----------------------mark_eliminated_locking_nodes----------------------- | 1792 //-------------------mark_eliminated_box---------------------------------- |
1793 // | |
1793 // During EA obj may point to several objects but after few ideal graph | 1794 // During EA obj may point to several objects but after few ideal graph |
1794 // transformations (CCP) it may point to only one non escaping object | 1795 // transformations (CCP) it may point to only one non escaping object |
1795 // (but still using phi), corresponding locks and unlocks will be marked | 1796 // (but still using phi), corresponding locks and unlocks will be marked |
1796 // for elimination. Later obj could be replaced with a new node (new phi) | 1797 // for elimination. Later obj could be replaced with a new node (new phi) |
1797 // and which does not have escape information. And later after some graph | 1798 // and which does not have escape information. And later after some graph |
1798 // reshape other locks and unlocks (which were not marked for elimination | 1799 // reshape other locks and unlocks (which were not marked for elimination |
1799 // before) are connected to this new obj (phi) but they still will not be | 1800 // before) are connected to this new obj (phi) but they still will not be |
1800 // marked for elimination since new obj has no escape information. | 1801 // marked for elimination since new obj has no escape information. |
1801 // Mark all associated (same box and obj) lock and unlock nodes for | 1802 // Mark all associated (same box and obj) lock and unlock nodes for |
1802 // elimination if some of them marked already. | 1803 // elimination if some of them marked already. |
1804 void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { | |
1805 if (oldbox->is_BoxLock() && oldbox->as_BoxLock()->is_eliminated()) | |
1806 return; | |
1807 | |
1808 if (oldbox->is_BoxLock() && | |
1809 oldbox->as_BoxLock()->is_simple_lock_region(NULL, obj)) { | |
1810 // Box is used only in one lock region. Mark this box as eliminated. | |
1811 _igvn.hash_delete(oldbox); | |
1812 oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value | |
1813 _igvn.hash_insert(oldbox); | |
1814 | |
1815 for (uint i = 0; i < oldbox->outcnt(); i++) { | |
1816 Node* u = oldbox->raw_out(i); | |
1817 if (u->is_AbstractLock() && !u->as_AbstractLock()->is_non_esc_obj()) { | |
1818 AbstractLockNode* alock = u->as_AbstractLock(); | |
1819 // Check lock's box since box could be referenced by Lock's debug info. | |
1820 if (alock->box_node() == oldbox) { | |
1821 assert(alock->obj_node() == obj, ""); | |
1822 // Mark eliminated all related locks and unlocks. | |
1823 alock->set_non_esc_obj(); | |
1824 } | |
1825 } | |
1826 } | |
1827 return; | |
1828 } | |
1829 | |
1830 // Create new "eliminated" BoxLock node and use it in monitor debug info | |
1831 // instead of oldbox for the same object. | |
1832 BoxLockNode* box = BoxLockNode::box_node(oldbox); | |
1833 BoxLockNode* newbox = box->clone()->as_BoxLock(); | |
1834 | |
1835 // Note: BoxLock node is marked eliminated only here and it is used | |
1836 // to indicate that all associated lock and unlock nodes are marked | |
1837 // for elimination. | |
1838 newbox->set_eliminated(); | |
1839 transform_later(newbox); | |
1840 | |
1841 // Replace old box node with new box for all users of the same object. | |
1842 for (uint i = 0; i < oldbox->outcnt();) { | |
1843 bool next_edge = true; | |
1844 | |
1845 Node* u = oldbox->raw_out(i); | |
1846 if (u->is_AbstractLock()) { | |
1847 AbstractLockNode* alock = u->as_AbstractLock(); | |
1848 if (alock->obj_node() == obj && alock->box_node() == oldbox) { | |
1849 // Replace Box and mark eliminated all related locks and unlocks. | |
1850 alock->set_non_esc_obj(); | |
1851 _igvn.hash_delete(alock); | |
1852 alock->set_box_node(newbox); | |
1853 _igvn._worklist.push(alock); | |
1854 next_edge = false; | |
1855 } | |
1856 } | |
1857 if (u->is_FastLock() && u->as_FastLock()->obj_node() == obj) { | |
1858 FastLockNode* flock = u->as_FastLock(); | |
1859 assert(flock->box_node() == oldbox, "sanity"); | |
1860 _igvn.hash_delete(flock); | |
1861 flock->set_box_node(newbox); | |
1862 _igvn._worklist.push(flock); | |
1863 next_edge = false; | |
1864 } | |
1865 | |
1866 // Replace old box in monitor debug info. | |
1867 if (u->is_SafePoint() && u->as_SafePoint()->jvms()) { | |
1868 SafePointNode* sfn = u->as_SafePoint(); | |
1869 JVMState* youngest_jvms = sfn->jvms(); | |
1870 int max_depth = youngest_jvms->depth(); | |
1871 for (int depth = 1; depth <= max_depth; depth++) { | |
1872 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1873 int num_mon = jvms->nof_monitors(); | |
1874 // Loop over monitors | |
1875 for (int idx = 0; idx < num_mon; idx++) { | |
1876 Node* obj_node = sfn->monitor_obj(jvms, idx); | |
1877 Node* box_node = sfn->monitor_box(jvms, idx); | |
1878 if (box_node == oldbox && obj_node == obj) { | |
1879 int j = jvms->monitor_box_offset(idx); | |
1880 _igvn.hash_delete(u); | |
1881 u->set_req(j, newbox); | |
1882 _igvn._worklist.push(u); | |
1883 next_edge = false; | |
1884 } | |
1885 } | |
1886 } | |
1887 } | |
1888 if (next_edge) i++; | |
1889 } | |
1890 } | |
1891 | |
1892 //-----------------------mark_eliminated_locking_nodes----------------------- | |
1803 void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { | 1893 void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { |
1804 if (!alock->is_eliminated()) { | 1894 if (EliminateNestedLocks) { |
1805 return; | 1895 if (alock->is_nested()) { |
1806 } | 1896 assert(alock->box_node()->as_BoxLock()->is_eliminated(), "sanity"); |
1807 if (!alock->is_coarsened()) { // Eliminated by EA | 1897 return; |
1808 // Create new "eliminated" BoxLock node and use it | 1898 } else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened |
1809 // in monitor debug info for the same object. | 1899 // Only Lock node has JVMState needed here. |
1810 BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); | 1900 if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) { |
1811 Node* obj = alock->obj_node(); | 1901 // Mark eliminated related nested locks and unlocks. |
1812 if (!oldbox->is_eliminated()) { | 1902 Node* obj = alock->obj_node(); |
1813 BoxLockNode* newbox = oldbox->clone()->as_BoxLock(); | 1903 BoxLockNode* box_node = alock->box_node()->as_BoxLock(); |
1904 assert(!box_node->is_eliminated(), "should not be marked yet"); | |
1814 // Note: BoxLock node is marked eliminated only here | 1905 // Note: BoxLock node is marked eliminated only here |
1815 // and it is used to indicate that all associated lock | 1906 // and it is used to indicate that all associated lock |
1816 // and unlock nodes are marked for elimination. | 1907 // and unlock nodes are marked for elimination. |
1817 newbox->set_eliminated(); | 1908 box_node->set_eliminated(); // Box's hash is always NO_HASH here |
1818 transform_later(newbox); | 1909 for (uint i = 0; i < box_node->outcnt(); i++) { |
1819 // Replace old box node with new box for all users | 1910 Node* u = box_node->raw_out(i); |
1820 // of the same object. | 1911 if (u->is_AbstractLock()) { |
1821 for (uint i = 0; i < oldbox->outcnt();) { | 1912 alock = u->as_AbstractLock(); |
1822 | 1913 if (alock->box_node() == box_node) { |
1823 bool next_edge = true; | 1914 // Verify that this Box is referenced only by related locks. |
1824 Node* u = oldbox->raw_out(i); | 1915 assert(alock->obj_node() == obj, ""); |
1825 if (u->is_AbstractLock() && | 1916 // Mark all related locks and unlocks. |
1826 u->as_AbstractLock()->obj_node() == obj && | 1917 alock->set_nested(); |
1827 u->as_AbstractLock()->box_node() == oldbox) { | 1918 } |
1828 // Mark all associated locks and unlocks. | |
1829 u->as_AbstractLock()->set_eliminated(); | |
1830 _igvn.hash_delete(u); | |
1831 u->set_req(TypeFunc::Parms + 1, newbox); | |
1832 next_edge = false; | |
1833 } | 1919 } |
1834 // Replace old box in monitor debug info. | 1920 } |
1835 if (u->is_SafePoint() && u->as_SafePoint()->jvms()) { | 1921 } |
1836 SafePointNode* sfn = u->as_SafePoint(); | 1922 return; |
1837 JVMState* youngest_jvms = sfn->jvms(); | 1923 } |
1838 int max_depth = youngest_jvms->depth(); | 1924 // Process locks for non escaping object |
1839 for (int depth = 1; depth <= max_depth; depth++) { | 1925 assert(alock->is_non_esc_obj(), ""); |
1840 JVMState* jvms = youngest_jvms->of_depth(depth); | 1926 } // EliminateNestedLocks |
1841 int num_mon = jvms->nof_monitors(); | 1927 |
1842 // Loop over monitors | 1928 if (alock->is_non_esc_obj()) { // Lock is used for non escaping object |
1843 for (int idx = 0; idx < num_mon; idx++) { | 1929 // Look for all locks of this object and mark them and |
1844 Node* obj_node = sfn->monitor_obj(jvms, idx); | 1930 // corresponding BoxLock nodes as eliminated. |
1845 Node* box_node = sfn->monitor_box(jvms, idx); | 1931 Node* obj = alock->obj_node(); |
1846 if (box_node == oldbox && obj_node == obj) { | 1932 for (uint j = 0; j < obj->outcnt(); j++) { |
1847 int j = jvms->monitor_box_offset(idx); | 1933 Node* o = obj->raw_out(j); |
1848 _igvn.hash_delete(u); | 1934 if (o->is_AbstractLock() && o->as_AbstractLock()->obj_node() == obj) { |
1849 u->set_req(j, newbox); | 1935 alock = o->as_AbstractLock(); |
1850 next_edge = false; | 1936 Node* box = alock->box_node(); |
1851 } | 1937 // Replace old box node with new eliminated box for all users |
1852 } // for (int idx = 0; | 1938 // of the same object and mark related locks as eliminated. |
1853 } // for (int depth = 1; | 1939 mark_eliminated_box(box, obj); |
1854 } // if (u->is_SafePoint() | 1940 } |
1855 if (next_edge) i++; | 1941 } |
1856 } // for (uint i = 0; i < oldbox->outcnt();) | 1942 } |
1857 } // if (!oldbox->is_eliminated()) | |
1858 } // if (!alock->is_coarsened()) | |
1859 } | 1943 } |
1860 | 1944 |
1861 // we have determined that this lock/unlock can be eliminated, we simply | 1945 // we have determined that this lock/unlock can be eliminated, we simply |
1862 // eliminate the node without expanding it. | 1946 // eliminate the node without expanding it. |
1863 // | 1947 // |
1868 | 1952 |
1869 if (!alock->is_eliminated()) { | 1953 if (!alock->is_eliminated()) { |
1870 return false; | 1954 return false; |
1871 } | 1955 } |
1872 #ifdef ASSERT | 1956 #ifdef ASSERT |
1873 if (alock->is_Lock() && !alock->is_coarsened()) { | 1957 if (!alock->is_coarsened()) { |
1874 // Check that new "eliminated" BoxLock node is created. | 1958 // Check that new "eliminated" BoxLock node is created. |
1875 BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); | 1959 BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); |
1876 assert(oldbox->is_eliminated(), "should be done already"); | 1960 assert(oldbox->is_eliminated(), "should be done already"); |
1877 } | 1961 } |
1878 #endif | 1962 #endif |
1959 Node* ctrl = lock->in(TypeFunc::Control); | 2043 Node* ctrl = lock->in(TypeFunc::Control); |
1960 Node* mem = lock->in(TypeFunc::Memory); | 2044 Node* mem = lock->in(TypeFunc::Memory); |
1961 Node* obj = lock->obj_node(); | 2045 Node* obj = lock->obj_node(); |
1962 Node* box = lock->box_node(); | 2046 Node* box = lock->box_node(); |
1963 Node* flock = lock->fastlock_node(); | 2047 Node* flock = lock->fastlock_node(); |
2048 | |
2049 assert(!BoxLockNode::box_node(box)->is_eliminated(), "sanity"); | |
1964 | 2050 |
1965 // Make the merge point | 2051 // Make the merge point |
1966 Node *region; | 2052 Node *region; |
1967 Node *mem_phi; | 2053 Node *mem_phi; |
1968 Node *slow_path; | 2054 Node *slow_path; |
2194 Node* ctrl = unlock->in(TypeFunc::Control); | 2280 Node* ctrl = unlock->in(TypeFunc::Control); |
2195 Node* mem = unlock->in(TypeFunc::Memory); | 2281 Node* mem = unlock->in(TypeFunc::Memory); |
2196 Node* obj = unlock->obj_node(); | 2282 Node* obj = unlock->obj_node(); |
2197 Node* box = unlock->box_node(); | 2283 Node* box = unlock->box_node(); |
2198 | 2284 |
2285 assert(!BoxLockNode::box_node(box)->is_eliminated(), "sanity"); | |
2286 | |
2199 // No need for a null check on unlock | 2287 // No need for a null check on unlock |
2200 | 2288 |
2201 // Make the merge point | 2289 // Make the merge point |
2202 Node *region; | 2290 Node *region; |
2203 Node *mem_phi; | 2291 Node *mem_phi; |