< prev index next >

src/share/vm/oops/instanceKlass.cpp

Print this page




1890 // Add an nmethodBucket to the list of dependencies for this nmethod.
1891 // It's possible that an nmethod has multiple dependencies on this klass
1892 // so a count is kept for each bucket to guarantee that creation and
1893 // deletion of dependencies is consistent. Returns new head of the list.
1894 //
1895 nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
1896   assert_locked_or_safepoint(CodeCache_lock);
1897   for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
1898     if (nm == b->get_nmethod()) {
1899       b->increment();
1900       return deps;
1901     }
1902   }
1903   return new nmethodBucket(nm, deps);
1904 }
1905 
1906 //
1907 // Decrement count of the nmethod in the dependency list and remove
1908 // the bucket completely when the count goes to 0.  This method must
1909 // find a corresponding bucket otherwise there's a bug in the
1910 // recording of dependencies. Returns true if the bucket is ready for reclamation.
1911 //
1912 bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
1913   assert_locked_or_safepoint(CodeCache_lock);
1914 
1915   for (nmethodBucket* b = deps; b != NULL; b = b->next()) {



1916     if (nm == b->get_nmethod()) {
1917       int val = b->decrement();
1918       guarantee(val >= 0, "Underflow: %d", val);
1919       return (val == 0);










1920     }

1921   }

1922 #ifdef ASSERT
1923   tty->print_raw_cr("### can't find dependent nmethod");
1924   nm->print();
1925 #endif // ASSERT
1926   ShouldNotReachHere();
1927   return false;
1928 }
1929 






1930 //
1931 // Reclaim all unused buckets. Returns new head of the list.
1932 //
1933 nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
1934   nmethodBucket* first = deps;
1935   nmethodBucket* last = NULL;
1936   nmethodBucket* b = first;
1937 
1938   while (b != NULL) {
1939     assert(b->count() >= 0, "bucket count: %d", b->count());
1940     nmethodBucket* next = b->next();
1941     if (b->count() == 0) {
1942       if (last == NULL) {
1943         first = next;
1944       } else {
1945         last->set_next(next);
1946       }
1947       delete b;
1948       // last stays the same.
1949     } else {


1996   if (has_unloaded_dependent()) {
1997     _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
1998     set_has_unloaded_dependent(false);
1999   }
2000 #ifdef ASSERT
2001   else {
2002     // Verification
2003     for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) {
2004       assert(b->count() >= 0, "bucket count: %d", b->count());
2005       assert(b->count() != 0, "empty buckets need to be cleaned");
2006     }
2007   }
2008 #endif
2009 }
2010 
2011 void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
2012   assert_locked_or_safepoint(CodeCache_lock);
2013   _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
2014 }
2015 
2016 void InstanceKlass::remove_dependent_nmethod(nmethod* nm) {
2017   assert_locked_or_safepoint(CodeCache_lock);
2018 
2019   if (nmethodBucket::remove_dependent_nmethod(_dependencies, nm)) {
2020     set_has_unloaded_dependent(true);
2021   }
2022 }
2023 
2024 #ifndef PRODUCT
2025 void InstanceKlass::print_dependent_nmethods(bool verbose) {
2026   nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
2027 }
2028 
2029 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
2030   return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
2031 }
2032 #endif //PRODUCT
2033 







2034 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
2035   assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
2036   if (is_interface()) {
2037     if (ClassUnloading) {
2038       Klass* impl = implementor();
2039       if (impl != NULL) {
2040         if (!impl->is_loader_alive(is_alive)) {
2041           // remove this guy
2042           Klass** klass = adr_implementor();
2043           assert(klass != NULL, "null klass");
2044           if (klass != NULL) {
2045             *klass = NULL;
2046           }
2047         }
2048       }
2049     }
2050   }
2051 }
2052 
2053 void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {


3529 }
3530 
3531 
3532 Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
3533   InstanceKlass* holder = get_klass_version(version);
3534   if (holder == NULL) {
3535     return NULL; // The version of klass is gone, no method is found
3536   }
3537   Method* method = holder->method_with_orig_idnum(idnum);
3538   return method;
3539 }
3540 
3541 
3542 jint InstanceKlass::get_cached_class_file_len() {
3543   return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
3544 }
3545 
3546 unsigned char * InstanceKlass::get_cached_class_file_bytes() {
3547   return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
3548 }






































































































































































































1890 // Add an nmethodBucket to the list of dependencies for this nmethod.
1891 // It's possible that an nmethod has multiple dependencies on this klass
1892 // so a count is kept for each bucket to guarantee that creation and
1893 // deletion of dependencies is consistent. Returns new head of the list.
1894 //
1895 nmethodBucket* nmethodBucket::add_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
1896   assert_locked_or_safepoint(CodeCache_lock);
1897   for (nmethodBucket* b = deps; b != NULL; b = b->next()) {
1898     if (nm == b->get_nmethod()) {
1899       b->increment();
1900       return deps;
1901     }
1902   }
1903   return new nmethodBucket(nm, deps);
1904 }
1905 
1906 //
1907 // Decrement count of the nmethod in the dependency list and remove
1908 // the bucket completely when the count goes to 0.  This method must
1909 // find a corresponding bucket otherwise there's a bug in the
1910 // recording of dependencies. Returns true if the bucket was deleted,
1911 // or marked ready for reclaimation.
1912 bool nmethodBucket::remove_dependent_nmethod(nmethodBucket** deps, nmethod* nm, bool delete_immediately) {
1913   assert_locked_or_safepoint(CodeCache_lock);
1914 
1915   nmethodBucket* first = *deps;
1916   nmethodBucket* last = NULL;
1917 
1918   for (nmethodBucket* b = first; b != NULL; b = b->next()) {
1919     if (nm == b->get_nmethod()) {
1920       int val = b->decrement();
1921       guarantee(val >= 0, "Underflow: %d", val);
1922       if (val == 0) {
1923         if (delete_immediately) {
1924           if (last == NULL) {
1925             *deps = b->next();
1926           } else {
1927             last->set_next(b->next());
1928           }
1929           delete b;
1930         }
1931       }
1932       return true;
1933     }
1934     last = b;
1935   }
1936 
1937 #ifdef ASSERT
1938   tty->print_raw_cr("### can't find dependent nmethod");
1939   nm->print();
1940 #endif // ASSERT
1941   ShouldNotReachHere();
1942   return false;
1943 }
1944 
1945 // Convenience overload, for callers that don't want to delete the nmethodBucket entry.
1946 bool nmethodBucket::remove_dependent_nmethod(nmethodBucket* deps, nmethod* nm) {
1947   nmethodBucket** deps_addr = &deps;
1948   return remove_dependent_nmethod(deps_addr, nm, false /* Don't delete */);
1949 }
1950 
1951 //
1952 // Reclaim all unused buckets. Returns new head of the list.
1953 //
1954 nmethodBucket* nmethodBucket::clean_dependent_nmethods(nmethodBucket* deps) {
1955   nmethodBucket* first = deps;
1956   nmethodBucket* last = NULL;
1957   nmethodBucket* b = first;
1958 
1959   while (b != NULL) {
1960     assert(b->count() >= 0, "bucket count: %d", b->count());
1961     nmethodBucket* next = b->next();
1962     if (b->count() == 0) {
1963       if (last == NULL) {
1964         first = next;
1965       } else {
1966         last->set_next(next);
1967       }
1968       delete b;
1969       // last stays the same.
1970     } else {


2017   if (has_unloaded_dependent()) {
2018     _dependencies = nmethodBucket::clean_dependent_nmethods(_dependencies);
2019     set_has_unloaded_dependent(false);
2020   }
2021 #ifdef ASSERT
2022   else {
2023     // Verification
2024     for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) {
2025       assert(b->count() >= 0, "bucket count: %d", b->count());
2026       assert(b->count() != 0, "empty buckets need to be cleaned");
2027     }
2028   }
2029 #endif
2030 }
2031 
2032 void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
2033   assert_locked_or_safepoint(CodeCache_lock);
2034   _dependencies = nmethodBucket::add_dependent_nmethod(_dependencies, nm);
2035 }
2036 
2037 void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
2038   assert_locked_or_safepoint(CodeCache_lock);
2039 
2040   if (nmethodBucket::remove_dependent_nmethod(&_dependencies, nm, delete_immediately)) {
2041     set_has_unloaded_dependent(true);
2042   }
2043 }
2044 
2045 #ifndef PRODUCT
2046 void InstanceKlass::print_dependent_nmethods(bool verbose) {
2047   nmethodBucket::print_dependent_nmethods(_dependencies, verbose);
2048 }
2049 
2050 bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
2051   return nmethodBucket::is_dependent_nmethod(_dependencies, nm);
2052 }
2053 #endif //PRODUCT
2054 
2055 void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
2056   clean_implementors_list(is_alive);
2057   clean_method_data(is_alive);
2058 
2059   clean_dependent_nmethods();
2060 }
2061 
2062 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
2063   assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
2064   if (is_interface()) {
2065     if (ClassUnloading) {
2066       Klass* impl = implementor();
2067       if (impl != NULL) {
2068         if (!impl->is_loader_alive(is_alive)) {
2069           // remove this guy
2070           Klass** klass = adr_implementor();
2071           assert(klass != NULL, "null klass");
2072           if (klass != NULL) {
2073             *klass = NULL;
2074           }
2075         }
2076       }
2077     }
2078   }
2079 }
2080 
2081 void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {


3557 }
3558 
3559 
3560 Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
3561   InstanceKlass* holder = get_klass_version(version);
3562   if (holder == NULL) {
3563     return NULL; // The version of klass is gone, no method is found
3564   }
3565   Method* method = holder->method_with_orig_idnum(idnum);
3566   return method;
3567 }
3568 
3569 
3570 jint InstanceKlass::get_cached_class_file_len() {
3571   return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
3572 }
3573 
3574 unsigned char * InstanceKlass::get_cached_class_file_bytes() {
3575   return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
3576 }
3577 
3578 
3579 /////////////// Unit tests ///////////////
3580 
3581 #ifndef PRODUCT
3582 
3583 class TestNmethodBucketContext {
3584  public:
3585   nmethod* _nmethodLast;
3586   nmethod* _nmethodMiddle;
3587   nmethod* _nmethodFirst;
3588 
3589   nmethodBucket* _bucketLast;
3590   nmethodBucket* _bucketMiddle;
3591   nmethodBucket* _bucketFirst;
3592 
3593   nmethodBucket* _bucketList;
3594 
3595   TestNmethodBucketContext() {
3596     CodeCache_lock->lock_without_safepoint_check();
3597 
3598     _nmethodLast   = reinterpret_cast<nmethod*>(0x8 * 0);
3599     _nmethodMiddle = reinterpret_cast<nmethod*>(0x8 * 1);
3600     _nmethodFirst  = reinterpret_cast<nmethod*>(0x8 * 2);
3601 
3602     _bucketLast   = new nmethodBucket(_nmethodLast,   NULL);
3603     _bucketMiddle = new nmethodBucket(_nmethodMiddle, _bucketLast);
3604     _bucketFirst  = new nmethodBucket(_nmethodFirst,   _bucketMiddle);
3605 
3606     _bucketList = _bucketFirst;
3607   }
3608 
3609   ~TestNmethodBucketContext() {
3610     delete _bucketLast;
3611     delete _bucketMiddle;
3612     delete _bucketFirst;
3613 
3614     CodeCache_lock->unlock();
3615   }
3616 };
3617 
3618 class TestNmethodBucket {
3619  public:
3620   static void testRemoveDependentNmethodFirstDeleteImmediately() {
3621     TestNmethodBucketContext c;
3622 
3623     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, true /* delete */);
3624 
3625     assert(c._bucketList == c._bucketMiddle, "check");
3626     assert(c._bucketList->next() == c._bucketLast, "check");
3627     assert(c._bucketList->next()->next() == NULL, "check");
3628 
3629     // Cleanup before context is deleted.
3630     c._bucketFirst = NULL;
3631   }
3632 
3633   static void testRemoveDependentNmethodMiddleDeleteImmediately() {
3634     TestNmethodBucketContext c;
3635 
3636     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, true /* delete */);
3637 
3638     assert(c._bucketList == c._bucketFirst, "check");
3639     assert(c._bucketList->next() == c._bucketLast, "check");
3640     assert(c._bucketList->next()->next() == NULL, "check");
3641 
3642     // Cleanup before context is deleted.
3643     c._bucketMiddle = NULL;
3644   }
3645 
3646   static void testRemoveDependentNmethodLastDeleteImmediately() {
3647     TestNmethodBucketContext c;
3648 
3649     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, true /* delete */);
3650 
3651     assert(c._bucketList == c._bucketFirst, "check");
3652     assert(c._bucketList->next() == c._bucketMiddle, "check");
3653     assert(c._bucketList->next()->next() == NULL, "check");
3654 
3655     // Cleanup before context is deleted.
3656     c._bucketLast = NULL;
3657   }
3658 
3659   static void testRemoveDependentNmethodFirstDeleteDeferred() {
3660     TestNmethodBucketContext c;
3661 
3662     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodFirst, false /* delete */);
3663 
3664     assert(c._bucketList                         == c._bucketFirst,  "check");
3665     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3666     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3667     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3668 
3669     assert(c._bucketFirst->count()  == 0, "check");
3670     assert(c._bucketMiddle->count() == 1, "check");
3671     assert(c._bucketLast->count()   == 1, "check");
3672   }
3673 
3674   static void testRemoveDependentNmethodMiddleDeleteDeferred() {
3675     TestNmethodBucketContext c;
3676 
3677     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodMiddle, false /* delete */);
3678 
3679     assert(c._bucketList                         == c._bucketFirst,  "check");
3680     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3681     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3682     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3683 
3684     assert(c._bucketFirst->count()  == 1, "check");
3685     assert(c._bucketMiddle->count() == 0, "check");
3686     assert(c._bucketLast->count()   == 1, "check");
3687   }
3688 
3689   static void testRemoveDependentNmethodLastDeleteDeferred() {
3690     TestNmethodBucketContext c;
3691 
3692     nmethodBucket::remove_dependent_nmethod(&c._bucketList, c._nmethodLast, false /* delete */);
3693 
3694     assert(c._bucketList                         == c._bucketFirst,  "check");
3695     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3696     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3697     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3698 
3699     assert(c._bucketFirst->count()  == 1, "check");
3700     assert(c._bucketMiddle->count() == 1, "check");
3701     assert(c._bucketLast->count()   == 0, "check");
3702   }
3703 
3704   static void testRemoveDependentNmethodConvenienceFirst() {
3705     TestNmethodBucketContext c;
3706 
3707     nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodFirst);
3708 
3709     assert(c._bucketList                         == c._bucketFirst,  "check");
3710     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3711     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3712     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3713 
3714     assert(c._bucketFirst->count()  == 0, "check");
3715     assert(c._bucketMiddle->count() == 1, "check");
3716     assert(c._bucketLast->count()   == 1, "check");
3717   }
3718 
3719   static void testRemoveDependentNmethodConvenienceMiddle() {
3720     TestNmethodBucketContext c;
3721 
3722     nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodMiddle);
3723 
3724     assert(c._bucketList                         == c._bucketFirst,  "check");
3725     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3726     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3727     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3728 
3729     assert(c._bucketFirst->count()  == 1, "check");
3730     assert(c._bucketMiddle->count() == 0, "check");
3731     assert(c._bucketLast->count()   == 1, "check");
3732   }
3733 
3734   static void testRemoveDependentNmethodConvenienceLast() {
3735     TestNmethodBucketContext c;
3736 
3737     nmethodBucket::remove_dependent_nmethod(c._bucketList, c._nmethodLast);
3738 
3739     assert(c._bucketList                         == c._bucketFirst,  "check");
3740     assert(c._bucketList->next()                 == c._bucketMiddle, "check");
3741     assert(c._bucketList->next()->next()         == c._bucketLast,   "check");
3742     assert(c._bucketList->next()->next()->next() == NULL,            "check");
3743 
3744     assert(c._bucketFirst->count()  == 1, "check");
3745     assert(c._bucketMiddle->count() == 1, "check");
3746     assert(c._bucketLast->count()   == 0, "check");
3747   }
3748 
3749   static void testRemoveDependentNmethod() {
3750     testRemoveDependentNmethodFirstDeleteImmediately();
3751     testRemoveDependentNmethodMiddleDeleteImmediately();
3752     testRemoveDependentNmethodLastDeleteImmediately();
3753 
3754     testRemoveDependentNmethodFirstDeleteDeferred();
3755     testRemoveDependentNmethodMiddleDeleteDeferred();
3756     testRemoveDependentNmethodLastDeleteDeferred();
3757 
3758     testRemoveDependentNmethodConvenienceFirst();
3759     testRemoveDependentNmethodConvenienceMiddle();
3760     testRemoveDependentNmethodConvenienceLast();
3761   }
3762 
3763   static void test() {
3764     testRemoveDependentNmethod();
3765   }
3766 };
3767 
3768 void TestNmethodBucket_test() {
3769   TestNmethodBucket::test();
3770 }
3771 
3772 #endif
< prev index next >