diff -r 029b56549e22 src/hotspot/share/interpreter/abstractInterpreter.cpp --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp Sat May 04 07:10:38 2019 +0800 @@ -28,6 +28,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" +#include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/interp_masm.hpp" @@ -36,6 +37,8 @@ #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" +#include "oops/constantPool.hpp" +#include "oops/cpCache.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" @@ -240,9 +243,36 @@ // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) { - Bytecodes::Code code = method()->code_at(bci); + BytecodeStream s(method, bci); + Bytecodes::Code code = s.next(); - if (!Bytecodes::must_rewrite(code)) { + if (Bytecodes::is_invoke(code)) { + assert(!Bytecodes::must_rewrite(code), "invokes aren't rewritten"); + ConstantPool* cpool = method()->constants(); + + Bytecode invoke_bc(s.bytecode()); + + switch (code) { + case Bytecodes::_invokedynamic: { + assert(invoke_bc.has_index_u4(code), "sanity"); + int method_index = invoke_bc.get_index_u4(code); + return cpool->invokedynamic_cp_cache_entry_at(method_index)->is_f1_null(); + } + case Bytecodes::_invokevirtual: // fall-through + case Bytecodes::_invokeinterface: // fall-through + case Bytecodes::_invokespecial: // fall-through + case Bytecodes::_invokestatic: { + if (cpool->has_preresolution()) { + return false; // might have been reached + } + assert(!invoke_bc.has_index_u4(code), "sanity"); + int method_index = invoke_bc.get_index_u2_cpcache(code); + Method* resolved_method = ConstantPool::method_at_if_loaded(cpool, method_index); + return (resolved_method == NULL); + } + default: ShouldNotReachHere(); + } + } else if (!Bytecodes::must_rewrite(code)) { // might have been reached return false; } diff -r 029b56549e22 src/hotspot/share/interpreter/bytecodeStream.hpp --- a/src/hotspot/share/interpreter/bytecodeStream.hpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/interpreter/bytecodeStream.hpp Sat May 04 07:10:38 2019 +0800 @@ -170,6 +170,10 @@ // Construction BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { } + BytecodeStream(const methodHandle& method, int bci) : BaseBytecodeStream(method) { + set_start(bci); + } + // Iteration Bytecodes::Code next() { Bytecodes::Code raw_code, code; diff -r 029b56549e22 src/hotspot/share/oops/cpCache.cpp --- a/src/hotspot/share/oops/cpCache.cpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/oops/cpCache.cpp Sat May 04 07:10:38 2019 +0800 @@ -506,7 +506,7 @@ switch (invoke_code) { case Bytecodes::_invokeinterface: assert(f1->is_klass(), ""); - return klassItable::method_for_itable_index((InstanceKlass*)f1, f2_as_index()); + return f2_as_interface_method(); case Bytecodes::_invokestatic: case Bytecodes::_invokespecial: assert(!has_appendix(), ""); diff -r 029b56549e22 src/hotspot/share/opto/bytecodeInfo.cpp --- a/src/hotspot/share/opto/bytecodeInfo.cpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/opto/bytecodeInfo.cpp Sat May 04 07:10:38 2019 +0800 @@ -321,6 +321,39 @@ return false; } +bool InlineTree::is_not_reached(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile) { + if (!UseInterpreter) { + return false; // -Xcomp + } + + if (profile.count() > 0) { + return false; // reachable according to profile + } + + if (!callee_method->was_executed_more_than(0)) { + return true; // callee was never executed + } + + if (caller_method->is_not_reached(caller_bci)) { + return true; // call site not resolved + } + + if (profile.count() == -1) { + return false; // immature profile; optimistically treat as reached + } + assert(profile.count() == 0, "sanity"); + + // Profile info is scarce. + // Try to guess: check if the call site belongs to a start block. + // Call sites in a start block should be reachable if no exception is thrown earlier. + ciMethodBlocks* caller_blocks = caller_method->get_method_blocks(); + bool is_start_block = caller_blocks->block_containing(caller_bci)->start_bci() == 0; + if (is_start_block) { + return false; // treat the call reached as part of start block + } + return true; // give up and treat the call site as not reached +} + //-----------------------------try_to_inline----------------------------------- // return true if ok // Relocated from "InliningClosure::try_to_inline" @@ -372,7 +405,7 @@ // inline constructors even if they are not reached. } else if (forced_inline()) { // Inlining was forced by CompilerOracle, ciReplay or annotation - } else if (profile.count() == 0) { + } else if (is_not_reached(callee_method, caller_method, caller_bci, profile)) { // don't inline unreached call sites set_msg("call site not reached"); return false; diff -r 029b56549e22 src/hotspot/share/opto/parse.hpp --- a/src/hotspot/share/opto/parse.hpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/opto/parse.hpp Sat May 04 07:10:38 2019 +0800 @@ -88,6 +88,10 @@ ciMethod* caller_method, JVMState* jvms, WarmCallInfo* wci_result); + bool is_not_reached(ciMethod* callee_method, + ciMethod* caller_method, + int caller_bci, + ciCallProfile& profile); void print_inlining(ciMethod* callee_method, int caller_bci, ciMethod* caller_method, bool success) const; diff -r 029b56549e22 src/hotspot/share/runtime/deoptimization.cpp --- a/src/hotspot/share/runtime/deoptimization.cpp Fri May 03 14:09:19 2019 -0700 +++ b/src/hotspot/share/runtime/deoptimization.cpp Sat May 04 07:10:38 2019 +0800 @@ -674,8 +674,7 @@ int top_frame_expression_stack_adjustment = 0; methodHandle mh(thread, iframe->interpreter_frame_method()); OopMapCache::compute_one_oop_map(mh, iframe->interpreter_frame_bci(), &mask); - BytecodeStream str(mh); - str.set_start(iframe->interpreter_frame_bci()); + BytecodeStream str(mh, iframe->interpreter_frame_bci()); int max_bci = mh->code_size(); // Get to the next bytecode if possible assert(str.bci() < max_bci, "bci in interpreter frame out of bounds");