Mercurial > hg > graal-jvmci-8
comparison src/share/vm/oops/instanceKlass.cpp @ 20278:2c6ef90f030a
8049421: G1 Class Unloading after completing a concurrent mark cycle
Reviewed-by: tschatzl, ehelin, brutisso, coleenp, roland, iveresov
Contributed-by: stefan.karlsson@oracle.com, mikael.gerdin@oracle.com
author | stefank |
---|---|
date | Mon, 07 Jul 2014 10:12:40 +0200 |
parents | 4c1b88a53c74 |
children | 870c03421152 |
comparison
equal
deleted
inserted
replaced
20277:882004b9e7e1 | 20278:2c6ef90f030a |
---|---|
287 set_array_name(NULL); | 287 set_array_name(NULL); |
288 set_inner_classes(NULL); | 288 set_inner_classes(NULL); |
289 set_static_oop_field_count(0); | 289 set_static_oop_field_count(0); |
290 set_nonstatic_field_size(0); | 290 set_nonstatic_field_size(0); |
291 set_is_marked_dependent(false); | 291 set_is_marked_dependent(false); |
292 set_has_unloaded_dependent(false); | |
292 set_init_state(InstanceKlass::allocated); | 293 set_init_state(InstanceKlass::allocated); |
293 set_init_thread(NULL); | 294 set_init_thread(NULL); |
294 set_reference_type(rt); | 295 set_reference_type(rt); |
295 set_oop_map_cache(NULL); | 296 set_oop_map_cache(NULL); |
296 set_jni_ids(NULL); | 297 set_jni_ids(NULL); |
1817 id = jmeths[idnum+1]; // Look up the id (may be NULL) | 1818 id = jmeths[idnum+1]; // Look up the id (may be NULL) |
1818 } | 1819 } |
1819 return id; | 1820 return id; |
1820 } | 1821 } |
1821 | 1822 |
1823 int nmethodBucket::decrement() { | |
1824 return Atomic::add(-1, (volatile int *)&_count); | |
1825 } | |
1822 | 1826 |
1823 // | 1827 // |
1824 // Walk the list of dependent nmethods searching for nmethods which | 1828 // Walk the list of dependent nmethods searching for nmethods which |
1825 // are dependent on the changes that were passed in and mark them for | 1829 // are dependent on the changes that were passed in and mark them for |
1826 // deoptimization. Returns the number of nmethods found. | 1830 // deoptimization. Returns the number of nmethods found. |
1831 nmethodBucket* b = _dependencies; | 1835 nmethodBucket* b = _dependencies; |
1832 while (b != NULL) { | 1836 while (b != NULL) { |
1833 nmethod* nm = b->get_nmethod(); | 1837 nmethod* nm = b->get_nmethod(); |
1834 // since dependencies aren't removed until an nmethod becomes a zombie, | 1838 // since dependencies aren't removed until an nmethod becomes a zombie, |
1835 // the dependency list may contain nmethods which aren't alive. | 1839 // the dependency list may contain nmethods which aren't alive. |
1836 if (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)) { |
1837 if (TraceDependencies) { | 1841 if (TraceDependencies) { |
1838 ResourceMark rm; | 1842 ResourceMark rm; |
1839 tty->print_cr("Marked for deoptimization"); | 1843 tty->print_cr("Marked for deoptimization"); |
1840 tty->print_cr(" context = %s", this->external_name()); | 1844 tty->print_cr(" context = %s", this->external_name()); |
1841 changes.print(); | 1845 changes.print(); |
1848 b = b->next(); | 1852 b = b->next(); |
1849 } | 1853 } |
1850 return found; | 1854 return found; |
1851 } | 1855 } |
1852 | 1856 |
1857 void InstanceKlass::clean_dependent_nmethods() { | |
1858 assert_locked_or_safepoint(CodeCache_lock); | |
1859 | |
1860 if (has_unloaded_dependent()) { | |
1861 nmethodBucket* b = _dependencies; | |
1862 nmethodBucket* last = NULL; | |
1863 while (b != NULL) { | |
1864 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); | |
1865 | |
1866 nmethodBucket* next = b->next(); | |
1867 | |
1868 if (b->count() == 0) { | |
1869 if (last == NULL) { | |
1870 _dependencies = next; | |
1871 } else { | |
1872 last->set_next(next); | |
1873 } | |
1874 delete b; | |
1875 // last stays the same. | |
1876 } else { | |
1877 last = b; | |
1878 } | |
1879 | |
1880 b = next; | |
1881 } | |
1882 set_has_unloaded_dependent(false); | |
1883 } | |
1884 #ifdef ASSERT | |
1885 else { | |
1886 // Verification | |
1887 for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) { | |
1888 assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); | |
1889 assert(b->count() != 0, "empty buckets need to be cleaned"); | |
1890 } | |
1891 } | |
1892 #endif | |
1893 } | |
1853 | 1894 |
1854 // | 1895 // |
1855 // Add an nmethodBucket to the list of dependencies for this nmethod. | 1896 // Add an nmethodBucket to the list of dependencies for this nmethod. |
1856 // It's possible that an nmethod has multiple dependencies on this klass | 1897 // It's possible that an nmethod has multiple dependencies on this klass |
1857 // so a count is kept for each bucket to guarantee that creation and | 1898 // so a count is kept for each bucket to guarantee that creation and |
1882 assert_locked_or_safepoint(CodeCache_lock); | 1923 assert_locked_or_safepoint(CodeCache_lock); |
1883 nmethodBucket* b = _dependencies; | 1924 nmethodBucket* b = _dependencies; |
1884 nmethodBucket* last = NULL; | 1925 nmethodBucket* last = NULL; |
1885 while (b != NULL) { | 1926 while (b != NULL) { |
1886 if (nm == b->get_nmethod()) { | 1927 if (nm == b->get_nmethod()) { |
1887 if (b->decrement() == 0) { | 1928 int val = b->decrement(); |
1888 if (last == NULL) { | 1929 guarantee(val >= 0, err_msg("Underflow: %d", val)); |
1889 _dependencies = b->next(); | 1930 if (val == 0) { |
1890 } else { | 1931 set_has_unloaded_dependent(true); |
1891 last->set_next(b->next()); | |
1892 } | |
1893 delete b; | |
1894 } | 1932 } |
1895 return; | 1933 return; |
1896 } | 1934 } |
1897 last = b; | 1935 last = b; |
1898 b = b->next(); | 1936 b = b->next(); |
1927 | 1965 |
1928 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { | 1966 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) { |
1929 nmethodBucket* b = _dependencies; | 1967 nmethodBucket* b = _dependencies; |
1930 while (b != NULL) { | 1968 while (b != NULL) { |
1931 if (nm == b->get_nmethod()) { | 1969 if (nm == b->get_nmethod()) { |
1970 #ifdef ASSERT | |
1971 int count = b->count(); | |
1972 assert(count >= 0, "Just check if we ever get here 1"); | |
1973 assert(count > 0, "Just check if we ever get here 2"); | |
1974 #endif | |
1932 return true; | 1975 return true; |
1933 } | 1976 } |
1934 b = b->next(); | 1977 b = b->next(); |
1935 } | 1978 } |
1936 return false; | 1979 return false; |
2225 } | 2268 } |
2226 | 2269 |
2227 #endif // INCLUDE_ALL_GCS | 2270 #endif // INCLUDE_ALL_GCS |
2228 | 2271 |
2229 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { | 2272 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { |
2230 assert(is_loader_alive(is_alive), "this klass should be live"); | 2273 assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); |
2231 if (is_interface()) { | 2274 if (is_interface()) { |
2232 if (ClassUnloading) { | 2275 if (ClassUnloading) { |
2233 Klass* impl = implementor(); | 2276 Klass* impl = implementor(); |
2234 if (impl != NULL) { | 2277 if (impl != NULL) { |
2235 if (!impl->is_loader_alive(is_alive)) { | 2278 if (!impl->is_loader_alive(is_alive)) { |