diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 37c8e0ae011..366b1f94898 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -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 diff --git a/src/hotspot/cpu/arm/arm_32.ad b/src/hotspot/cpu/arm/arm_32.ad index 2af7e253a1a..87ffc46e67a 100644 --- a/src/hotspot/cpu/arm/arm_32.ad +++ b/src/hotspot/cpu/arm/arm_32.ad @@ -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; diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 2c0904a6b58..9428c0014e1 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -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) diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index e022dcb4262..d30b6b67945 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -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 diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 3d4abea7529..83898f3086e 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -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(); %} diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 883fb0c6300..b3e5a42926c 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -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(); diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index 666fa2989bd..ecca86ceae4 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -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