8388170: [s390x] compiler/inlining/LateInlineQueueDrainTest.java#id0 fail due to invalid ret_addr_offset

Reviewed-by: amitkumar, aph
This commit is contained in:
Vladimir Petko 2026-07-24 06:03:49 +00:00 committed by Amit Kumar
parent ead9921903
commit bb05fd9f72
7 changed files with 76 additions and 46 deletions

View File

@ -1662,19 +1662,19 @@ bool needs_acquiring_load_exclusive(const Node *n)
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset()
int MachCallStaticJavaNode::ret_addr_offset() const
{
// call should be a simple bl
int off = 4;
return off;
}
int MachCallDynamicJavaNode::ret_addr_offset()
int MachCallDynamicJavaNode::ret_addr_offset() const
{
return 16; // movz, movk, movk, bl
}
int MachCallRuntimeNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() const {
// for generated stubs the call will be
// bl(addr)
// or with far branches

View File

@ -430,18 +430,18 @@ OptoRegPair c2::return_value(int ideal_reg) {
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
int MachCallStaticJavaNode::ret_addr_offset() const {
bool far = (_method == nullptr) ? maybe_far_call(this) : !cache_reachable();
return (far ? 3 : 1) * NativeInstruction::instruction_size;
}
int MachCallDynamicJavaNode::ret_addr_offset() {
int MachCallDynamicJavaNode::ret_addr_offset() const {
bool far = !cache_reachable();
// mov_oop is always 2 words
return (2 + (far ? 3 : 1)) * NativeInstruction::instruction_size;
}
int MachCallRuntimeNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() const {
// bl or movw; movt; blx
bool far = maybe_far_call(this);
return (far ? 3 : 1) * NativeInstruction::instruction_size;

View File

@ -1171,16 +1171,16 @@ bool followed_by_acquire(const Node *load) {
// PPC port: Removed use of lazy constant construct.
int MachCallStaticJavaNode::ret_addr_offset() {
int MachCallStaticJavaNode::ret_addr_offset() const {
// It's only a single branch-and-link instruction.
return 4;
}
int MachCallDynamicJavaNode::ret_addr_offset() {
int MachCallDynamicJavaNode::ret_addr_offset() const {
return 12;
}
int MachCallRuntimeNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() const {
if (rule() == CallRuntimeDirect_rule) {
// CallRuntimeDirectNode uses call_c.
#if defined(ABI_ELFv2)

View File

@ -1208,17 +1208,17 @@ bool needs_acquiring_load_reserved(const Node *n)
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset()
int MachCallStaticJavaNode::ret_addr_offset() const
{
return 3 * NativeInstruction::instruction_size; // auipc + ld + jalr
}
int MachCallDynamicJavaNode::ret_addr_offset()
int MachCallDynamicJavaNode::ret_addr_offset() const
{
return NativeMovConstReg::movptr2_instruction_size + (3 * NativeInstruction::instruction_size); // movptr2, auipc + ld + jal
}
int MachCallRuntimeNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() const {
// For address inside the code cache the call will be:
// auipc + jalr
// For real runtime callouts it will be 8 instructions

View File

@ -886,29 +886,59 @@ int MachNode::compute_padding(int current_offset) const {
return 0;
}
int MachCallStaticJavaNode::ret_addr_offset() {
int MachCallStaticJavaNode::ret_addr_offset() const {
if (_method) {
return 8;
return MacroAssembler::call_far_pcrelative_size();
} else {
return MacroAssembler::call_far_patchable_ret_addr_offset();
}
}
int MachCallDynamicJavaNode::ret_addr_offset() {
int MachCallDynamicJavaNode::ret_addr_offset() const {
// Consider size of receiver type profiling (C2 tiers).
int profile_receiver_type_size = 0;
int vtable_index = this->_vtable_index;
if (vtable_index == -4) {
return 14 + profile_receiver_type_size;
return MacroAssembler::load_const_from_toc_size()
+ MacroAssembler::call_far_pcrelative_size();
} else {
assert(!UseInlineCaches, "expect vtable calls only if not using ICs");
return 36 + profile_receiver_type_size;
// This should return the size of instructions in vtable dispatch
// branch of z_enc_java_dynamic_call
int offset = 0;
// __ load_klass(Z_method, Z_R2);
if (UseCompactObjectHeaders) {
// load_narrow_klass_compact (z_lg z_srlg)
offset += 6 // z_lg
+ 6; // z_srlg;
} else {
offset += 6; // z_llgf
}
offset += MacroAssembler::instr_size_for_decode_klass_not_null();
// check if displacement is valid, as it will generate different
// instructions:
int entry_offset = in_bytes(Klass::vtable_start_offset()) +
vtable_index * vtableEntry::size_in_bytes();
int v_off = entry_offset + in_bytes(vtableEntry::method_offset());
if (!Displacement::is_validDisp(v_off)) {
offset += MacroAssembler::load_const_size(); // emits iihf + iilf
}
// both generate z_lg
offset += 6; // z_lg (z_method, v_off | Address(Z_method, Z_R1_scratch))
// common footer
offset += 6; // z_lg(Z_R1_scratch, Method::from_compiled_offset())
offset += 2; // z_basr
return offset;
}
}
int MachCallRuntimeNode::ret_addr_offset() {
return 12 + MacroAssembler::call_far_patchable_ret_addr_offset();
int MachCallRuntimeNode::ret_addr_offset() const {
return 6 // get_PC() (LARL)
+ 6 // save_return_pc() (STG)
+ MacroAssembler::call_far_patchable_ret_addr_offset();
}
// Compute padding required for nodes which need alignment
@ -994,7 +1024,6 @@ static inline void z_assert_aligned(C2_MacroAssembler *masm, int disp, Register
int emit_call_reloc(C2_MacroAssembler *masm, intptr_t entry_point, relocInfo::relocType rtype,
PhaseRegAlloc* ra_, bool is_native_call = false) {
__ set_inst_mark(); // Used in z_enc_java_static_call() and emit_java_to_interp().
address old_mark = __ inst_mark();
unsigned int start_off = __ offset();
if (is_native_call) {
@ -1024,7 +1053,6 @@ int emit_call_reloc(C2_MacroAssembler *masm, intptr_t entry_point, relocInfo::re
static int emit_call_reloc(C2_MacroAssembler *masm, intptr_t entry_point, RelocationHolder const& rspec) {
__ set_inst_mark(); // Used in z_enc_java_static_call() and emit_java_to_interp().
address old_mark = __ inst_mark();
unsigned int start_off = __ offset();
relocInfo::relocType rtype = rspec.type();
@ -2344,8 +2372,7 @@ encode %{
// callee doesn't.
unsigned int start_off = __ offset();
// Compute size of "larl + stg + call_c_opt".
const int size_of_code = 6 + 6 + MacroAssembler::call_far_patchable_size();
__ get_PC(Z_R14, size_of_code);
__ get_PC(Z_R14, ret_addr_offset());
__ save_return_pc();
assert(__ offset() - start_off == 12, "bad prelude len: %d", __ offset() - start_off);
@ -2356,30 +2383,28 @@ encode %{
return;
}
#ifdef ASSERT
// Plausibility check for size_of_code assumptions.
unsigned int actual_ret_off = __ offset();
assert(start_off + size_of_code == actual_ret_off, "wrong return_pc");
#endif
assert(__ offset() - start_off == (uint)ret_addr_offset(),
"z_enc_java_to_runtime_call return offset mismatch: emitted %d bytes, ret_addr_offset()=%d",
__ offset() - start_off, ret_addr_offset());
__ post_call_nop();
%}
enc_class z_enc_java_static_call(method meth) %{
unsigned int start_off = __ offset();
// Call to fixup routine. Fixup routine uses ScopeDesc info to determine
// whom we intended to call.
int ret_offset = 0;
if (!_method) {
ret_offset = emit_call_reloc(masm, $meth$$method,
relocInfo::runtime_call_w_cp_type, ra_);
emit_call_reloc(masm, $meth$$method,
relocInfo::runtime_call_w_cp_type, ra_);
} else {
int method_index = resolved_method_index(masm);
if (_optimized_virtual) {
ret_offset = emit_call_reloc(masm, $meth$$method,
opt_virtual_call_Relocation::spec(method_index));
emit_call_reloc(masm, $meth$$method,
opt_virtual_call_Relocation::spec(method_index));
} else {
ret_offset = emit_call_reloc(masm, $meth$$method,
static_call_Relocation::spec(method_index));
emit_call_reloc(masm, $meth$$method,
static_call_Relocation::spec(method_index));
}
}
assert(__ inst_mark() != nullptr, "emit_call_reloc must set_inst_mark()");
@ -2394,6 +2419,9 @@ encode %{
}
__ clear_inst_mark();
assert(__ offset() - start_off == (uint)ret_addr_offset(),
"z_enc_java_static_call return offset mismatch: emitted %d bytes, ret_addr_offset()=%d",
__ offset() - start_off, ret_addr_offset());
__ post_call_nop();
%}
@ -2418,9 +2446,8 @@ encode %{
// to determine who we intended to call.
int method_index = resolved_method_index(masm);
__ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr, method_index));
unsigned int ret_off = __ offset();
assert(__ offset() - start_off == 6, "bad prelude len: %d", __ offset() - start_off);
ret_off += emit_call_reloc(masm, $meth$$method, relocInfo::none, ra_);
emit_call_reloc(masm, $meth$$method, relocInfo::none, ra_);
__ clear_inst_mark();
assert(_method, "lazy_constant may be wrong when _method==null");
} else {
@ -2449,8 +2476,11 @@ encode %{
__ z_lg(Z_R1_scratch, Address(Z_method, Method::from_compiled_offset()));
// Call target. Either compiled code or C2I adapter.
__ z_basr(Z_R14, Z_R1_scratch);
unsigned int ret_off = __ offset();
}
assert(__ offset() - start_off == (uint)ret_addr_offset(),
"z_enc_java_dynamic_call return offset mismatch: emitted %d bytes, ret_addr_offset()=%d",
__ offset() - start_off, ret_addr_offset());
__ post_call_nop();
%}

View File

@ -1634,21 +1634,21 @@ static int clear_avx_size() {
// !!!!! Special hack to get all types of calls to specify the byte offset
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset()
int MachCallStaticJavaNode::ret_addr_offset() const
{
int offset = 5; // 5 bytes from start of call to where return address points
offset += clear_avx_size();
return offset;
}
int MachCallDynamicJavaNode::ret_addr_offset()
int MachCallDynamicJavaNode::ret_addr_offset() const
{
int offset = 15; // 15 bytes from start of call to where return address points
offset += clear_avx_size();
return offset;
}
int MachCallRuntimeNode::ret_addr_offset() {
int MachCallRuntimeNode::ret_addr_offset() const {
int offset = 13; // movq r10,#addr; callq (r10)
if (this->ideal_Opcode() != Op_CallLeafVector) {
offset += clear_avx_size();

View File

@ -937,7 +937,7 @@ public:
virtual bool pinned() const { return false; }
virtual const Type* Value(PhaseGVN* phase) const;
virtual const RegMask &in_RegMask(uint) const;
virtual int ret_addr_offset() { return 0; }
virtual int ret_addr_offset() const { return 0; }
NOT_LP64(bool return_value_is_used() const;)
@ -998,7 +998,7 @@ public:
// If this is an uncommon trap, return the request code, else zero.
int uncommon_trap_request() const;
virtual int ret_addr_offset();
virtual int ret_addr_offset() const;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
void dump_trap_args(outputStream *st) const;
@ -1014,7 +1014,7 @@ public:
init_class_id(Class_MachCallDynamicJava);
DEBUG_ONLY(_vtable_index = -99); // throw an assert if uninitialized
}
virtual int ret_addr_offset();
virtual int ret_addr_offset() const;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
#endif
@ -1032,7 +1032,7 @@ public:
MachCallRuntimeNode() : MachCallNode() {
init_class_id(Class_MachCallRuntime);
}
virtual int ret_addr_offset();
virtual int ret_addr_offset() const;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
#endif