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(®_map2);
+ // Retrieve from a compiled argument list
+ Handle receiver = Handle(THREAD, callerFrame.retrieve_receiver(®_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