src/share/vm/oops/instanceKlass.cpp
Print this page
*** 243,252 ****
--- 243,253 ----
set_array_name(NULL);
set_inner_classes(NULL);
set_static_oop_field_count(0);
set_nonstatic_field_size(0);
set_is_marked_dependent(false);
+ set_has_unloaded_dependent(false);
set_init_state(InstanceKlass::allocated);
set_init_thread(NULL);
set_reference_type(rt);
set_oop_map_cache(NULL);
set_jni_ids(NULL);
*** 1799,1808 ****
--- 1800,1812 ----
id = jmeths[idnum+1]; // Look up the id (may be NULL)
}
return id;
}
+ int nmethodBucket::decrement() {
+ return Atomic::add(-1, (volatile int *)&_count);
+ }
//
// Walk the list of dependent nmethods searching for nmethods which
// are dependent on the changes that were passed in and mark them for
// deoptimization. Returns the number of nmethods found.
*** 1813,1823 ****
nmethodBucket* b = _dependencies;
while (b != NULL) {
nmethod* nm = b->get_nmethod();
// since dependencies aren't removed until an nmethod becomes a zombie,
// the dependency list may contain nmethods which aren't alive.
! if (nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) {
if (TraceDependencies) {
ResourceMark rm;
tty->print_cr("Marked for deoptimization");
tty->print_cr(" context = %s", this->external_name());
changes.print();
--- 1817,1827 ----
nmethodBucket* b = _dependencies;
while (b != NULL) {
nmethod* nm = b->get_nmethod();
// since dependencies aren't removed until an nmethod becomes a zombie,
// the dependency list may contain nmethods which aren't alive.
! if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) {
if (TraceDependencies) {
ResourceMark rm;
tty->print_cr("Marked for deoptimization");
tty->print_cr(" context = %s", this->external_name());
changes.print();
*** 1830,1839 ****
--- 1834,1880 ----
b = b->next();
}
return found;
}
+ void InstanceKlass::clean_dependent_nmethods() {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ if (has_unloaded_dependent()) {
+ nmethodBucket* b = _dependencies;
+ nmethodBucket* last = NULL;
+ while (b != NULL) {
+ assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+
+ nmethodBucket* next = b->next();
+
+ if (b->count() == 0) {
+ if (last == NULL) {
+ _dependencies = next;
+ } else {
+ last->set_next(next);
+ }
+ delete b;
+ // last stays the same.
+ } else {
+ last = b;
+ }
+
+ b = next;
+ }
+ set_has_unloaded_dependent(false);
+ }
+ #ifdef ASSERT
+ else {
+ // Verification
+ for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) {
+ assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+ assert(b->count() != 0, "empty buckets need to be cleaned");
+ }
+ }
+ #endif
+ }
//
// Add an nmethodBucket to the list of dependencies for this nmethod.
// It's possible that an nmethod has multiple dependencies on this klass
// so a count is kept for each bucket to guarantee that creation and
*** 1864,1880 ****
assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL;
while (b != NULL) {
if (nm == b->get_nmethod()) {
! if (b->decrement() == 0) {
! if (last == NULL) {
! _dependencies = b->next();
! } else {
! last->set_next(b->next());
! }
! delete b;
}
return;
}
last = b;
b = b->next();
--- 1905,1918 ----
assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL;
while (b != NULL) {
if (nm == b->get_nmethod()) {
! int val = b->decrement();
! guarantee(val >= 0, err_msg("Underflow: %d", val));
! if (val == 0) {
! set_has_unloaded_dependent(true);
}
return;
}
last = b;
b = b->next();
*** 1909,1918 ****
--- 1947,1961 ----
bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
nmethodBucket* b = _dependencies;
while (b != NULL) {
if (nm == b->get_nmethod()) {
+ #ifdef ASSERT
+ int count = b->count();
+ assert(count >= 0, "Just check if we ever get here 1");
+ assert(count > 0, "Just check if we ever get here 2");
+ #endif
return true;
}
b = b->next();
}
return false;
*** 2207,2217 ****
}
#endif // INCLUDE_ALL_GCS
void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
! assert(is_loader_alive(is_alive), "this klass should be live");
if (is_interface()) {
if (ClassUnloading) {
Klass* impl = implementor();
if (impl != NULL) {
if (!impl->is_loader_alive(is_alive)) {
--- 2250,2260 ----
}
#endif // INCLUDE_ALL_GCS
void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
! assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
if (is_interface()) {
if (ClassUnloading) {
Klass* impl = implementor();
if (impl != NULL) {
if (!impl->is_loader_alive(is_alive)) {