1828 // |
1828 // |
1829 // Walk the list of dependent nmethods searching for nmethods which |
1829 // Walk the list of dependent nmethods searching for nmethods which |
1830 // are dependent on the changes that were passed in and mark them for |
1830 // are dependent on the changes that were passed in and mark them for |
1831 // deoptimization. Returns the number of nmethods found. |
1831 // deoptimization. Returns the number of nmethods found. |
1832 // |
1832 // |
1833 int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { |
1833 int nmethodBucket::mark_dependent_nmethods(nmethodBucket* deps, DepChange& changes) { |
1834 assert_locked_or_safepoint(CodeCache_lock); |
1834 assert_locked_or_safepoint(CodeCache_lock); |
1835 int found = 0; |
1835 int found = 0; |
1836 nmethodBucket* b = _dependencies; |
1836 for (nmethodBucket* b = deps; b != NULL; b = b->next()) { |
1837 while (b != NULL) { |
|
1838 nmethod* nm = b->get_nmethod(); |
1837 nmethod* nm = b->get_nmethod(); |
1839 // since dependencies aren't removed until an nmethod becomes a zombie, |
1838 // since dependencies aren't removed until an nmethod becomes a zombie, |
1840 // the dependency list may contain nmethods which aren't alive. |
1839 // the dependency list may contain nmethods which aren't alive. |
1841 if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) { |
1840 if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) { |
1842 if (TraceDependencies) { |
1841 if (TraceDependencies) { |
1843 ResourceMark rm; |
1842 ResourceMark rm; |
1844 tty->print_cr("Marked for deoptimization"); |
1843 tty->print_cr("Marked for deoptimization"); |
1845 tty->print_cr(" context = %s", this->external_name()); |
|
1846 changes.print(); |
1844 changes.print(); |
1847 nm->print(); |
1845 nm->print(); |
1848 nm->print_dependencies(); |
1846 nm->print_dependencies(); |
1849 } |
1847 } |
1850 nm->mark_for_deoptimization(); |
1848 nm->mark_for_deoptimization(); |
1851 found++; |
1849 found++; |
1852 } |
1850 } |
1853 b = b->next(); |
|
1854 } |
1851 } |
1855 return found; |
1852 return found; |
1856 } |
|
1857 |
|
1858 void InstanceKlass::clean_dependent_nmethods() { |
|
1859 assert_locked_or_safepoint(CodeCache_lock); |
|
1860 |
|
1861 if (has_unloaded_dependent()) { |
|
1862 nmethodBucket* b = _dependencies; |
|
1863 nmethodBucket* last = NULL; |
|
1864 while (b != NULL) { |
|
1865 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); |
|
1866 |
|
1867 nmethodBucket* next = b->next(); |
|
1868 |
|
1869 if (b->count() == 0) { |
|
1870 if (last == NULL) { |
|
1871 _dependencies = next; |
|
1872 } else { |
|
1873 last->set_next(next); |
|
1874 } |
|
1875 delete b; |
|
1876 // last stays the same. |
|
1877 } else { |
|
1878 last = b; |
|
1879 } |
|
1880 |
|
1881 b = next; |
|
1882 } |
|
1883 set_has_unloaded_dependent(false); |
|
1884 } |
|
1885 #ifdef ASSERT |
|
1886 else { |
|
1887 // Verification |
|
1888 for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) { |
|
1889 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); |
|
1890 assert(b->count() != 0, "empty buckets need to be cleaned"); |
|
1891 } |
|
1892 } |
|
1893 #endif |
|
1894 } |
1853 } |
1895 |
1854 |
1896 // |
1855 // |
1897 // Add an nmethodBucket to the list of dependencies for this nmethod. |
1856 // Add an nmethodBucket to the list of dependencies for this nmethod. |
1898 // It's possible that an nmethod has multiple dependencies on this klass |
1857 // It's possible that an nmethod has multiple dependencies on this klass |
1899 // so a count is kept for each bucket to guarantee that creation and |
1858 // so a count is kept for each bucket to guarantee that creation and |
1900 // deletion of dependencies is consistent. |
1859 // deletion of dependencies is consistent. Returns new head of the list. |
1901 // |
1860 // |
1902 void InstanceKlass::add_dependent_nmethod(nmethod* nm) { |
1861 nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { |
1903 assert_locked_or_safepoint(CodeCache_lock); |
1862 assert_locked_or_safepoint(CodeCache_lock); |
1904 nmethodBucket* b = _dependencies; |
1863 for (nmethodBucket* b = deps; b != NULL; b = b->next()) { |
1905 nmethodBucket* last = NULL; |
|
1906 while (b != NULL) { |
|
1907 if (nm == b->get_nmethod()) { |
1864 if (nm == b->get_nmethod()) { |
1908 b->increment(); |
1865 b->increment(); |
1909 return; |
1866 return deps; |
1910 } |
1867 } |
1911 b = b->next(); |
1868 } |
1912 } |
1869 return new nmethodBucket(nm, deps); |
1913 _dependencies = new nmethodBucket(nm, _dependencies); |
1870 } |
1914 } |
|
1915 |
|
1916 |
1871 |
1917 // |
1872 // |
1918 // Decrement count of the nmethod in the dependency list and remove |
1873 // Decrement count of the nmethod in the dependency list and remove |
1919 // the bucket competely when the count goes to 0. This method must |
1874 // the bucket completely when the count goes to 0. This method must |
1920 // find a corresponding bucket otherwise there's a bug in the |
1875 // find a corresponding bucket otherwise there's a bug in the |
1921 // recording of dependecies. |
1876 // recording of dependencies. Returns true if the bucket is ready for reclamation. |
1922 // |
1877 // |
1923 void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { |
1878 bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { |
1924 assert_locked_or_safepoint(CodeCache_lock); |
1879 assert_locked_or_safepoint(CodeCache_lock); |
1925 nmethodBucket* b = _dependencies; |
1880 |
1926 nmethodBucket* last = NULL; |
1881 for (nmethodBucket* b = deps; b != NULL; b = b->next()) { |
1927 while (b != NULL) { |
|
1928 if (nm == b->get_nmethod()) { |
1882 if (nm == b->get_nmethod()) { |
1929 int val = b->decrement(); |
1883 int val = b->decrement(); |
1930 guarantee(val >= 0, err_msg("Underflow: %d", val)); |
1884 guarantee(val >= 0, err_msg("Underflow: %d", val)); |
1931 if (val == 0) { |
1885 return (val == 0); |
1932 set_has_unloaded_dependent(true); |
1886 } |
1933 } |
|
1934 return; |
|
1935 } |
|
1936 last = b; |
|
1937 b = b->next(); |
|
1938 } |
1887 } |
1939 #ifdef ASSERT |
1888 #ifdef ASSERT |
1940 tty->print_cr("### %s can't find dependent nmethod:", this->external_name()); |
1889 tty->print_raw_cr("### can't find dependent nmethod"); |
1941 nm->print(); |
1890 nm->print(); |
1942 #endif // ASSERT |
1891 #endif // ASSERT |
1943 ShouldNotReachHere(); |
1892 ShouldNotReachHere(); |
1944 } |
1893 return false; |
1945 |
1894 } |
|
1895 |
|
1896 // |
|
1897 // Reclaim all unused buckets. Returns new head of the list. |
|
1898 // |
|
1899 nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) { |
|
1900 nmethodBucket* first = deps; |
|
1901 nmethodBucket* last = NULL; |
|
1902 nmethodBucket* b = first; |
|
1903 |
|
1904 while (b != NULL) { |
|
1905 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); |
|
1906 nmethodBucket* next = b->next(); |
|
1907 if (b->count() == 0) { |
|
1908 if (last == NULL) { |
|
1909 first = next; |
|
1910 } else { |
|
1911 last->set_next(next); |
|
1912 } |
|
1913 delete b; |
|
1914 // last stays the same. |
|
1915 } else { |
|
1916 last = b; |
|
1917 } |
|
1918 b = next; |
|
1919 } |
|
1920 return first; |
|
1921 } |
1946 |
1922 |
1947 #ifndef PRODUCT |
1923 #ifndef PRODUCT |
1948 void InstanceKlass::print_dependent_nmethods(bool verbose) { |
1924 void nmethodBucket::print_dependent_nmethods(nmethodBucket* deps, bool verbose) { |
1949 nmethodBucket* b = _dependencies; |
|
1950 int idx = 0; |
1925 int idx = 0; |
1951 while (b != NULL) { |
1926 for (nmethodBucket* b = deps; b != NULL; b = b->next()) { |
1952 nmethod* nm = b->get_nmethod(); |
1927 nmethod* nm = b->get_nmethod(); |
1953 tty->print("[%d] count=%d { ", idx++, b->count()); |
1928 tty->print("[%d] count=%d { ", idx++, b->count()); |
1954 if (!verbose) { |
1929 if (!verbose) { |
1955 nm->print_on(tty, "nmethod"); |
1930 nm->print_on(tty, "nmethod"); |
1956 tty->print_cr(" } "); |
1931 tty->print_cr(" } "); |
1957 } else { |
1932 } else { |
1958 nm->print(); |
1933 nm->print(); |
1959 nm->print_dependencies(); |
1934 nm->print_dependencies(); |
1960 tty->print_cr("--- } "); |
1935 tty->print_cr("--- } "); |
1961 } |
1936 } |
1962 b = b->next(); |
1937 } |
1963 } |
1938 } |
1964 } |
1939 |
1965 |
1940 bool nmethodBucket::is_dependent_nmethod(nmethodBucket* deps, nmethod* nm) { |
1966 |
1941 for (nmethodBucket* b = deps; b != NULL; b = b->next()) { |
1967 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { |
|
1968 nmethodBucket* b = _dependencies; |
|
1969 while (b != NULL) { |
|
1970 if (nm == b->get_nmethod()) { |
1942 if (nm == b->get_nmethod()) { |
1971 #ifdef ASSERT |
1943 #ifdef ASSERT |
1972 int count = b->count(); |
1944 int count = b->count(); |
1973 assert(count >= 0, err_msg("count shouldn't be negative: %d", count)); |
1945 assert(count >= 0, err_msg("count shouldn't be negative: %d", count)); |
1974 #endif |
1946 #endif |
1975 return true; |
1947 return true; |
1976 } |
1948 } |
1977 b = b->next(); |
|
1978 } |
1949 } |
1979 return false; |
1950 return false; |
|
1951 } |
|
1952 #endif //PRODUCT |
|
1953 |
|
1954 int InstanceKlass::mark_dependent_nmethods(DepChange& changes) { |
|
1955 assert_locked_or_safepoint(CodeCache_lock); |
|
1956 return nmethodBucket::mark_dependent_nmethods(_dependencies, changes); |
|
1957 } |
|
1958 |
|
1959 void InstanceKlass::clean_dependent_nmethods() { |
|
1960 assert_locked_or_safepoint(CodeCache_lock); |
|
1961 |
|
1962 if (has_unloaded_dependent()) { |
|
1963 _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies); |
|
1964 set_has_unloaded_dependent(false); |
|
1965 } |
|
1966 #ifdef ASSERT |
|
1967 else { |
|
1968 // Verification |
|
1969 for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) { |
|
1970 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); |
|
1971 assert(b->count() != 0, "empty buckets need to be cleaned"); |
|
1972 } |
|
1973 } |
|
1974 #endif |
|
1975 } |
|
1976 |
|
1977 void InstanceKlass::add_dependent_nmethod(nmethod* nm) { |
|
1978 assert_locked_or_safepoint(CodeCache_lock); |
|
1979 _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm); |
|
1980 } |
|
1981 |
|
1982 void InstanceKlass::remove_dependent_nmethod(nmethod* nm) { |
|
1983 assert_locked_or_safepoint(CodeCache_lock); |
|
1984 |
|
1985 if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) { |
|
1986 set_has_unloaded_dependent(true); |
|
1987 } |
|
1988 } |
|
1989 |
|
1990 #ifndef PRODUCT |
|
1991 void InstanceKlass::print_dependent_nmethods(bool verbose) { |
|
1992 nmethodBucket::print_dependent_nmethods(_dependencies, verbose); |
|
1993 } |
|
1994 |
|
1995 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { |
|
1996 return nmethodBucket::is_dependent_nmethod(_dependencies, nm); |
1980 } |
1997 } |
1981 #endif //PRODUCT |
1998 #endif //PRODUCT |
1982 |
1999 |
1983 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { |
2000 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { |
1984 assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); |
2001 assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); |