8337753: Target class of upcall stub may be unloaded
Reviewed-by: amitkumar, vlivanov, mdoerr
This commit is contained in:
parent
19642bd383
commit
6af13580c2
@ -7320,6 +7320,28 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// load Method* target of MethodHandle
|
||||
// j_rarg0 = jobject receiver
|
||||
// rmethod = result
|
||||
address generate_upcall_stub_load_target() {
|
||||
StubCodeMark mark(this, "StubRoutines", "upcall_stub_load_target");
|
||||
address start = __ pc();
|
||||
|
||||
__ resolve_global_jobject(j_rarg0, rscratch1, rscratch2);
|
||||
// Load target method from receiver
|
||||
__ load_heap_oop(rmethod, Address(j_rarg0, java_lang_invoke_MethodHandle::form_offset()), rscratch1, rscratch2);
|
||||
__ load_heap_oop(rmethod, Address(rmethod, java_lang_invoke_LambdaForm::vmentry_offset()), rscratch1, rscratch2);
|
||||
__ load_heap_oop(rmethod, Address(rmethod, java_lang_invoke_MemberName::method_offset()), rscratch1, rscratch2);
|
||||
__ access_load_at(T_ADDRESS, IN_HEAP, rmethod,
|
||||
Address(rmethod, java_lang_invoke_ResolvedMethodName::vmtarget_offset()),
|
||||
noreg, noreg);
|
||||
__ str(rmethod, Address(rthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
|
||||
|
||||
__ ret(lr);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ masm->
|
||||
|
||||
@ -8241,6 +8263,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#endif
|
||||
|
||||
StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler();
|
||||
StubRoutines::_upcall_stub_load_target = generate_upcall_stub_load_target();
|
||||
|
||||
StubRoutines::aarch64::set_completed(); // Inidicate that arraycopy and zero_blocks stubs are generated
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
@ -117,7 +118,7 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
|
||||
static const int upcall_stub_code_base_size = 1024;
|
||||
static const int upcall_stub_size_per_arg = 16;
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
@ -222,7 +223,6 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
__ block_comment("{ on_entry");
|
||||
__ lea(c_rarg0, Address(sp, frame_data_offset));
|
||||
__ movptr(c_rarg1, (intptr_t)receiver);
|
||||
__ movptr(rscratch1, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::on_entry));
|
||||
__ blr(rscratch1);
|
||||
__ mov(rthread, r0);
|
||||
@ -238,12 +238,10 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0);
|
||||
__ block_comment("} argument shuffle");
|
||||
|
||||
__ block_comment("{ receiver ");
|
||||
__ get_vm_result(j_rarg0, rthread);
|
||||
__ block_comment("} receiver ");
|
||||
|
||||
__ mov_metadata(rmethod, entry);
|
||||
__ str(rmethod, Address(rthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
|
||||
__ block_comment("{ load target ");
|
||||
__ movptr(j_rarg0, (intptr_t)receiver);
|
||||
__ far_call(RuntimeAddress(StubRoutines::upcall_stub_load_target()), rscratch1); // puts target Method* in rmethod
|
||||
__ block_comment("} load target ");
|
||||
|
||||
__ push_cont_fastpath(rthread);
|
||||
|
||||
@ -318,7 +316,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
#ifndef PRODUCT
|
||||
stringStream ss;
|
||||
ss.print("upcall_stub_%s", entry->signature()->as_C_string());
|
||||
ss.print("upcall_stub_%s", signature->as_C_string());
|
||||
const char* name = _masm->code_string(ss.as_string());
|
||||
#else // PRODUCT
|
||||
const char* name = "upcall_stub";
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "prims/upcallLinker.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
|
@ -4587,6 +4587,30 @@ address generate_lookup_secondary_supers_table_stub(u1 super_klass_index) {
|
||||
return start;
|
||||
}
|
||||
|
||||
// load Method* target of MethodHandle
|
||||
// R3_ARG1 = jobject receiver
|
||||
// R19_method = result Method*
|
||||
address generate_upcall_stub_load_target() {
|
||||
|
||||
StubCodeMark mark(this, "StubRoutines", "upcall_stub_load_target");
|
||||
address start = __ pc();
|
||||
|
||||
__ resolve_global_jobject(R3_ARG1, R22_tmp2, R23_tmp3, MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS);
|
||||
// Load target method from receiver
|
||||
__ load_heap_oop(R19_method, java_lang_invoke_MethodHandle::form_offset(), R3_ARG1,
|
||||
R22_tmp2, R23_tmp3, MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS, IS_NOT_NULL);
|
||||
__ load_heap_oop(R19_method, java_lang_invoke_LambdaForm::vmentry_offset(), R19_method,
|
||||
R22_tmp2, R23_tmp3, MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS, IS_NOT_NULL);
|
||||
__ load_heap_oop(R19_method, java_lang_invoke_MemberName::method_offset(), R19_method,
|
||||
R22_tmp2, R23_tmp3, MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS, IS_NOT_NULL);
|
||||
__ ld(R19_method, java_lang_invoke_ResolvedMethodName::vmtarget_offset(), R19_method);
|
||||
__ std(R19_method, in_bytes(JavaThread::callee_target_offset()), R16_thread); // just in case callee is deoptimized
|
||||
|
||||
__ blr();
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
// Initialization
|
||||
void generate_initial_stubs() {
|
||||
// Generates all stubs and initializes the entry points
|
||||
@ -4651,6 +4675,7 @@ address generate_lookup_secondary_supers_table_stub(u1 super_klass_index) {
|
||||
}
|
||||
|
||||
StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler();
|
||||
StubRoutines::_upcall_stub_load_target = generate_upcall_stub_load_target();
|
||||
}
|
||||
|
||||
void generate_compiler_stubs() {
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
@ -118,7 +119,7 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
|
||||
static const int upcall_stub_code_base_size = 1024;
|
||||
static const int upcall_stub_size_per_arg = 16; // arg save & restore + move
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
@ -221,7 +222,6 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
__ block_comment("{ on_entry");
|
||||
__ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::on_entry), R0);
|
||||
__ addi(R3_ARG1, R1_SP, frame_data_offset);
|
||||
__ load_const_optimized(R4_ARG2, (intptr_t)receiver, R0);
|
||||
__ call_c(call_target_address);
|
||||
__ mr(R16_thread, R3_RET);
|
||||
__ block_comment("} on_entry");
|
||||
@ -236,12 +236,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
arg_shuffle.generate(_masm, as_VMStorage(callerSP), frame::native_abi_minframe_size, frame::jit_out_preserve_size);
|
||||
__ block_comment("} argument shuffle");
|
||||
|
||||
__ block_comment("{ receiver ");
|
||||
__ get_vm_result(R3_ARG1);
|
||||
__ block_comment("} receiver ");
|
||||
|
||||
__ load_const_optimized(R19_method, (intptr_t)entry);
|
||||
__ std(R19_method, in_bytes(JavaThread::callee_target_offset()), R16_thread);
|
||||
__ block_comment("{ load target ");
|
||||
__ load_const_optimized(call_target_address, StubRoutines::upcall_stub_load_target(), R0);
|
||||
__ load_const_optimized(R3_ARG1, (intptr_t)receiver, R0);
|
||||
__ mtctr(call_target_address);
|
||||
__ bctrl(); // loads target Method* into R19_method
|
||||
__ block_comment("} load target ");
|
||||
|
||||
__ push_cont_fastpath();
|
||||
|
||||
@ -326,7 +326,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
#ifndef PRODUCT
|
||||
stringStream ss;
|
||||
ss.print("upcall_stub_%s", entry->signature()->as_C_string());
|
||||
ss.print("upcall_stub_%s", signature->as_C_string());
|
||||
const char* name = _masm->code_string(ss.as_string());
|
||||
#else // PRODUCT
|
||||
const char* name = "upcall_stub";
|
||||
|
@ -6124,6 +6124,29 @@ static const int64_t right_3_bits = right_n_bits(3);
|
||||
return start;
|
||||
}
|
||||
|
||||
// load Method* target of MethodHandle
|
||||
// j_rarg0 = jobject receiver
|
||||
// xmethod = Method* result
|
||||
address generate_upcall_stub_load_target() {
|
||||
|
||||
StubCodeMark mark(this, "StubRoutines", "upcall_stub_load_target");
|
||||
address start = __ pc();
|
||||
|
||||
__ resolve_global_jobject(j_rarg0, t0, t1);
|
||||
// Load target method from receiver
|
||||
__ load_heap_oop(xmethod, Address(j_rarg0, java_lang_invoke_MethodHandle::form_offset()), t0, t1);
|
||||
__ load_heap_oop(xmethod, Address(xmethod, java_lang_invoke_LambdaForm::vmentry_offset()), t0, t1);
|
||||
__ load_heap_oop(xmethod, Address(xmethod, java_lang_invoke_MemberName::method_offset()), t0, t1);
|
||||
__ access_load_at(T_ADDRESS, IN_HEAP, xmethod,
|
||||
Address(xmethod, java_lang_invoke_ResolvedMethodName::vmtarget_offset()),
|
||||
noreg, noreg);
|
||||
__ sd(xmethod, Address(xthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
|
||||
|
||||
__ ret();
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
// Initialization
|
||||
@ -6189,6 +6212,7 @@ static const int64_t right_3_bits = right_n_bits(3);
|
||||
#endif // COMPILER2
|
||||
|
||||
StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler();
|
||||
StubRoutines::_upcall_stub_load_target = generate_upcall_stub_load_target();
|
||||
|
||||
StubRoutines::riscv::set_completed();
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
@ -117,7 +118,7 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
|
||||
static const int upcall_stub_code_base_size = 1024;
|
||||
static const int upcall_stub_size_per_arg = 16;
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
@ -223,7 +224,6 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
__ block_comment("{ on_entry");
|
||||
__ la(c_rarg0, Address(sp, frame_data_offset));
|
||||
__ movptr(c_rarg1, (address) receiver);
|
||||
__ rt_call(CAST_FROM_FN_PTR(address, UpcallLinker::on_entry));
|
||||
__ mv(xthread, x10);
|
||||
__ reinit_heapbase();
|
||||
@ -260,12 +260,10 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0);
|
||||
__ block_comment("} argument shuffle");
|
||||
|
||||
__ block_comment("{ receiver ");
|
||||
__ get_vm_result(j_rarg0, xthread);
|
||||
__ block_comment("} receiver ");
|
||||
|
||||
__ mov_metadata(xmethod, entry);
|
||||
__ sd(xmethod, Address(xthread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
|
||||
__ block_comment("{ load target ");
|
||||
__ movptr(j_rarg0, (address) receiver);
|
||||
__ far_call(RuntimeAddress(StubRoutines::upcall_stub_load_target())); // loads Method* into xmethod
|
||||
__ block_comment("} load target ");
|
||||
|
||||
__ push_cont_fastpath(xthread);
|
||||
|
||||
@ -338,7 +336,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
#ifndef PRODUCT
|
||||
stringStream ss;
|
||||
ss.print("upcall_stub_%s", entry->signature()->as_C_string());
|
||||
ss.print("upcall_stub_%s", signature->as_C_string());
|
||||
const char *name = _masm->code_string(ss.as_string());
|
||||
#else // PRODUCT
|
||||
const char* name = "upcall_stub";
|
||||
|
@ -3053,6 +3053,29 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
// load Method* target of MethodHandle
|
||||
// Z_ARG1 = jobject receiver
|
||||
// Z_method = Method* result
|
||||
address generate_upcall_stub_load_target() {
|
||||
StubCodeMark mark(this, "StubRoutines", "upcall_stub_load_target");
|
||||
address start = __ pc();
|
||||
|
||||
__ resolve_global_jobject(Z_ARG1, Z_tmp_1, Z_tmp_2);
|
||||
// Load target method from receiver
|
||||
__ load_heap_oop(Z_method, Address(Z_ARG1, java_lang_invoke_MethodHandle::form_offset()),
|
||||
noreg, noreg, IS_NOT_NULL);
|
||||
__ load_heap_oop(Z_method, Address(Z_method, java_lang_invoke_LambdaForm::vmentry_offset()),
|
||||
noreg, noreg, IS_NOT_NULL);
|
||||
__ load_heap_oop(Z_method, Address(Z_method, java_lang_invoke_MemberName::method_offset()),
|
||||
noreg, noreg, IS_NOT_NULL);
|
||||
__ z_lg(Z_method, Address(Z_method, java_lang_invoke_ResolvedMethodName::vmtarget_offset()));
|
||||
__ z_stg(Z_method, Address(Z_thread, JavaThread::callee_target_offset())); // just in case callee is deoptimized
|
||||
|
||||
__ z_br(Z_R14);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void generate_initial_stubs() {
|
||||
// Generates all stubs and initializes the entry points.
|
||||
|
||||
@ -3110,6 +3133,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler();
|
||||
StubRoutines::_upcall_stub_load_target = generate_upcall_stub_load_target();
|
||||
}
|
||||
|
||||
void generate_compiler_stubs() {
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
@ -116,7 +117,7 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
|
||||
|
||||
static const int upcall_stub_code_base_size = 1024;
|
||||
static const int upcall_stub_size_per_arg = 16; // arg save & restore + move
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
@ -206,7 +207,6 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
__ block_comment("on_entry {");
|
||||
__ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::on_entry));
|
||||
__ z_aghik(Z_ARG1, Z_SP, frame_data_offset);
|
||||
__ load_const_optimized(Z_ARG2, (intptr_t)receiver);
|
||||
__ call(call_target_address);
|
||||
__ z_lgr(Z_thread, Z_RET);
|
||||
__ block_comment("} on_entry");
|
||||
@ -216,12 +216,11 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
arg_shuffle.generate(_masm, shuffle_reg, abi._shadow_space_bytes, frame::z_jit_out_preserve_size);
|
||||
__ block_comment("} argument_shuffle");
|
||||
|
||||
__ block_comment("receiver {");
|
||||
__ get_vm_result(Z_ARG1);
|
||||
__ block_comment("} receiver");
|
||||
|
||||
__ load_const_optimized(Z_method, (intptr_t)entry);
|
||||
__ z_stg(Z_method, Address(Z_thread, in_bytes(JavaThread::callee_target_offset())));
|
||||
__ block_comment("load_target {");
|
||||
__ load_const_optimized(Z_ARG1, (intptr_t)receiver);
|
||||
__ load_const_optimized(call_target_address, StubRoutines::upcall_stub_load_target());
|
||||
__ call(call_target_address); // load taget Method* into Z_method
|
||||
__ block_comment("} load_target");
|
||||
|
||||
__ z_lg(call_target_address, Address(Z_method, in_bytes(Method::from_compiled_offset())));
|
||||
__ call(call_target_address);
|
||||
@ -274,7 +273,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
#ifndef PRODUCT
|
||||
stringStream ss;
|
||||
ss.print("upcall_stub_%s", entry->signature()->as_C_string());
|
||||
ss.print("upcall_stub_%s", signature->as_C_string());
|
||||
const char* name = _masm->code_string(ss.as_string());
|
||||
#else // PRODUCT
|
||||
const char* name = "upcall_stub";
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/vmIntrinsics.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
@ -3796,6 +3797,28 @@ address StubGenerator::generate_upcall_stub_exception_handler() {
|
||||
return start;
|
||||
}
|
||||
|
||||
// load Method* target of MethodHandle
|
||||
// j_rarg0 = jobject receiver
|
||||
// rbx = result
|
||||
address StubGenerator::generate_upcall_stub_load_target() {
|
||||
StubCodeMark mark(this, "StubRoutines", "upcall_stub_load_target");
|
||||
address start = __ pc();
|
||||
|
||||
__ resolve_global_jobject(j_rarg0, r15_thread, rscratch1);
|
||||
// Load target method from receiver
|
||||
__ load_heap_oop(rbx, Address(j_rarg0, java_lang_invoke_MethodHandle::form_offset()), rscratch1);
|
||||
__ load_heap_oop(rbx, Address(rbx, java_lang_invoke_LambdaForm::vmentry_offset()), rscratch1);
|
||||
__ load_heap_oop(rbx, Address(rbx, java_lang_invoke_MemberName::method_offset()), rscratch1);
|
||||
__ access_load_at(T_ADDRESS, IN_HEAP, rbx,
|
||||
Address(rbx, java_lang_invoke_ResolvedMethodName::vmtarget_offset()),
|
||||
noreg, noreg);
|
||||
__ movptr(Address(r15_thread, JavaThread::callee_target_offset()), rbx); // just in case callee is deoptimized
|
||||
|
||||
__ ret(0);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
address StubGenerator::generate_lookup_secondary_supers_table_stub(u1 super_klass_index) {
|
||||
StubCodeMark mark(this, "StubRoutines", "lookup_secondary_supers_table");
|
||||
|
||||
@ -3955,6 +3978,7 @@ void StubGenerator::generate_final_stubs() {
|
||||
}
|
||||
|
||||
StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler();
|
||||
StubRoutines::_upcall_stub_load_target = generate_upcall_stub_load_target();
|
||||
}
|
||||
|
||||
void StubGenerator::generate_compiler_stubs() {
|
||||
|
@ -620,6 +620,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
// shared exception handler for FFM upcall stubs
|
||||
address generate_upcall_stub_exception_handler();
|
||||
address generate_upcall_stub_load_target();
|
||||
|
||||
// Specialized stub implementations for UseSecondarySupersTable.
|
||||
address generate_lookup_secondary_supers_table_stub(u1 super_klass_index);
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "asm/macroAssembler.hpp"
|
||||
#include "code/codeBlob.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "code/codeBlob.hpp"
|
||||
#include "code/vmreg.inline.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
@ -169,10 +169,10 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
|
||||
__ block_comment("} restore_callee_saved_regs ");
|
||||
}
|
||||
|
||||
static const int upcall_stub_code_base_size = 1024;
|
||||
static const int upcall_stub_code_base_size = 1200;
|
||||
static const int upcall_stub_size_per_arg = 16;
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject receiver, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
@ -281,7 +281,6 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
__ block_comment("{ on_entry");
|
||||
__ vzeroupper();
|
||||
__ lea(c_rarg0, Address(rsp, frame_data_offset));
|
||||
__ movptr(c_rarg1, (intptr_t)receiver);
|
||||
// stack already aligned
|
||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, UpcallLinker::on_entry)));
|
||||
__ movptr(r15_thread, rax);
|
||||
@ -297,12 +296,10 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
arg_shuffle.generate(_masm, shuffle_reg, abi._shadow_space_bytes, 0);
|
||||
__ block_comment("} argument shuffle");
|
||||
|
||||
__ block_comment("{ receiver ");
|
||||
__ get_vm_result(j_rarg0, r15_thread);
|
||||
__ block_comment("} receiver ");
|
||||
|
||||
__ mov_metadata(rbx, entry);
|
||||
__ movptr(Address(r15_thread, JavaThread::callee_target_offset()), rbx); // just in case callee is deoptimized
|
||||
__ block_comment("{ load target ");
|
||||
__ movptr(j_rarg0, (intptr_t)receiver);
|
||||
__ call(RuntimeAddress(StubRoutines::upcall_stub_load_target())); // puts target Method* in rbx
|
||||
__ block_comment("} load target ");
|
||||
|
||||
__ push_cont_fastpath();
|
||||
|
||||
@ -377,7 +374,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
|
||||
|
||||
#ifndef PRODUCT
|
||||
stringStream ss;
|
||||
ss.print("upcall_stub_%s", entry->signature()->as_C_string());
|
||||
ss.print("upcall_stub_%s", signature->as_C_string());
|
||||
const char* name = _masm->code_string(ss.freeze());
|
||||
#else // PRODUCT
|
||||
const char* name = "upcall_stub";
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "prims/upcallLinker.hpp"
|
||||
|
||||
address UpcallLinker::make_upcall_stub(jobject mh, Method* entry,
|
||||
address UpcallLinker::make_upcall_stub(jobject mh, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/javaFrameAnchor.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
@ -623,7 +623,7 @@ UpcallStub* UpcallStub::create(const char* name, CodeBuffer* cb, jobject receive
|
||||
// Track memory usage statistic after releasing CodeCache_lock
|
||||
MemoryService::track_code_cache_memory_usage();
|
||||
|
||||
trace_new_stub(blob, "UpcallStub");
|
||||
trace_new_stub(blob, "UpcallStub - ", name);
|
||||
|
||||
return blob;
|
||||
}
|
||||
@ -772,6 +772,10 @@ void UpcallStub::verify() {
|
||||
void UpcallStub::print_on(outputStream* st) const {
|
||||
RuntimeBlob::print_on(st);
|
||||
print_value_on(st);
|
||||
st->print_cr("Frame data offset: %d", (int) _frame_data_offset);
|
||||
oop recv = JNIHandles::resolve(_receiver);
|
||||
st->print("Receiver MH=");
|
||||
recv->print_on(st);
|
||||
Disassembler::decode((RuntimeBlob*)this, st);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "compiler/compilationPolicy.hpp"
|
||||
@ -73,7 +73,7 @@ JavaThread* UpcallLinker::maybe_attach_and_get_thread() {
|
||||
}
|
||||
|
||||
// modelled after JavaCallWrapper::JavaCallWrapper
|
||||
JavaThread* UpcallLinker::on_entry(UpcallStub::FrameData* context, jobject receiver) {
|
||||
JavaThread* UpcallLinker::on_entry(UpcallStub::FrameData* context) {
|
||||
JavaThread* thread = maybe_attach_and_get_thread();
|
||||
guarantee(thread->thread_state() == _thread_in_native, "wrong thread state for upcall");
|
||||
context->thread = thread;
|
||||
@ -108,8 +108,6 @@ JavaThread* UpcallLinker::on_entry(UpcallStub::FrameData* context, jobject recei
|
||||
debug_only(thread->inc_java_call_counter());
|
||||
thread->set_active_handles(context->new_handles); // install new handle block and reset Java frame linkage
|
||||
|
||||
thread->set_vm_result(JNIHandles::resolve(receiver));
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
@ -138,11 +136,10 @@ void UpcallLinker::on_exit(UpcallStub::FrameData* context) {
|
||||
}
|
||||
|
||||
void UpcallLinker::handle_uncaught_exception(oop exception) {
|
||||
ResourceMark rm;
|
||||
// Based on CATCH macro
|
||||
tty->print_cr("Uncaught exception:");
|
||||
exception->print();
|
||||
ShouldNotReachHere();
|
||||
Handle exception_h(Thread::current(), exception);
|
||||
java_lang_Throwable::print_stack_trace(exception_h, tty);
|
||||
fatal("Unrecoverable uncaught exception encountered");
|
||||
}
|
||||
|
||||
JVM_ENTRY(jlong, UL_MakeUpcallStub(JNIEnv *env, jclass unused, jobject mh, jobject abi, jobject conv,
|
||||
@ -150,36 +147,30 @@ JVM_ENTRY(jlong, UL_MakeUpcallStub(JNIEnv *env, jclass unused, jobject mh, jobje
|
||||
ResourceMark rm(THREAD);
|
||||
Handle mh_h(THREAD, JNIHandles::resolve(mh));
|
||||
jobject mh_j = JNIHandles::make_global(mh_h);
|
||||
oop type = java_lang_invoke_MethodHandle::type(mh_h());
|
||||
|
||||
oop lform = java_lang_invoke_MethodHandle::form(mh_h());
|
||||
oop vmentry = java_lang_invoke_LambdaForm::vmentry(lform);
|
||||
Method* entry = java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||
const methodHandle mh_entry(THREAD, entry);
|
||||
|
||||
assert(entry->method_holder()->is_initialized(), "no clinit barrier");
|
||||
CompilationPolicy::compile_if_required(mh_entry, CHECK_0);
|
||||
|
||||
assert(entry->is_static(), "static only");
|
||||
// Fill in the signature array, for the calling-convention call.
|
||||
const int total_out_args = entry->size_of_parameters();
|
||||
assert(total_out_args > 0, "receiver arg");
|
||||
const int total_out_args = java_lang_invoke_MethodType::ptype_slot_count(type) + 1; // +1 for receiver
|
||||
|
||||
bool create_new = true;
|
||||
TempNewSymbol signature = java_lang_invoke_MethodType::as_signature(type, create_new);
|
||||
BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_out_args);
|
||||
BasicType ret_type;
|
||||
{
|
||||
int i = 0;
|
||||
SignatureStream ss(entry->signature());
|
||||
out_sig_bt[i++] = T_OBJECT; // receiver MH
|
||||
SignatureStream ss(signature);
|
||||
for (; !ss.at_return_type(); ss.next()) {
|
||||
out_sig_bt[i++] = ss.type(); // Collect remaining bits of signature
|
||||
if (ss.type() == T_LONG || ss.type() == T_DOUBLE)
|
||||
out_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots
|
||||
}
|
||||
assert(i == total_out_args, "");
|
||||
assert(i == total_out_args, "%d != %d", i, total_out_args);
|
||||
ret_type = ss.type();
|
||||
}
|
||||
|
||||
return (jlong) UpcallLinker::make_upcall_stub(
|
||||
mh_j, entry, out_sig_bt, total_out_args, ret_type,
|
||||
mh_j, signature, out_sig_bt, total_out_args, ret_type,
|
||||
abi, conv, needs_return_buffer, checked_cast<int>(ret_buf_size));
|
||||
JVM_END
|
||||
|
||||
|
@ -34,10 +34,10 @@ class UpcallLinker {
|
||||
private:
|
||||
static JavaThread* maybe_attach_and_get_thread();
|
||||
|
||||
static JavaThread* on_entry(UpcallStub::FrameData* context, jobject receiver);
|
||||
static JavaThread* on_entry(UpcallStub::FrameData* context);
|
||||
static void on_exit(UpcallStub::FrameData* context);
|
||||
public:
|
||||
static address make_upcall_stub(jobject mh, Method* entry,
|
||||
static address make_upcall_stub(jobject mh, Symbol* signature,
|
||||
BasicType* out_sig_bt, int total_out_args,
|
||||
BasicType ret_type,
|
||||
jobject jabi, jobject jconv,
|
||||
|
@ -719,6 +719,8 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose
|
||||
st->print("v ~MethodHandlesAdapterBlob " PTR_FORMAT, p2i(pc()));
|
||||
} else if (_cb->is_uncommon_trap_stub()) {
|
||||
st->print("v ~UncommonTrapBlob " PTR_FORMAT, p2i(pc()));
|
||||
} else if (_cb->is_upcall_stub()) {
|
||||
st->print("v ~UpcallStub::%s " PTR_FORMAT, _cb->name(), p2i(pc()));
|
||||
} else {
|
||||
st->print("v blob " PTR_FORMAT, p2i(pc()));
|
||||
}
|
||||
@ -1116,6 +1118,19 @@ void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) const {
|
||||
entry_frame_call_wrapper()->oops_do(f);
|
||||
}
|
||||
|
||||
void frame::oops_upcall_do(OopClosure* f, const RegisterMap* map) const {
|
||||
assert(map != nullptr, "map must be set");
|
||||
if (map->include_argument_oops()) {
|
||||
// Upcall stubs call a MethodHandle impl method of which only the receiver
|
||||
// is ever an oop.
|
||||
// Currently we should not be able to get here, since there are no
|
||||
// safepoints in the one resolve stub we can get into (handle_wrong_method)
|
||||
// Leave this here as a trap in case we ever do:
|
||||
ShouldNotReachHere(); // not implemented
|
||||
}
|
||||
_cb->as_upcall_stub()->oops_do(f, *this);
|
||||
}
|
||||
|
||||
bool frame::is_deoptimized_frame() const {
|
||||
assert(_deopt_state != unknown, "not answerable");
|
||||
if (_deopt_state == is_deoptimized) {
|
||||
@ -1147,7 +1162,7 @@ void frame::oops_do_internal(OopClosure* f, NMethodClosure* cf,
|
||||
} else if (is_entry_frame()) {
|
||||
oops_entry_do(f, map);
|
||||
} else if (is_upcall_stub_frame()) {
|
||||
_cb->as_upcall_stub()->oops_do(f, *this);
|
||||
oops_upcall_do(f, map);
|
||||
} else if (CodeCache::contains(pc())) {
|
||||
oops_nmethod_do(f, cf, df, derived_mode, map);
|
||||
} else {
|
||||
|
@ -464,6 +464,7 @@ class frame {
|
||||
const RegisterMap* map, bool use_interpreter_oop_map_cache) const;
|
||||
|
||||
void oops_entry_do(OopClosure* f, const RegisterMap* map) const;
|
||||
void oops_upcall_do(OopClosure* f, const RegisterMap* map) const;
|
||||
void oops_nmethod_do(OopClosure* f, NMethodClosure* cf,
|
||||
DerivedOopClosure* df, DerivedPointerIterationMode derived_mode,
|
||||
const RegisterMap* map) const;
|
||||
|
@ -188,6 +188,7 @@ address StubRoutines::_cont_returnBarrier = nullptr;
|
||||
address StubRoutines::_cont_returnBarrierExc = nullptr;
|
||||
|
||||
address StubRoutines::_upcall_stub_exception_handler = nullptr;
|
||||
address StubRoutines::_upcall_stub_load_target = nullptr;
|
||||
|
||||
address StubRoutines::_lookup_secondary_supers_table_slow_path_stub = nullptr;
|
||||
address StubRoutines::_lookup_secondary_supers_table_stubs[Klass::SECONDARY_SUPERS_TABLE_SIZE] = { nullptr };
|
||||
|
@ -298,6 +298,7 @@ class StubRoutines: AllStatic {
|
||||
static address _vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_SVML_OP];
|
||||
|
||||
static address _upcall_stub_exception_handler;
|
||||
static address _upcall_stub_load_target;
|
||||
|
||||
static address _lookup_secondary_supers_table_stubs[];
|
||||
static address _lookup_secondary_supers_table_slow_path_stub;
|
||||
@ -506,6 +507,11 @@ class StubRoutines: AllStatic {
|
||||
return _upcall_stub_exception_handler;
|
||||
}
|
||||
|
||||
static address upcall_stub_load_target() {
|
||||
assert(_upcall_stub_load_target != nullptr, "not implemented");
|
||||
return _upcall_stub_load_target;
|
||||
}
|
||||
|
||||
static address lookup_secondary_supers_table_stub(u1 slot) {
|
||||
assert(slot < Klass::SECONDARY_SUPERS_TABLE_SIZE, "out of bounds");
|
||||
assert(_lookup_secondary_supers_table_stubs[slot] != nullptr, "not implemented");
|
||||
|
@ -381,7 +381,8 @@ jdk_svc = \
|
||||
jdk_foreign = \
|
||||
java/foreign \
|
||||
jdk/internal/reflect/CallerSensitive/CheckCSMs.java \
|
||||
-java/foreign/TestMatrix.java
|
||||
-java/foreign/TestMatrix.java \
|
||||
-java/foreign/TestUpcallStress.java
|
||||
|
||||
jdk_vector = \
|
||||
jdk/incubator/vector
|
||||
|
97
test/jdk/java/foreign/TestUpcallStress.java
Normal file
97
test/jdk/java/foreign/TestUpcallStress.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires jdk.foreign.linker != "FALLBACK"
|
||||
* @requires (os.arch == "aarch64" | os.arch=="riscv64") & os.name == "Linux"
|
||||
* @requires os.maxMemory > 4G
|
||||
* @modules java.base/jdk.internal.foreign
|
||||
* @build NativeTestHelper CallGeneratorHelper TestUpcallBase
|
||||
* @bug 8337753
|
||||
*
|
||||
* @run testng/othervm/timeout=3200
|
||||
* -Xcheck:jni
|
||||
* -XX:+IgnoreUnrecognizedVMOptions
|
||||
* -XX:-VerifyDependencies
|
||||
* --enable-native-access=ALL-UNNAMED
|
||||
* -Dgenerator.sample.factor=17
|
||||
* TestUpcallStress
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TestUpcallStress extends TestUpcallBase {
|
||||
|
||||
static {
|
||||
System.loadLibrary("TestUpcall");
|
||||
}
|
||||
|
||||
@Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class)
|
||||
public void testUpcallsStress(int count, String fName, Ret ret, List<ParamType> paramTypes,
|
||||
List<StructFieldType> fields) throws Throwable {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(16);
|
||||
for (int threadIdx = 0; threadIdx < 16; threadIdx++) {
|
||||
executor.submit(() -> {
|
||||
for (int iter = 0; iter < 10000; iter++) {
|
||||
List<Consumer<Object>> returnChecks = new ArrayList<>();
|
||||
List<Consumer<Object>> argChecks = new ArrayList<>();
|
||||
MemorySegment addr = findNativeOrThrow(fName);
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
FunctionDescriptor descriptor = function(ret, paramTypes, fields);
|
||||
MethodHandle mh = downcallHandle(LINKER, addr, arena, descriptor);
|
||||
AtomicReference<Object[]> capturedArgs = new AtomicReference<>();
|
||||
Object[] args = makeArgs(capturedArgs, arena, descriptor, returnChecks, argChecks, 0);
|
||||
|
||||
Object res = mh.invokeWithArguments(args);
|
||||
|
||||
if (ret == Ret.NON_VOID) {
|
||||
returnChecks.forEach(c -> c.accept(res));
|
||||
}
|
||||
|
||||
Object[] capturedArgsArr = capturedArgs.get();
|
||||
for (int i = 0; i < capturedArgsArr.length; i++) {
|
||||
argChecks.get(i).accept(capturedArgsArr[i]);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// This shutdownNow is 'wrong', since it doesn't wait for tasks to terminate,
|
||||
// but it seems to be the only way to reproduce the race of JDK-8337753
|
||||
executor.shutdownNow();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user