8134493: Cleaning inline caches of unloaded nmethods should be done in sweeper
Clean ICs of unloaded nmethods in sweeper to avoid impact on safepoint duration. Reviewed-by: kvn, mdoerr
This commit is contained in:
parent
9dcbe322e0
commit
7b6480cfa4
@ -745,13 +745,12 @@ void CodeCache::gc_prologue() {
|
||||
|
||||
void CodeCache::gc_epilogue() {
|
||||
assert_locked_or_safepoint(CodeCache_lock);
|
||||
NOT_DEBUG(if (needs_cache_clean())) {
|
||||
NMethodIterator iter;
|
||||
while(iter.next()) {
|
||||
while(iter.next_alive()) {
|
||||
nmethod* nm = iter.method();
|
||||
if (!nm->is_zombie()) {
|
||||
if (needs_cache_clean()) {
|
||||
// Clean ICs of unloaded nmethods as well because they may reference other
|
||||
// unloaded nmethods that may be flushed earlier in the sweeper cycle.
|
||||
assert(!nm->is_unloaded(), "Tautology");
|
||||
DEBUG_ONLY(if (needs_cache_clean())) {
|
||||
nm->cleanup_inline_caches();
|
||||
}
|
||||
DEBUG_ONLY(nm->verify());
|
||||
|
@ -287,6 +287,7 @@ bool CompiledIC::is_call_to_compiled() const {
|
||||
assert( is_c1_method ||
|
||||
!is_monomorphic ||
|
||||
is_optimized() ||
|
||||
!caller->is_alive() ||
|
||||
(cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check");
|
||||
#endif // ASSERT
|
||||
return is_monomorphic;
|
||||
@ -321,7 +322,7 @@ bool CompiledIC::is_call_to_interpreted() const {
|
||||
}
|
||||
|
||||
|
||||
void CompiledIC::set_to_clean() {
|
||||
void CompiledIC::set_to_clean(bool in_use) {
|
||||
assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call");
|
||||
if (TraceInlineCacheClearing || TraceICs) {
|
||||
tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
|
||||
@ -337,7 +338,7 @@ void CompiledIC::set_to_clean() {
|
||||
|
||||
// A zombie transition will always be safe, since the metadata has already been set to NULL, so
|
||||
// we only need to patch the destination
|
||||
bool safe_transition = is_optimized() || SafepointSynchronize::is_at_safepoint();
|
||||
bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
|
||||
|
||||
if (safe_transition) {
|
||||
// Kill any leftover stub we might have too
|
||||
|
@ -214,7 +214,7 @@ class CompiledIC: public ResourceObj {
|
||||
//
|
||||
// They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full.
|
||||
//
|
||||
void set_to_clean();
|
||||
void set_to_clean(bool in_use = true);
|
||||
void set_to_monomorphic(CompiledICInfo& info);
|
||||
void clear_ic_stub();
|
||||
|
||||
|
@ -1050,7 +1050,7 @@ void nmethod::cleanup_inline_caches() {
|
||||
if( cb != NULL && cb->is_nmethod() ) {
|
||||
nmethod* nm = (nmethod*)cb;
|
||||
// Clean inline caches pointing to zombie, non-entrant and unloaded methods
|
||||
if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean();
|
||||
if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1150,7 +1150,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
|
||||
|
@ -577,7 +577,7 @@ public:
|
||||
|
||||
// See comment at definition of _last_seen_on_stack
|
||||
void mark_as_seen_on_stack();
|
||||
bool can_not_entrant_be_converted();
|
||||
bool can_convert_to_zombie();
|
||||
|
||||
// Evolution support. We make old (discarded) compiled methods point to new Method*s.
|
||||
void set_method(Method* method) { _method = method; }
|
||||
|
@ -611,7 +611,7 @@ NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) {
|
||||
} else if (nm->is_not_entrant()) {
|
||||
// If there are no current activations of this method on the
|
||||
// stack we can safely convert it to a zombie method
|
||||
if (nm->can_not_entrant_be_converted()) {
|
||||
if (nm->can_convert_to_zombie()) {
|
||||
// Clear ICStubs to prevent back patching stubs of zombie or unloaded
|
||||
// nmethods during the next safepoint (see ICStub::finalize).
|
||||
{
|
||||
@ -645,6 +645,12 @@ NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) {
|
||||
assert(result == None, "sanity");
|
||||
result = Flushed;
|
||||
} else {
|
||||
{
|
||||
// Clean ICs of unloaded nmethods as well because they may reference other
|
||||
// unloaded nmethods that may be flushed earlier in the sweeper cycle.
|
||||
MutexLocker cl(CompiledIC_lock);
|
||||
nm->cleanup_inline_caches();
|
||||
}
|
||||
// Code cache state change is tracked in make_zombie()
|
||||
nm->make_zombie();
|
||||
SWEEP(nm);
|
||||
|
Loading…
Reference in New Issue
Block a user