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)) {