Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8241764: [lworld] TestC2CCalls fails with SIGSEGV in frame::sender_for_compiled_frame #12

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -480,7 +480,8 @@ int LIR_Assembler::emit_unwind_handler() {
}

// remove the activation and dispatch to the unwind handler
__ remove_frame(initial_frame_size_in_bytes(), needs_stack_repair());
int initial_framesize = initial_frame_size_in_bytes();
__ remove_frame(initial_framesize, needs_stack_repair(), initial_framesize - wordSize);
__ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));

// Emit the slow path assembly
@@ -546,7 +547,8 @@ void LIR_Assembler::return_op(LIR_Opr result) {
}

// Pop the stack before the safepoint code
__ remove_frame(initial_frame_size_in_bytes(), needs_stack_repair());
int initial_framesize = initial_frame_size_in_bytes();
__ remove_frame(initial_framesize, needs_stack_repair(), initial_framesize - wordSize);

if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
__ reserved_stack_check();
@@ -345,9 +345,8 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by
#endif // !_LP64 && TIERED
decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
if (needs_stack_repair) {
int real_frame_size = frame_size_in_bytes
+ wordSize // skip over pushed rbp
+ wordSize; // skip over RA pushed by caller
// Save stack increment (also account for rbp)
int real_frame_size = frame_size_in_bytes + wordSize;
movptr(Address(rsp, frame_size_in_bytes - wordSize), real_frame_size);
if (verified_value_entry_label != NULL) {
bind(*verified_value_entry_label);
@@ -358,20 +357,6 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by
bs->nmethod_entry_barrier(this);
}


void C1_MacroAssembler::remove_frame(int frame_size_in_bytes, bool needs_stack_repair) {
if (!needs_stack_repair) {
increment(rsp, frame_size_in_bytes); // Does not emit code for frame_size == 0
pop(rbp);
} else {
movq(r13, Address(rsp, frame_size_in_bytes + wordSize)); // return address
movq(rbp, Address(rsp, frame_size_in_bytes));
addq(rsp, Address(rsp, frame_size_in_bytes - wordSize)); // now we are back to caller frame, without the outgoing return address
push(r13); // restore the return address, as pushed by caller
}
}


void C1_MacroAssembler::verified_entry() {
if (C1Breakpoint || VerifyFPU || !UseStackBanging) {
// Verified Entry first instruction should be 5 bytes long for correct
@@ -407,27 +392,28 @@ int C1_MacroAssembler::scalarized_entry(const CompiledEntrySignature *ces, int f
int args_passed_cc = SigEntry::fill_sig_bt(sig_cc, sig_bt);
int extra_stack_offset = wordSize; // tos is return address.

int sp_inc = (args_on_stack - args_on_stack_cc) * VMRegImpl::stack_slot_size;
if (sp_inc > 0) {
pop(r13);
// Check if we need to extend the stack for packing
int sp_inc = 0;
if (args_on_stack > args_on_stack_cc) {
// Two additional slots to account for return address
sp_inc = (args_on_stack + 2) * VMRegImpl::stack_slot_size;
sp_inc = align_up(sp_inc, StackAlignmentInBytes);
pop(r13); // Copy return address
subptr(rsp, sp_inc);
push(r13);
} else {
sp_inc = 0;
}

// Create a temp frame so we can call into runtime. It must be properly set up to accommodate GC.
// Create a temp frame so we can call into the runtime. It must be properly set up to accommodate GC.
push(rbp);
if (PreserveFramePointer) {
mov(rbp, rsp);
}
subptr(rsp, frame_size_in_bytes);
if (sp_inc > 0) {
int real_frame_size = frame_size_in_bytes +
+ wordSize // pushed rbp
+ wordSize // return address pushed by the stack extension code
+ sp_inc; // stack extension

if (ces->c1_needs_stack_repair()) {
// Save stack increment (also account for fixed framesize and rbp)
assert((sp_inc & (StackAlignmentInBytes-1)) == 0, "stack increment not aligned");
int real_frame_size = sp_inc + frame_size_in_bytes + wordSize;
movptr(Address(rsp, frame_size_in_bytes - wordSize), real_frame_size);
}

@@ -447,15 +433,13 @@ int C1_MacroAssembler::scalarized_entry(const CompiledEntrySignature *ces, int f
addptr(rsp, frame_size_in_bytes);
pop(rbp);

int n = shuffle_value_args(true, is_value_ro_entry, extra_stack_offset, sig_bt, sig_cc,
args_passed_cc, args_on_stack_cc, regs_cc, // from
args_passed, args_on_stack, regs); // to
assert(sp_inc == n, "must be");
shuffle_value_args(true, is_value_ro_entry, extra_stack_offset, sig_bt, sig_cc,
args_passed_cc, args_on_stack_cc, regs_cc, // from
args_passed, args_on_stack, regs, sp_inc); // to

if (sp_inc != 0) {
if (ces->c1_needs_stack_repair()) {
// Skip over the stack banging and frame setup code in the
// verified_value_entry (which has a different real_frame_size).
assert(sp_inc > 0, "stack should not shrink");
push(rbp);
if (PreserveFramePointer) {
mov(rbp, rsp);
@@ -451,7 +451,7 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const {
// It is only an FP if the sender is an interpreter frame (or C1?).
intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset);

// Repair the sender sp if this is a method with scalarized value type args
// Repair the sender sp if the frame has been extended
sender_sp = repair_sender_sp(sender_sp, saved_fp_addr);

// On Intel the return_address is always the word on the stack
@@ -714,11 +714,7 @@ intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr)
// The stack increment resides just below the saved rbp on the stack
// and does not account for the return address.
intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1);
int real_frame_size = (*real_frame_size_addr) / wordSize;
if (!cm->is_compiled_by_c1()) {
// Add size of return address (C1 already includes the RA size)
real_frame_size += 1;
}
int real_frame_size = ((*real_frame_size_addr) + wordSize) / wordSize;
assert(real_frame_size >= _cb->frame_size(), "invalid frame size");
sender_sp = unextended_sp() + real_frame_size;
}
@@ -6420,26 +6420,18 @@ void MacroAssembler::unpack_value_args(Compile* C, bool receiver_only) {
verified_entry(C, sp_inc);
}

int MacroAssembler::shuffle_value_args(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs, // from
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to) { // to
void MacroAssembler::shuffle_value_args(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs,
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to, int sp_inc) {
// Check if we need to extend the stack for packing/unpacking
int sp_inc = (args_on_stack_to - args_on_stack) * VMRegImpl::stack_slot_size;
if (sp_inc > 0) {
sp_inc = align_up(sp_inc, StackAlignmentInBytes);
if (!is_packing) {
// Save the return address, adjust the stack (make sure it is properly
// 16-byte aligned) and copy the return address to the new top of the stack.
// (Note: C1 does this in C1_MacroAssembler::scalarized_entry).
pop(r13);
subptr(rsp, sp_inc);
push(r13);
}
} else {
// The scalarized calling convention needs less stack space than the unscalarized one.
// No need to extend the stack, the caller will take care of these adjustments.
sp_inc = 0;
if (sp_inc > 0 && !is_packing) {
// Save the return address, adjust the stack (make sure it is properly
// 16-byte aligned) and copy the return address to the new top of the stack.
// (Note: C1 does this in C1_MacroAssembler::scalarized_entry).
pop(r13);
subptr(rsp, sp_inc);
push(r13);
}

int ret_off; // make sure we don't overwrite the return address
@@ -6452,31 +6444,26 @@ int MacroAssembler::shuffle_value_args(bool is_packing, bool receiver_only, int
ret_off = sp_inc;
}

return shuffle_value_args_common(is_packing, receiver_only, extra_stack_offset,
sig_bt, sig_cc,
args_passed, args_on_stack, regs,
args_passed_to, args_on_stack_to, regs_to,
sp_inc, ret_off);
shuffle_value_args_common(is_packing, receiver_only, extra_stack_offset,
sig_bt, sig_cc,
args_passed, args_on_stack, regs,
args_passed_to, args_on_stack_to, regs_to,
sp_inc, ret_off);
}

VMReg MacroAssembler::spill_reg_for(VMReg reg) {
return reg->is_XMMRegister() ? xmm8->as_VMReg() : r14->as_VMReg();
}

// Restores the stack on return
void MacroAssembler::restore_stack(Compile* C) {
int framesize = C->frame_size_in_bytes();
assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
// Remove word for return addr already pushed and RBP
framesize -= 2*wordSize;

if (C->needs_stack_repair()) {
void MacroAssembler::remove_frame(int initial_framesize, bool needs_stack_repair, int sp_inc_offset) {
assert((initial_framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
if (needs_stack_repair) {
// Restore rbp and repair rsp by adding the stack increment
movq(rbp, Address(rsp, framesize));
addq(rsp, Address(rsp, C->sp_inc_offset()));
movq(rbp, Address(rsp, initial_framesize));
addq(rsp, Address(rsp, sp_inc_offset));
} else {
if (framesize > 0) {
addq(rsp, framesize);
if (initial_framesize > 0) {
addq(rsp, initial_framesize);
}
pop(rbp);
}
@@ -1717,12 +1717,12 @@ class MacroAssembler: public Assembler {
bool pack_value_helper(const GrowableArray<SigEntry>* sig, int& sig_index, int vtarg_index,
VMReg to, VMRegPair* regs_from, int regs_from_count, int& from_index, RegState reg_state[],
int ret_off, int extra_stack_offset);
void restore_stack(Compile* C);
void remove_frame(int initial_framesize, bool needs_stack_repair, int sp_inc_offset);

int shuffle_value_args(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs,
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to);
void shuffle_value_args(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs,
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to, int sp_inc);
bool shuffle_value_args_spill(bool is_packing, const GrowableArray<SigEntry>* sig_cc, int sig_cc_index,
VMRegPair* regs_from, int from_index, int regs_from_count,
RegState* reg_state, int sp_inc, int extra_stack_offset);
@@ -963,8 +963,9 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
__ vzeroupper();
}

__ restore_stack(C);

// Subtract two words to account for return address and rbp
int initial_framesize = C->frame_size_in_bytes() - 2*wordSize;
__ remove_frame(initial_framesize, C->needs_stack_repair(), C->sp_inc_offset());

if (StackReservedPages > 0 && C->has_reserved_stack_access()) {
__ reserved_stack_check();
@@ -166,19 +166,24 @@ int MacroAssembler::unpack_value_args_common(Compile* C, bool receiver_only) {
int args_passed_cc = SigEntry::fill_sig_bt(sig_cc, sig_bt);
VMRegPair* regs_cc = NEW_RESOURCE_ARRAY(VMRegPair, sig_cc->length());
int args_on_stack_cc = SharedRuntime::java_calling_convention(sig_bt, regs_cc, args_passed_cc, false);

int extra_stack_offset = wordSize; // stack has the returned address
int sp_inc = shuffle_value_args(false, receiver_only, extra_stack_offset, sig_bt, sig_cc,
args_passed, args_on_stack, regs,
args_passed_cc, args_on_stack_cc, regs_cc);
// Compute stack increment
int sp_inc = 0;
if (args_on_stack_cc > args_on_stack) {
sp_inc = (args_on_stack_cc - args_on_stack) * VMRegImpl::stack_slot_size;
sp_inc = align_up(sp_inc, StackAlignmentInBytes);
}
shuffle_value_args(false, receiver_only, extra_stack_offset, sig_bt, sig_cc,
args_passed, args_on_stack, regs,
args_passed_cc, args_on_stack_cc, regs_cc, sp_inc);
return sp_inc;
}

int MacroAssembler::shuffle_value_args_common(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs, // from
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to, // to
int sp_inc, int ret_off) {
void MacroAssembler::shuffle_value_args_common(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs,
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to,
int sp_inc, int ret_off) {
int max_stack = MAX2(args_on_stack + sp_inc/VMRegImpl::stack_slot_size, args_on_stack_to);
RegState* reg_state = init_reg_state(is_packing, sig_cc, regs, args_passed, sp_inc, max_stack);

@@ -236,7 +241,6 @@ int MacroAssembler::shuffle_value_args_common(bool is_packing, bool receiver_onl
}
}
guarantee(done, "Could not resolve circular dependency when shuffling value type arguments");
return sp_inc;
}

bool MacroAssembler::shuffle_value_args_spill(bool is_packing, const GrowableArray<SigEntry>* sig_cc, int sig_cc_index,
@@ -40,11 +40,11 @@
VMRegPair* regs, int num_regs, int sp_inc, int max_stack);

int unpack_value_args_common(Compile* C, bool receiver_only);
int shuffle_value_args_common(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs, // from
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to, // to
int sp_inc, int ret_off);
void shuffle_value_args_common(bool is_packing, bool receiver_only, int extra_stack_offset,
BasicType* sig_bt, const GrowableArray<SigEntry>* sig_cc,
int args_passed, int args_on_stack, VMRegPair* regs,
int args_passed_to, int args_on_stack_to, VMRegPair* regs_to,
int sp_inc, int ret_off);

// };

@@ -911,8 +911,7 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {

void LIR_Assembler::build_frame() {
_masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes(), in_bytes(frame_map()->sp_offset_for_orig_pc()),
compilation()->needs_stack_repair(), method()->has_scalarized_args(),
&_verified_value_entry);
needs_stack_repair(), method()->has_scalarized_args(), &_verified_value_entry);
}


@@ -42,7 +42,6 @@ class C1_MacroAssembler: public MacroAssembler {

void inline_cache_check(Register receiver, Register iCache);
void build_frame(int frame_size_in_bytes, int bang_size_in_bytes, int sp_offset_for_orig_pc = 0, bool needs_stack_repair = false, bool has_scalarized_args = false, Label* verified_value_entry_label = NULL);
void remove_frame(int frame_size_in_bytes, bool needs_stack_repair);

int verified_entry(const CompiledEntrySignature *ces, int frame_size_in_bytes, int bang_size_in_bytes, int sp_offset_for_orig_pc, Label& verified_value_entry_label) {
return scalarized_entry(ces, frame_size_in_bytes, bang_size_in_bytes, sp_offset_for_orig_pc, verified_value_entry_label, false);