8287071: Loom: Cleanup x86_64 gen_continuation_enter

Reviewed-by: rpressler, pchilanomate, kvn
This commit is contained in:
Aleksey Shipilev 2022-06-07 06:55:35 +00:00
parent f6a79e340f
commit 956d44d2da
2 changed files with 96 additions and 63 deletions

@ -1259,99 +1259,129 @@ static void verify_oop_args(MacroAssembler* masm,
// defined in stubGenerator_x86_64.cpp
OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots);
void fill_continuation_entry(MacroAssembler* masm);
void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, Register reg_flags);
void continuation_enter_cleanup(MacroAssembler* masm);
// enterSpecial(Continuation c, boolean isContinue, boolean isVirtualThread)
// On entry: c_rarg1 -- the continuation object
// c_rarg2 -- isContinue
// c_rarg3 -- isVirtualThread
static void check_continuation_enter_argument(VMReg actual_vmreg,
Register expected_reg,
const char* name) {
assert(!actual_vmreg->is_stack(), "%s cannot be on stack", name);
assert(actual_vmreg->as_Register() == expected_reg,
"%s is in unexpected register: %s instead of %s",
name, actual_vmreg->as_Register()->name(), expected_reg->name());
}
static void gen_continuation_enter(MacroAssembler* masm,
const methodHandle& method,
const BasicType* sig_bt,
const VMRegPair* regs,
int& exception_offset,
OopMapSet*oop_maps,
OopMapSet* oop_maps,
int& frame_complete,
int& stack_slots) {
//verify_oop_args(masm, method, sig_bt, regs);
AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(),
relocInfo::static_call_type);
stack_slots = 2; // will be overwritten
// enterSpecial(Continuation c, boolean isContinue, boolean isVirtualThread)
int pos_cont_obj = 0;
int pos_is_cont = 1;
int pos_is_virtual = 2;
// The platform-specific calling convention may present the arguments in various registers.
// To simplify the rest of the code, we expect the arguments to reside at these known
// registers, and we additionally check the placement here in case calling convention ever
// changes.
Register reg_cont_obj = c_rarg1;
Register reg_is_cont = c_rarg2;
Register reg_is_virtual = c_rarg3;
check_continuation_enter_argument(regs[pos_cont_obj].first(), reg_cont_obj, "Continuation object");
check_continuation_enter_argument(regs[pos_is_cont].first(), reg_is_cont, "isContinue");
check_continuation_enter_argument(regs[pos_is_virtual].first(), reg_is_virtual, "isVirtualThread");
// Utility methods kill rax, make sure there are no collisions
assert_different_registers(rax, reg_cont_obj, reg_is_cont, reg_is_virtual);
address start = __ pc();
Label call_thaw, exit;
__ enter();
//BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
//bs->nmethod_entry_barrier(masm);
OopMap* map = continuation_enter_setup(masm, stack_slots); // kills rax
stack_slots = 2; // will be adjusted in setup
OopMap* map = continuation_enter_setup(masm, stack_slots);
// Frame is now completed as far as size and linkage.
frame_complete =__ pc() - start;
// if isContinue == 0
// _enterSP = sp
// end
frame_complete = __ pc() - start;
fill_continuation_entry(masm); // kills rax
__ verify_oop(reg_cont_obj);
__ cmpl(c_rarg2, 0);
__ jcc(Assembler::notEqual, call_thaw);
fill_continuation_entry(masm, reg_cont_obj, reg_is_virtual);
int up = align_up((intptr_t) __ pc() + 1, 4) - (intptr_t) (__ pc() + 1);
if (up > 0) {
__ nop(up);
Label L_thaw, L_exit;
// If continuation, call to thaw. Otherwise, resolve the call and exit.
__ testptr(reg_is_cont, reg_is_cont);
__ jccb(Assembler::notZero, L_thaw);
// --- Resolve path
// Make sure the call is patchable
__ align(BytesPerWord, __ offset() + NativeCall::displacement_offset);
// Emit stub for static call
CodeBuffer* cbuf = masm->code_section()->outer();
address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc());
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
address mark = __ pc();
// Call the resolve stub
AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(),
relocInfo::static_call_type);
__ call(resolve);
oop_maps->add_gc_map(__ pc() - start, map);
__ post_call_nop();
__ jmp(exit);
__ jmpb(L_exit);
__ bind(call_thaw);
// --- Thawing path
__ bind(L_thaw);
__ call(RuntimeAddress(StubRoutines::cont_thaw()));
__ movptr(rbx, (intptr_t) StubRoutines::cont_thaw());
__ call(rbx);
oop_maps->add_gc_map(__ pc() - start, map->deep_copy());
ContinuationEntry::_return_pc_offset = __ pc() - start;
oop_maps->add_gc_map(__ pc() - start, map->deep_copy());
__ post_call_nop();
__ bind(exit);
// --- Normal exit (resolve/thawing)
__ bind(L_exit);
continuation_enter_cleanup(masm);
__ pop(rbp);
__ ret(0);
/// exception handling
// --- Exception handling path
exception_offset = __ pc() - start;
continuation_enter_cleanup(masm);
__ pop(rbp);
__ movptr(rbx, rax); // save the exception
__ movptr(c_rarg0, Address(rsp, 0));
__ movptr(c_rarg0, r15_thread);
__ movptr(c_rarg1, Address(rsp, 0)); // return address
__ call_VM_leaf(CAST_FROM_FN_PTR(address,
SharedRuntime::exception_handler_for_return_address),
r15_thread, c_rarg0);
__ mov(rdi, rax);
__ movptr(rax, rbx);
__ mov(rbx, rdi);
__ pop(rdx);
// rax still holds the original exception oop, save it before the call
__ push(rax);
// continue at exception handler (return address removed)
// rax: exception
// rbx: exception handler
// rdx: throwing pc
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), 2);
__ movptr(rbx, rax);
// Continue at exception handler:
// rax: exception oop
// rbx: exception handler
// rdx: exception pc
__ pop(rax);
__ verify_oop(rax);
__ pop(rdx);
__ jmp(rbx);
CodeBuffer* cbuf = masm->code_section()->outer();
address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, mark);
}
static void gen_special_dispatch(MacroAssembler* masm,
@ -1447,8 +1477,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
int stack_slots = 0;
OopMapSet* oop_maps = new OopMapSet();
gen_continuation_enter(masm,
method,
in_sig_bt,
in_regs,
exception_offset,
oop_maps,

@ -7666,11 +7666,14 @@ address generate_avx_ghash_processBlocks() {
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), 2);
__ movptr(rbx, rax);
// rbx now holds the exception handler.
// Prepare for its invocation; see OptoRuntime::generate_exception_blob.
__ pop(rax); // exception oop
__ pop(rbp);
__ pop(rdx); // exception pc
// Continue at exception handler:
// rax: exception oop
// rbx: exception handler
// rdx: exception pc
__ pop(rax);
__ verify_oop(rax);
__ pop(rbp); // pop out RBP here too
__ pop(rdx);
__ jmp(rbx);
} else {
// We are "returning" into the topmost thawed frame; see Thaw::push_return_frame
@ -8309,8 +8312,8 @@ OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots) {
//
// Arguments:
// rsp: pointer to blank Continuation entry
// c_rarg1: pointer to the continuation
// c_rarg3: flags
// reg_cont_obj: pointer to the continuation
// reg_flags: flags
//
// Results:
// rsp: pointer to filled out ContinuationEntry
@ -8318,11 +8321,13 @@ OopMap* continuation_enter_setup(MacroAssembler* masm, int& stack_slots) {
// Kills:
// rax
//
void fill_continuation_entry(MacroAssembler* masm) {
void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, Register reg_flags) {
assert_different_registers(rax, reg_cont_obj, reg_flags);
DEBUG_ONLY(__ movl(Address(rsp, ContinuationEntry::cookie_offset()), ContinuationEntry::cookie_value());)
__ movptr(Address(rsp, ContinuationEntry::cont_offset()), c_rarg1);
__ movl (Address(rsp, ContinuationEntry::flags_offset()), c_rarg3);
__ movptr(Address(rsp, ContinuationEntry::cont_offset()), reg_cont_obj);
__ movl (Address(rsp, ContinuationEntry::flags_offset()), reg_flags);
__ movptr(Address(rsp, ContinuationEntry::chunk_offset()), 0);
__ movl(Address(rsp, ContinuationEntry::argsize_offset()), 0);
__ movl(Address(rsp, ContinuationEntry::pin_count_offset()), 0);