1.1 --- a/src/share/vm/oops/instanceKlass.cpp Tue Jul 01 09:03:55 2014 +0200 1.2 +++ b/src/share/vm/oops/instanceKlass.cpp Mon Jul 07 10:12:40 2014 +0200 1.3 @@ -289,6 +289,7 @@ 1.4 set_static_oop_field_count(0); 1.5 set_nonstatic_field_size(0); 1.6 set_is_marked_dependent(false); 1.7 + set_has_unloaded_dependent(false); 1.8 set_init_state(InstanceKlass::allocated); 1.9 set_init_thread(NULL); 1.10 set_reference_type(rt); 1.11 @@ -1819,6 +1820,9 @@ 1.12 return id; 1.13 } 1.14 1.15 +int nmethodBucket::decrement() { 1.16 + return Atomic::add(-1, (volatile int *)&_count); 1.17 +} 1.18 1.19 // 1.20 // Walk the list of dependent nmethods searching for nmethods which 1.21 @@ -1833,7 +1837,7 @@ 1.22 nmethod* nm = b->get_nmethod(); 1.23 // since dependencies aren't removed until an nmethod becomes a zombie, 1.24 // the dependency list may contain nmethods which aren't alive. 1.25 - if (nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) { 1.26 + if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) { 1.27 if (TraceDependencies) { 1.28 ResourceMark rm; 1.29 tty->print_cr("Marked for deoptimization"); 1.30 @@ -1850,6 +1854,43 @@ 1.31 return found; 1.32 } 1.33 1.34 +void InstanceKlass::clean_dependent_nmethods() { 1.35 + assert_locked_or_safepoint(CodeCache_lock); 1.36 + 1.37 + if (has_unloaded_dependent()) { 1.38 + nmethodBucket* b = _dependencies; 1.39 + nmethodBucket* last = NULL; 1.40 + while (b != NULL) { 1.41 + assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); 1.42 + 1.43 + nmethodBucket* next = b->next(); 1.44 + 1.45 + if (b->count() == 0) { 1.46 + if (last == NULL) { 1.47 + _dependencies = next; 1.48 + } else { 1.49 + last->set_next(next); 1.50 + } 1.51 + delete b; 1.52 + // last stays the same. 1.53 + } else { 1.54 + last = b; 1.55 + } 1.56 + 1.57 + b = next; 1.58 + } 1.59 + set_has_unloaded_dependent(false); 1.60 + } 1.61 +#ifdef ASSERT 1.62 + else { 1.63 + // Verification 1.64 + for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) { 1.65 + assert(b->count() >= 0, err_msg("bucket count: %d", b->count())); 1.66 + assert(b->count() != 0, "empty buckets need to be cleaned"); 1.67 + } 1.68 + } 1.69 +#endif 1.70 +} 1.71 1.72 // 1.73 // Add an nmethodBucket to the list of dependencies for this nmethod. 1.74 @@ -1884,13 +1925,10 @@ 1.75 nmethodBucket* last = NULL; 1.76 while (b != NULL) { 1.77 if (nm == b->get_nmethod()) { 1.78 - if (b->decrement() == 0) { 1.79 - if (last == NULL) { 1.80 - _dependencies = b->next(); 1.81 - } else { 1.82 - last->set_next(b->next()); 1.83 - } 1.84 - delete b; 1.85 + int val = b->decrement(); 1.86 + guarantee(val >= 0, err_msg("Underflow: %d", val)); 1.87 + if (val == 0) { 1.88 + set_has_unloaded_dependent(true); 1.89 } 1.90 return; 1.91 } 1.92 @@ -1929,6 +1967,11 @@ 1.93 nmethodBucket* b = _dependencies; 1.94 while (b != NULL) { 1.95 if (nm == b->get_nmethod()) { 1.96 +#ifdef ASSERT 1.97 + int count = b->count(); 1.98 + assert(count >= 0, "Just check if we ever get here 1"); 1.99 + assert(count > 0, "Just check if we ever get here 2"); 1.100 +#endif 1.101 return true; 1.102 } 1.103 b = b->next(); 1.104 @@ -2227,7 +2270,7 @@ 1.105 #endif // INCLUDE_ALL_GCS 1.106 1.107 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { 1.108 - assert(is_loader_alive(is_alive), "this klass should be live"); 1.109 + assert(class_loader_data()->is_alive(is_alive), "this klass should be live"); 1.110 if (is_interface()) { 1.111 if (ClassUnloading) { 1.112 Klass* impl = implementor();