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 Mon Nov 23 21:11:33 2015
--- new/src/share/vm/runtime/sharedRuntime.cpp Mon Nov 23 21:11:33 2015
*** 1068,1077 ****
--- 1068,1092 ----
vframeStream vfst(thread, true); // Do not skip and javaCalls
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
// but callee has not been invoked yet. Caller frame must be compiled.
Handle SharedRuntime::find_callee_info_helper(JavaThread* thread,
*** 1085,1142 ****
--- 1100,1191 ----
// Find caller and bci from vframe
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();
// Find receiver for non-static call
! if (bc != Bytecodes::_invokestatic &&
+ 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) {
+ bc != Bytecodes::_invokehandle;
+
+ // Find receiver for non-static call
+ 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);
frame stubFrame = thread->last_frame();
// Caller-frame is a compiled frame
frame callerFrame = stubFrame.sender(®_map2);
methodHandle callee = bytecode.static_target(CHECK_(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));
if (receiver.is_null()) {
THROW_(vmSymbols::java_lang_NullPointerException(), nullHandle);
}
}
// 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()) {
tty->print_cr("ERROR: Klass not yet initialized!!");
receiver_klass()->print();
*** 1668,1678 ****
--- 1717,1726 ----
// compiled, dispatched call (which used to call an interpreted method)
CompiledIC* inline_cache = CompiledIC_at(caller_nm, call_addr);
inline_cache->set_to_clean();
}
}
}
methodHandle callee_method = find_callee_method(thread, CHECK_(methodHandle()));
src/share/vm/runtime/sharedRuntime.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File