8028107: Kitchensink crashed with EAV

Fri, 06 Dec 2013 12:11:51 -0800

author
kvn
date
Fri, 06 Dec 2013 12:11:51 -0800
changeset 6172
df832bd8edb9
parent 6160
3aa20cee331a
child 6173
b87211e33ebb

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

src/share/vm/code/compiledIC.cpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.cpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/sharedRuntime.cpp file | annotate | diff | comparison | revisions
     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) {

mercurial