diff --git a/src/share/vm/opto/c2compiler.cpp b/src/share/vm/opto/c2compiler.cpp index 87932d26888f383af2e989413b86de6deac1553b..9d06646d022e4a861804d9604944f36ddd0e02bc 100644 --- a/src/share/vm/opto/c2compiler.cpp +++ b/src/share/vm/opto/c2compiler.cpp @@ -49,6 +49,9 @@ const char* C2Compiler::retry_no_subsuming_loads() { const char* C2Compiler::retry_no_escape_analysis() { return "retry without escape analysis"; } +const char* C2Compiler::retry_class_loading_during_parsing() { + return "retry class loading during parsing"; +} bool C2Compiler::init_c2_runtime() { // Check assumptions used while running ADLC @@ -115,6 +118,10 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { // Check result and retry if appropriate. if (C.failure_reason() != NULL) { + if (C.failure_reason_is(retry_class_loading_during_parsing())) { + env->record_failure(C.failure_reason()); + continue; // retry + } if (C.failure_reason_is(retry_no_subsuming_loads())) { assert(subsume_loads, "must make progress"); subsume_loads = false; diff --git a/src/share/vm/opto/c2compiler.hpp b/src/share/vm/opto/c2compiler.hpp index 635153d1dbf4c0967d4a3a641029869e39415733..c1449bc348afc8de032707c7f3eb98702dbd8a4b 100644 --- a/src/share/vm/opto/c2compiler.hpp +++ b/src/share/vm/opto/c2compiler.hpp @@ -49,6 +49,7 @@ public: // sentinel value used to trigger backtracking in compile_method(). static const char* retry_no_subsuming_loads(); static const char* retry_no_escape_analysis(); + static const char* retry_class_loading_during_parsing(); // Print compilation timers and statistics void print_timers(); diff --git a/src/share/vm/opto/compile.cpp b/src/share/vm/opto/compile.cpp index 91a77aa8cbfb4d2897c9d35c1eed21d3d40a2b18..dc88381a114d83735a9ebd8ab70deb4b129bfed7 100644 --- a/src/share/vm/opto/compile.cpp +++ b/src/share/vm/opto/compile.cpp @@ -791,7 +791,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr } JVMState* jvms = build_start_state(start(), tf()); if ((jvms = cg->generate(jvms)) == NULL) { - record_method_not_compilable("method parse failed"); + if (!failure_reason_is(C2Compiler::retry_class_loading_during_parsing())) { + record_method_not_compilable("method parse failed"); + } return; } GraphKit kit(jvms); diff --git a/src/share/vm/opto/parse1.cpp b/src/share/vm/opto/parse1.cpp index b45652375f1f359184ccc58a53703bdd803adb73..ea1c84ec49c0e1500a03355f6495a0b158d062c3 100644 --- a/src/share/vm/opto/parse1.cpp +++ b/src/share/vm/opto/parse1.cpp @@ -27,6 +27,7 @@ #include "interpreter/linkResolver.hpp" #include "oops/method.hpp" #include "opto/addnode.hpp" +#include "opto/c2compiler.hpp" #include "opto/idealGraphPrinter.hpp" #include "opto/locknode.hpp" #include "opto/memnode.hpp" @@ -957,7 +958,18 @@ void Parse::do_exits() { if (tf()->range()->cnt() > TypeFunc::Parms) { const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); Node* ret_phi = _gvn.transform( _exits.argument(0) ); - assert(_exits.control()->is_top() || !_gvn.type(ret_phi)->empty(), "return value must be well defined"); + if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) { + // In case of concurrent class loading, the type we set for the + // ret_phi in build_exits() may have been too optimistic and the + // ret_phi may be top now. +#ifdef ASSERT + { + MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag); + assert(ret_type->isa_ptr() && C->env()->system_dictionary_modification_counter_changed(), "return value must be well defined"); + } +#endif + C->record_failure(C2Compiler::retry_class_loading_during_parsing()); + } _exits.push_node(ret_type->basic_type(), ret_phi); }