diff -r 839c8ba29724 -r bbf32241d851 hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Dec 04 16:38:04 2015 +0100 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Dec 04 23:46:19 2015 +0300 @@ -1070,6 +1070,21 @@ return find_callee_info_helper(thread, vfst, bc, callinfo, THREAD); } +methodHandle SharedRuntime::extract_attached_method(vframeStream& vfst) { + nmethod* caller_nm = vfst.nm(); + + nmethodLocker caller_lock(caller_nm); + + address pc = vfst.frame_pc(); + { // Get call instruction under lock because another thread may be busy patching it. + MutexLockerEx ml_patch(Patching_lock, Mutex::_no_safepoint_check_flag); + if (NativeCall::is_call_before(pc)) { + NativeCall* ncall = nativeCall_before(pc); + return caller_nm->attached_method(ncall->instruction_address()); + } + } + return NULL; +} // Finds receiver, CallInfo (i.e. receiver method), and calling bytecode // for a call current in progress, i.e., arguments has been pushed on stack @@ -1087,15 +1102,37 @@ methodHandle caller(THREAD, vfst.method()); int bci = vfst.bci(); - // Find bytecode Bytecode_invoke bytecode(caller, bci); - bc = bytecode.invoke_code(); int bytecode_index = bytecode.index(); + methodHandle attached_method = extract_attached_method(vfst); + if (attached_method.not_null()) { + methodHandle callee = bytecode.static_target(CHECK_NH); + vmIntrinsics::ID id = callee->intrinsic_id(); + // When VM replaces MH.invokeBasic/linkTo* call with a direct/virtual call, + // it attaches statically resolved method to the call site. + if (MethodHandles::is_signature_polymorphic(id) && + MethodHandles::is_signature_polymorphic_intrinsic(id)) { + bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id); + + // Need to adjust invokehandle since inlining through signature-polymorphic + // method happened. + if (bc == Bytecodes::_invokehandle && + !MethodHandles::is_signature_polymorphic_method(attached_method())) { + bc = attached_method->is_static() ? Bytecodes::_invokestatic + : Bytecodes::_invokevirtual; + } + } + } else { + bc = bytecode.invoke_code(); + } + + bool has_receiver = bc != Bytecodes::_invokestatic && + bc != Bytecodes::_invokedynamic && + bc != Bytecodes::_invokehandle; + // Find receiver for non-static call - if (bc != Bytecodes::_invokestatic && - bc != Bytecodes::_invokedynamic && - bc != Bytecodes::_invokehandle) { + if (has_receiver) { // This register map must be update since we need to find the receiver for // compiled frames. The receiver might be in a register. RegisterMap reg_map2(thread); @@ -1103,10 +1140,13 @@ // Caller-frame is a compiled frame frame callerFrame = stubFrame.sender(®_map2); - methodHandle callee = bytecode.static_target(CHECK_(nullHandle)); - if (callee.is_null()) { - THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle); + if (attached_method.is_null()) { + methodHandle callee = bytecode.static_target(CHECK_NH); + if (callee.is_null()) { + THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle); + } } + // Retrieve from a compiled argument list receiver = Handle(THREAD, callerFrame.retrieve_receiver(®_map2)); @@ -1115,26 +1155,35 @@ } } - // Resolve method. This is parameterized by bytecode. - constantPoolHandle constants(THREAD, caller->constants()); assert(receiver.is_null() || receiver->is_oop(), "wrong receiver"); - LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_(nullHandle)); + + // Resolve method + if (attached_method.not_null()) { + // Parameterized by attached method. + LinkResolver::resolve_invoke(callinfo, receiver, attached_method, bc, CHECK_NH); + } else { + // Parameterized by bytecode. + constantPoolHandle constants(THREAD, caller->constants()); + LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_NH); + } #ifdef ASSERT // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls - if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic && bc != Bytecodes::_invokehandle) { + if (has_receiver) { assert(receiver.not_null(), "should have thrown exception"); KlassHandle receiver_klass(THREAD, receiver->klass()); - Klass* rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle)); - // klass is already loaded + Klass* rk = NULL; + if (attached_method.not_null()) { + // In case there's resolved method attached, use its holder during the check. + rk = attached_method->method_holder(); + } else { + // Klass is already loaded. + constantPoolHandle constants(THREAD, caller->constants()); + rk = constants->klass_ref_at(bytecode_index, CHECK_NH); + } KlassHandle static_receiver_klass(THREAD, rk); - // Method handle invokes might have been optimized to a direct call - // so don't check for the receiver class. - // FIXME this weakens the assert too much methodHandle callee = callinfo.selected_method(); - assert(receiver_klass->is_subtype_of(static_receiver_klass()) || - callee->is_method_handle_intrinsic() || - callee->is_compiled_lambda_form(), + assert(receiver_klass->is_subtype_of(static_receiver_klass()), "actual receiver must be subclass of static receiver klass"); if (receiver_klass->is_instance_klass()) { if (InstanceKlass::cast(receiver_klass())->is_not_initialized()) { @@ -1670,7 +1719,6 @@ inline_cache->set_to_clean(); } } - } methodHandle callee_method = find_callee_method(thread, CHECK_(methodHandle()));