8173338: C2: continuous CallSite relinkage eventually disables compilation for a method

Reviewed-by: jrose, dlong, kvn
This commit is contained in:
Vladimir Ivanov 2017-01-31 01:11:40 +03:00
parent 81e25c58fb
commit 95ff3ccdb4
4 changed files with 19 additions and 3 deletions

View file

@ -101,6 +101,7 @@ ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter)
_debug_info = NULL; _debug_info = NULL;
_dependencies = NULL; _dependencies = NULL;
_failure_reason = NULL; _failure_reason = NULL;
_inc_decompile_count_on_failure = true;
_compilable = MethodCompilable; _compilable = MethodCompilable;
_break_at_compile = false; _break_at_compile = false;
_compiler_data = NULL; _compiler_data = NULL;
@ -161,6 +162,7 @@ ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
_debug_info = NULL; _debug_info = NULL;
_dependencies = NULL; _dependencies = NULL;
_failure_reason = NULL; _failure_reason = NULL;
_inc_decompile_count_on_failure = true;
_compilable = MethodCompilable_never; _compilable = MethodCompilable_never;
_break_at_compile = false; _break_at_compile = false;
_compiler_data = NULL; _compiler_data = NULL;
@ -902,7 +904,12 @@ void ciEnv::validate_compile_task_dependencies(ciMethod* target) {
if (deps.is_klass_type()) continue; // skip klass dependencies if (deps.is_klass_type()) continue; // skip klass dependencies
Klass* witness = deps.check_dependency(); Klass* witness = deps.check_dependency();
if (witness != NULL) { 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; return;
} }
} }
@ -1017,7 +1024,7 @@ void ciEnv::register_method(ciMethod* target,
if (failing()) { if (failing()) {
// While not a true deoptimization, it is a preemptive decompile. // While not a true deoptimization, it is a preemptive decompile.
MethodData* mdo = method()->method_data(); MethodData* mdo = method()->method_data();
if (mdo != NULL) { if (mdo != NULL && _inc_decompile_count_on_failure) {
mdo->inc_decompile_count(); mdo->inc_decompile_count();
} }

View file

@ -55,6 +55,7 @@ private:
DebugInformationRecorder* _debug_info; DebugInformationRecorder* _debug_info;
Dependencies* _dependencies; Dependencies* _dependencies;
const char* _failure_reason; const char* _failure_reason;
bool _inc_decompile_count_on_failure;
int _compilable; int _compilable;
bool _break_at_compile; bool _break_at_compile;
int _num_inlined_bytecodes; int _num_inlined_bytecodes;

View file

@ -1211,7 +1211,7 @@ void CodeCache::make_marked_nmethods_not_entrant() {
CompiledMethodIterator iter; CompiledMethodIterator iter;
while(iter.next_alive()) { while(iter.next_alive()) {
CompiledMethod* nm = iter.method(); CompiledMethod* nm = iter.method();
if (nm->is_marked_for_deoptimization()) { if (nm->is_marked_for_deoptimization() && !nm->is_not_entrant()) {
nm->make_not_entrant(); nm->make_not_entrant();
} }
} }

View file

@ -1146,6 +1146,14 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
assert(!is_zombie(), "should not already be a zombie"); 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. // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this); nmethodLocker nml(this);
methodHandle the_method(method()); methodHandle the_method(method());