Skip to content
Permalink
Browse files
8241764: [lworld] TestC2CCalls fails with SIGSEGV in frame::sender_fo…
…r_compiled_frame
  • Loading branch information
TobiHartmann committed Apr 3, 2020
1 parent d544758 commit a264ae9a75672223559f483270a5333b24195a22
@@ -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);

0 comments on commit a264ae9

Please sign in to comment.