From b4036c8045dcfc45027abeb770aad7d2d82bc32e Mon Sep 17 00:00:00 2001 From: twisti Date: Wed, 13 Jun 2012 11:36:03 -0700 Subject: [PATCH] 7174928: JSR 292: unresolved invokedynamic call sites deopt and osr infinitely Reviewed-by: kvn --- src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp | 8 +++--- src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 2 +- src/cpu/x86/vm/c1_LIRGenerator_x86.cpp | 8 +++--- src/share/vm/c1/c1_LIRGenerator.cpp | 26 +++++++++---------- .../vm/interpreter/interpreterRuntime.cpp | 8 ++++++ src/share/vm/oops/methodOop.cpp | 7 ++--- src/share/vm/oops/methodOop.hpp | 4 +-- 7 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 41b3eeb65..7b1bf6f1c 100644 --- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -965,10 +965,10 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { if (!x->klass()->is_loaded() || PatchALot) { patching_info = state_for(x, x->state_before()); - // cannot re-use same xhandlers for multiple CodeEmitInfos, so - // clone all handlers. This is handled transparently in other - // places by the CodeEmitInfo cloning logic but is handled - // specially here because a stub isn't being used. + // Cannot re-use same xhandlers for multiple CodeEmitInfos, so + // clone all handlers (NOTE: Usually this is handled transparently + // by the CodeEmitInfo cloning logic in CodeStub constructors but + // is done explicitly here because a stub isn't being used). x->set_exception_handlers(new XHandlers(x->exception_handlers())); } CodeEmitInfo* info = state_for(x, x->state()); diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 764c9cff7..dedde0b6e 100644 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -2673,7 +2673,7 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, #endif // _LP64 } } else { - ShouldNotReachHere(); + fatal(err_msg("unexpected type: %s", basictype_to_str(c->type()))); } // cpu register - address } else if (opr2->is_address()) { diff --git a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index c6bac720d..deca1a0ed 100644 --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -1087,10 +1087,10 @@ void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { if (!x->klass()->is_loaded() || PatchALot) { patching_info = state_for(x, x->state_before()); - // cannot re-use same xhandlers for multiple CodeEmitInfos, so - // clone all handlers. This is handled transparently in other - // places by the CodeEmitInfo cloning logic but is handled - // specially here because a stub isn't being used. + // Cannot re-use same xhandlers for multiple CodeEmitInfos, so + // clone all handlers (NOTE: Usually this is handled transparently + // by the CodeEmitInfo cloning logic in CodeStub constructors but + // is done explicitly here because a stub isn't being used). x->set_exception_handlers(new XHandlers(x->exception_handlers())); } CodeEmitInfo* info = state_for(x, x->state()); diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index ef302ea35..db61d7a42 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2807,31 +2807,29 @@ void LIRGenerator::do_Invoke(Invoke* x) { int index = bcs.get_method_index(); size_t call_site_offset = cpcache->get_f1_offset(index); + // Load CallSite object from constant pool cache. + LIR_Opr call_site = new_register(objectType); + __ oop2reg(cpcache->constant_encoding(), call_site); + __ move_wide(new LIR_Address(call_site, call_site_offset, T_OBJECT), call_site); + // If this invokedynamic call site hasn't been executed yet in // the interpreter, the CallSite object in the constant pool // cache is still null and we need to deoptimize. if (cpcache->is_f1_null_at(index)) { - // Cannot re-use same xhandlers for multiple CodeEmitInfos, so - // clone all handlers. This is handled transparently in other - // places by the CodeEmitInfo cloning logic but is handled - // specially here because a stub isn't being used. - x->set_exception_handlers(new XHandlers(x->exception_handlers())); - + // Only deoptimize if the CallSite object is still null; we don't + // recompile methods in C1 after deoptimization so this call site + // might be resolved the next time we execute it after OSR. DeoptimizeStub* deopt_stub = new DeoptimizeStub(deopt_info); - __ jump(deopt_stub); + __ cmp(lir_cond_equal, call_site, LIR_OprFact::oopConst(NULL)); + __ branch(lir_cond_equal, T_OBJECT, deopt_stub); } // Use the receiver register for the synthetic MethodHandle // argument. receiver = LIR_Assembler::receiverOpr(); - LIR_Opr tmp = new_register(objectType); - - // Load CallSite object from constant pool cache. - __ oop2reg(cpcache->constant_encoding(), tmp); - __ move_wide(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); // Load target MethodHandle from CallSite object. - __ load(new LIR_Address(tmp, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); + __ load(new LIR_Address(call_site, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); __ call_dynamic(target, receiver, result_register, SharedRuntime::get_resolve_opt_virtual_call_stub(), @@ -2839,7 +2837,7 @@ void LIRGenerator::do_Invoke(Invoke* x) { break; } default: - ShouldNotReachHere(); + fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(x->code()))); break; } diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp index e1c166587..6f5511f9f 100644 --- a/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/src/share/vm/interpreter/interpreterRuntime.cpp @@ -844,6 +844,14 @@ nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, addr int bci = method->bci_from(fr.interpreter_frame_bcp()); nm = method->lookup_osr_nmethod_for(bci, CompLevel_none, false); } +#ifndef PRODUCT + if (TraceOnStackReplacement) { + if (nm != NULL) { + tty->print("OSR entry @ pc: " INTPTR_FORMAT ": ", nm->osr_entry()); + nm->print(); + } + } +#endif return nm; } diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp index 6decdd72b..0a7850f37 100644 --- a/src/share/vm/oops/methodOop.cpp +++ b/src/share/vm/oops/methodOop.cpp @@ -70,11 +70,11 @@ address methodOopDesc::get_c2i_unverified_entry() { return _adapter->get_c2i_unverified_entry(); } -char* methodOopDesc::name_and_sig_as_C_string() { +char* methodOopDesc::name_and_sig_as_C_string() const { return name_and_sig_as_C_string(Klass::cast(constants()->pool_holder()), name(), signature()); } -char* methodOopDesc::name_and_sig_as_C_string(char* buf, int size) { +char* methodOopDesc::name_and_sig_as_C_string(char* buf, int size) const { return name_and_sig_as_C_string(Klass::cast(constants()->pool_holder()), name(), signature(), buf, size); } @@ -177,7 +177,8 @@ void methodOopDesc::mask_for(int bci, InterpreterOopMap* mask) { int methodOopDesc::bci_from(address bcp) const { - assert(is_native() && bcp == code_base() || contains(bcp) || is_error_reported(), "bcp doesn't belong to this method"); + assert(is_native() && bcp == code_base() || contains(bcp) || is_error_reported(), + err_msg("bcp doesn't belong to this method: bcp: " INTPTR_FORMAT ", method: %s", bcp, name_and_sig_as_C_string())); return bcp - code_base(); } diff --git a/src/share/vm/oops/methodOop.hpp b/src/share/vm/oops/methodOop.hpp index 60bb34bb2..03f62f673 100644 --- a/src/share/vm/oops/methodOop.hpp +++ b/src/share/vm/oops/methodOop.hpp @@ -198,8 +198,8 @@ class methodOopDesc : public oopDesc { // C string, for the purpose of providing more useful NoSuchMethodErrors // and fatal error handling. The string is allocated in resource // area if a buffer is not provided by the caller. - char* name_and_sig_as_C_string(); - char* name_and_sig_as_C_string(char* buf, int size); + char* name_and_sig_as_C_string() const; + char* name_and_sig_as_C_string(char* buf, int size) const; // Static routine in the situations we don't have a methodOop static char* name_and_sig_as_C_string(Klass* klass, Symbol* method_name, Symbol* signature); -- GitLab