# HG changeset patch # User vlivanov # Date 1485814300 -10800 # Node ID a2b3220830297e5e35dc1e6faa209422dc59d321 # Parent 5d984252fc261a4ebcdbe745bf3f3453c8c3d858 8173338: C2: continuous CallSite relinkage eventually disables compilation for a method Reviewed-by: jrose, dlong, kvn diff -r 5d984252fc26 -r a2b322083029 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Mon Jan 30 16:04:22 2017 +0300 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Tue Jan 31 01:11:40 2017 +0300 @@ -101,6 +101,7 @@ _debug_info = NULL; _dependencies = NULL; _failure_reason = NULL; + _inc_decompile_count_on_failure = true; _compilable = MethodCompilable; _break_at_compile = false; _compiler_data = NULL; @@ -161,6 +162,7 @@ _debug_info = NULL; _dependencies = NULL; _failure_reason = NULL; + _inc_decompile_count_on_failure = true; _compilable = MethodCompilable_never; _break_at_compile = false; _compiler_data = NULL; @@ -902,7 +904,12 @@ if (deps.is_klass_type()) continue; // skip klass dependencies Klass* witness = deps.check_dependency(); if (witness != NULL) { - record_failure("invalid non-klass dependency"); + if (deps.type() == Dependencies::call_site_target_value) { + _inc_decompile_count_on_failure = false; + record_failure("call site target change"); + } else { + record_failure("invalid non-klass dependency"); + } return; } } @@ -1017,7 +1024,7 @@ if (failing()) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdo = method()->method_data(); - if (mdo != NULL) { + if (mdo != NULL && _inc_decompile_count_on_failure) { mdo->inc_decompile_count(); } diff -r 5d984252fc26 -r a2b322083029 hotspot/src/share/vm/ci/ciEnv.hpp --- a/hotspot/src/share/vm/ci/ciEnv.hpp Mon Jan 30 16:04:22 2017 +0300 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Tue Jan 31 01:11:40 2017 +0300 @@ -55,6 +55,7 @@ DebugInformationRecorder* _debug_info; Dependencies* _dependencies; const char* _failure_reason; + bool _inc_decompile_count_on_failure; int _compilable; bool _break_at_compile; int _num_inlined_bytecodes; diff -r 5d984252fc26 -r a2b322083029 hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Mon Jan 30 16:04:22 2017 +0300 +++ b/hotspot/src/share/vm/code/codeCache.cpp Tue Jan 31 01:11:40 2017 +0300 @@ -1211,7 +1211,7 @@ CompiledMethodIterator iter; while(iter.next_alive()) { CompiledMethod* nm = iter.method(); - if (nm->is_marked_for_deoptimization()) { + if (nm->is_marked_for_deoptimization() && !nm->is_not_entrant()) { nm->make_not_entrant(); } } diff -r 5d984252fc26 -r a2b322083029 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Mon Jan 30 16:04:22 2017 +0300 +++ b/hotspot/src/share/vm/code/nmethod.cpp Tue Jan 31 01:11:40 2017 +0300 @@ -1146,6 +1146,14 @@ assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); assert(!is_zombie(), "should not already be a zombie"); + if (_state == state) { + // Avoid taking the lock if already in required state. + // This is safe from races because the state is an end-state, + // which the nmethod cannot back out of once entered. + // No need for fencing either. + return false; + } + // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); methodHandle the_method(method());