aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/code/nmethod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/share/vm/code/nmethod.cpp')
-rw-r--r--src/share/vm/code/nmethod.cpp32
1 files changed, 24 insertions, 8 deletions
diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp
index b31ede05e..6ea39aea9 100644
--- a/src/share/vm/code/nmethod.cpp
+++ b/src/share/vm/code/nmethod.cpp
@@ -1148,9 +1148,20 @@ void nmethod::clear_inline_caches() {
}
}
+// Clear ICStubs of all compiled ICs
+void nmethod::clear_ic_stubs() {
+ assert_locked_or_safepoint(CompiledIC_lock);
+ RelocIterator iter(this);
+ while(iter.next()) {
+ if (iter.type() == relocInfo::virtual_call_type) {
+ CompiledIC* ic = CompiledIC_at(&iter);
+ ic->clear_ic_stub();
+ }
+ }
+}
-void nmethod::cleanup_inline_caches() {
+void nmethod::cleanup_inline_caches() {
assert_locked_or_safepoint(CompiledIC_lock);
// If the method is not entrant or zombie then a JMP is plastered over the
@@ -1166,7 +1177,8 @@ void nmethod::cleanup_inline_caches() {
// In fact, why are we bothering to look at oops in a non-entrant method??
}
- // Find all calls in an nmethod, and clear the ones that points to zombie methods
+ // Find all calls in an nmethod and clear the ones that point to non-entrant,
+ // zombie and unloaded nmethods.
ResourceMark rm;
RelocIterator iter(this, low_boundary);
while(iter.next()) {
@@ -1178,8 +1190,8 @@ void nmethod::cleanup_inline_caches() {
CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination());
if( cb != NULL && cb->is_nmethod() ) {
nmethod* nm = (nmethod*)cb;
- // Clean inline caches pointing to both zombie and not_entrant methods
- if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean();
+ // Clean inline caches pointing to zombie, non-entrant and unloaded methods
+ if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
}
break;
}
@@ -1188,7 +1200,7 @@ void nmethod::cleanup_inline_caches() {
CodeBlob *cb = CodeCache::find_blob_unsafe(csc->destination());
if( cb != NULL && cb->is_nmethod() ) {
nmethod* nm = (nmethod*)cb;
- // Clean inline caches pointing to both zombie and not_entrant methods
+ // Clean inline caches pointing to zombie, non-entrant and unloaded methods
if (!nm->is_in_use() || (nm->method()->code() != nm)) csc->set_to_clean();
}
break;
@@ -1279,7 +1291,7 @@ void nmethod::mark_as_seen_on_stack() {
// Tell if a non-entrant method can be converted to a zombie (i.e.,
// there are no activations on the stack, not in use by the VM,
// and not in use by the ServiceThread)
-bool nmethod::can_not_entrant_be_converted() {
+bool nmethod::can_convert_to_zombie() {
assert(is_not_entrant(), "must be a non-entrant method");
// Since the nmethod sweeper only does partial sweep the sweeper's traversal
@@ -1607,7 +1619,11 @@ void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
// During GC the is_alive closure is non-NULL, and is used to
// determine liveness of dependees that need to be updated.
if (is_alive == NULL || klass->is_loader_alive(is_alive)) {
- InstanceKlass::cast(klass)->remove_dependent_nmethod(this);
+ // The GC defers deletion of this entry, since there might be multiple threads
+ // iterating over the _dependencies graph. Other call paths are single-threaded
+ // and may delete it immediately.
+ bool delete_immediately = is_alive == NULL;
+ InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately);
}
}
}
@@ -2695,7 +2711,7 @@ void nmethod::verify() {
// Hmm. OSR methods can be deopted but not marked as zombie or not_entrant
// seems odd.
- if( is_zombie() || is_not_entrant() )
+ if (is_zombie() || is_not_entrant() || is_unloaded())
return;
// Make sure all the entry points are correctly aligned for patching.