src/share/vm/runtime/sharedRuntime.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/runtime/sharedRuntime.cpp	Fri Oct 30 00:19:42 2015
--- new/src/share/vm/runtime/sharedRuntime.cpp	Fri Oct 30 00:19:42 2015

*** 1074,1083 **** --- 1074,1162 ---- vframeStream vfst(thread, true); // Do not skip and javaCalls return find_callee_info_helper(thread, vfst, bc, callinfo, THREAD); } + methodHandle SharedRuntime::extract_attached_call_info(JavaThread* thread) { + ResourceMark rm(thread); + RegisterMap cbl_map(thread, false); + frame caller_frame = thread->last_frame().sender(&cbl_map); + CodeBlob* caller_cb = caller_frame.cb(); + guarantee(caller_cb != NULL && caller_cb->is_nmethod(), "must be called from nmethod"); + nmethod* caller_nm = caller_cb->as_nmethod_or_null(); + + //assert(caller_nm is locked)); + + NativeCall* call = nativeCall_before(caller_frame.pc()); + RelocIterator iter(caller_nm, call->instruction_address()); + while (iter.next()) { + if (iter.addr() == call->instruction_address()) { + switch(iter.type()) { + case relocInfo::static_call_type: return iter.static_call_reloc()->method_value(); + case relocInfo::opt_virtual_call_type: return iter.opt_virtual_call_reloc()->method_value(); + case relocInfo::virtual_call_type: return iter.virtual_call_reloc()->method_value(); + default: + fatal("unexpected reloc type: %d", iter.type()); + } + } + } + return NULL; + } + + static Bytecodes::Code compute_bc(vmIntrinsics::ID id) { + switch(id) { + case vmIntrinsics::_linkToVirtual: return Bytecodes::_invokevirtual; + case vmIntrinsics::_linkToInterface: return Bytecodes::_invokeinterface; + case vmIntrinsics::_linkToStatic: return Bytecodes::_invokestatic; + case vmIntrinsics::_linkToSpecial: return Bytecodes::_invokespecial; + case vmIntrinsics::_invokeBasic: return Bytecodes::_invokestatic; + default: + fatal("unexpected id: (%d) %s", (uint)id, vmIntrinsics::name_at(id)); + return Bytecodes::_illegal; + } + } + + static Handle extract_receiver(JavaThread* thread, TRAPS) { + // 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); + frame stubFrame = thread->last_frame(); + // Caller-frame is a compiled frame + frame callerFrame = stubFrame.sender(&reg_map2); + // Retrieve from a compiled argument list + Handle receiver = Handle(THREAD, callerFrame.retrieve_receiver(&reg_map2)); + if (receiver.is_null()) { + THROW_(vmSymbols::java_lang_NullPointerException(), Handle()); + } + return receiver; + } + + void SharedRuntime::resolve_attached_call_info(JavaThread* thread, methodHandle info, Bytecodes::Code bc, + Handle& receiver, CallInfo& callinfo, TRAPS) { + KlassHandle defc = info->method_holder(); + Symbol* name = info->name(); + Symbol* type = info->signature(); + LinkInfo link_info(defc, name, type, KlassHandle(), /*check_access=*/false); + switch(bc) { + case Bytecodes::_invokevirtual: + LinkResolver::resolve_virtual_call(callinfo, receiver, receiver->klass(), + link_info, /*check_null_and_abstract=*/true, THREAD); + break; + case Bytecodes::_invokeinterface: + LinkResolver::resolve_interface_call(callinfo, receiver, receiver->klass(), + link_info, /*check_null_and_abstract=*/true, THREAD); + break; + case Bytecodes::_invokestatic: + LinkResolver::resolve_static_call(callinfo, link_info, /*initialize_class=*/false, THREAD); + break; + case Bytecodes::_invokespecial: + LinkResolver::resolve_special_call(callinfo, link_info, THREAD); + break; + default: + fatal("bad call"); + } + } // Finds receiver, CallInfo (i.e. receiver method), and calling bytecode // for a call current in progress, i.e., arguments has been pushed on stack // but callee has not been invoked yet. Caller frame must be compiled. Handle SharedRuntime::find_callee_info_helper(JavaThread* thread,
*** 1124,1148 **** --- 1203,1241 ---- // 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)); + // When VM replaces MH.invokeBasic/linkTo* call with a direct/virtual call, + // it attaches statically resolved method to the call site. + methodHandle call_info; + vmIntrinsics::ID id = callinfo.resolved_method()->intrinsic_id(); + if (MethodHandles::is_signature_polymorphic(id) && id != vmIntrinsics::_invokeGeneric) { + call_info = extract_attached_call_info(thread); + if (!call_info.is_null()) { + bc = compute_bc(id); + // Find receiver for non-static call + if (bc != Bytecodes::_invokestatic) { + receiver = extract_receiver(thread, CHECK_(nullHandle)); + } + resolve_attached_call_info(thread, call_info, bc, receiver, callinfo, CHECK_(nullHandle)); + } + } #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) { 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 + if (!call_info.is_null()) { + // In case there's resolved method attached, use it's holder during the check. + rk = call_info->method_holder(); + } 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->oop_is_instance()) { if (InstanceKlass::cast(receiver_klass())->is_not_initialized()) { tty->print_cr("ERROR: Klass not yet initialized!!"); receiver_klass()->print();

src/share/vm/runtime/sharedRuntime.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File