Fri, 06 Dec 2013 12:11:51 -0800
8028107: Kitchensink crashed with EAV
Summary: check the state of caller and callee nmethods and skip call site patching if any of them is not alive
Reviewed-by: jrose, twisti
1.1 --- a/src/share/vm/code/compiledIC.cpp Fri Dec 06 09:41:57 2013 -0800 1.2 +++ b/src/share/vm/code/compiledIC.cpp Fri Dec 06 12:11:51 2013 -0800 1.3 @@ -418,7 +418,7 @@ 1.4 TRAPS) { 1.5 nmethod* method_code = method->code(); 1.6 address entry = NULL; 1.7 - if (method_code != NULL) { 1.8 + if (method_code != NULL && method_code->is_in_use()) { 1.9 // Call to compiled code 1.10 if (static_bound || is_optimized) { 1.11 entry = method_code->verified_entry_point(); 1.12 @@ -545,7 +545,7 @@ 1.13 void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) { 1.14 nmethod* m_code = m->code(); 1.15 info._callee = m; 1.16 - if (m_code != NULL) { 1.17 + if (m_code != NULL && m_code->is_in_use()) { 1.18 info._to_interpreter = false; 1.19 info._entry = m_code->verified_entry_point(); 1.20 } else {
2.1 --- a/src/share/vm/code/nmethod.cpp Fri Dec 06 09:41:57 2013 -0800 2.2 +++ b/src/share/vm/code/nmethod.cpp Fri Dec 06 12:11:51 2013 -0800 2.3 @@ -459,7 +459,7 @@ 2.4 2.5 // Fill in default values for various flag fields 2.6 void nmethod::init_defaults() { 2.7 - _state = alive; 2.8 + _state = in_use; 2.9 _marked_for_reclamation = 0; 2.10 _has_flushed_dependencies = 0; 2.11 _has_unsafe_access = 0; 2.12 @@ -1660,8 +1660,8 @@ 2.13 CompiledICHolder* cichk_oop = ic->cached_icholder(); 2.14 if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && 2.15 cichk_oop->holder_klass()->is_loader_alive(is_alive)) { 2.16 - continue; 2.17 - } 2.18 + continue; 2.19 + } 2.20 } else { 2.21 Metadata* ic_oop = ic->cached_metadata(); 2.22 if (ic_oop != NULL) { 2.23 @@ -1677,8 +1677,8 @@ 2.24 ShouldNotReachHere(); 2.25 } 2.26 } 2.27 - } 2.28 - ic->set_to_clean(); 2.29 + } 2.30 + ic->set_to_clean(); 2.31 } 2.32 } 2.33 } 2.34 @@ -2393,8 +2393,8 @@ 2.35 2.36 void nmethod::verify_interrupt_point(address call_site) { 2.37 // Verify IC only when nmethod installation is finished. 2.38 - bool is_installed = (method()->code() == this) // nmethod is in state 'alive' and installed 2.39 - || !this->is_in_use(); // nmethod is installed, but not in 'alive' state 2.40 + bool is_installed = (method()->code() == this) // nmethod is in state 'in_use' and installed 2.41 + || !this->is_in_use(); // nmethod is installed, but not in 'in_use' state 2.42 if (is_installed) { 2.43 Thread *cur = Thread::current(); 2.44 if (CompiledIC_lock->owner() == cur ||
3.1 --- a/src/share/vm/code/nmethod.hpp Fri Dec 06 09:41:57 2013 -0800 3.2 +++ b/src/share/vm/code/nmethod.hpp Fri Dec 06 12:11:51 2013 -0800 3.3 @@ -184,11 +184,12 @@ 3.4 bool _oops_are_stale; // indicates that it's no longer safe to access oops section 3.5 #endif 3.6 3.7 - enum { alive = 0, 3.8 - not_entrant = 1, // uncommon trap has happened but activations may still exist 3.9 - zombie = 2, 3.10 - unloaded = 3 }; 3.11 - 3.12 + enum { in_use = 0, // executable nmethod 3.13 + not_entrant = 1, // marked for deoptimization but activations may still exist, 3.14 + // will be transformed to zombie when all activations are gone 3.15 + zombie = 2, // no activations exist, nmethod is ready for purge 3.16 + unloaded = 3 }; // there should be no activations, should not be called, 3.17 + // will be transformed to zombie immediately 3.18 3.19 jbyte _scavenge_root_state; 3.20 3.21 @@ -407,8 +408,8 @@ 3.22 address verified_entry_point() const { return _verified_entry_point; } // if klass is correct 3.23 3.24 // flag accessing and manipulation 3.25 - bool is_in_use() const { return _state == alive; } 3.26 - bool is_alive() const { return _state == alive || _state == not_entrant; } 3.27 + bool is_in_use() const { return _state == in_use; } 3.28 + bool is_alive() const { return _state == in_use || _state == not_entrant; } 3.29 bool is_not_entrant() const { return _state == not_entrant; } 3.30 bool is_zombie() const { return _state == zombie; } 3.31 bool is_unloaded() const { return _state == unloaded; }
4.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Fri Dec 06 09:41:57 2013 -0800 4.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Dec 06 12:11:51 2013 -0800 4.3 @@ -1178,12 +1178,12 @@ 4.4 CodeBlob* caller_cb = caller_frame.cb(); 4.5 guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod"); 4.6 nmethod* caller_nm = caller_cb->as_nmethod_or_null(); 4.7 + 4.8 // make sure caller is not getting deoptimized 4.9 // and removed before we are done with it. 4.10 // CLEANUP - with lazy deopt shouldn't need this lock 4.11 nmethodLocker caller_lock(caller_nm); 4.12 4.13 - 4.14 // determine call info & receiver 4.15 // note: a) receiver is NULL for static calls 4.16 // b) an exception is thrown if receiver is NULL for non-static calls 4.17 @@ -1198,6 +1198,11 @@ 4.18 (!is_virtual && invoke_code == Bytecodes::_invokedynamic) || 4.19 ( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode"); 4.20 4.21 + // We do not patch the call site if the caller nmethod has been made non-entrant. 4.22 + if (!caller_nm->is_in_use()) { 4.23 + return callee_method; 4.24 + } 4.25 + 4.26 #ifndef PRODUCT 4.27 // tracing/debugging/statistics 4.28 int *addr = (is_optimized) ? (&_resolve_opt_virtual_ctr) : 4.29 @@ -1237,6 +1242,10 @@ 4.30 // Make sure the callee nmethod does not get deoptimized and removed before 4.31 // we are done patching the code. 4.32 nmethod* callee_nm = callee_method->code(); 4.33 + if (callee_nm != NULL && !callee_nm->is_in_use()) { 4.34 + // Patch call site to C2I adapter if callee nmethod is deoptimized or unloaded. 4.35 + callee_nm = NULL; 4.36 + } 4.37 nmethodLocker nl_callee(callee_nm); 4.38 #ifdef ASSERT 4.39 address dest_entry_point = callee_nm == NULL ? 0 : callee_nm->entry_point(); // used below 4.40 @@ -1258,15 +1267,24 @@ 4.41 { 4.42 MutexLocker ml_patch(CompiledIC_lock); 4.43 4.44 + // Lock blocks for safepoint during which both nmethods can change state. 4.45 + 4.46 // Now that we are ready to patch if the Method* was redefined then 4.47 // don't update call site and let the caller retry. 4.48 - 4.49 - if (!callee_method->is_old()) { 4.50 + // Don't update call site if caller nmethod has been made non-entrant 4.51 + // as it is a waste of time. 4.52 + // Don't update call site if callee nmethod was unloaded or deoptimized. 4.53 + // Don't update call site if callee nmethod was replaced by an other nmethod 4.54 + // which may happen when multiply alive nmethod (tiered compilation) 4.55 + // will be supported. 4.56 + if (!callee_method->is_old() && caller_nm->is_in_use() && 4.57 + (callee_nm == NULL || callee_nm->is_in_use() && (callee_method->code() == callee_nm))) { 4.58 #ifdef ASSERT 4.59 // We must not try to patch to jump to an already unloaded method. 4.60 if (dest_entry_point != 0) { 4.61 - assert(CodeCache::find_blob(dest_entry_point) != NULL, 4.62 - "should not unload nmethod while locked"); 4.63 + CodeBlob* cb = CodeCache::find_blob(dest_entry_point); 4.64 + assert((cb != NULL) && cb->is_nmethod() && (((nmethod*)cb) == callee_nm), 4.65 + "should not call unloaded nmethod"); 4.66 } 4.67 #endif 4.68 if (is_virtual) {