diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp index 396c72bd725..8944aabb124 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp @@ -213,11 +213,8 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, // conventions for inline types. Save all argument registers before calling // into the runtime. - // TODO 8366717 This came with 8284161: Implementation of Virtual Threads (Preview) later in May 2022 - // Check if it's sufficient - //__ push_call_clobbered_registers(); - assert_different_registers(rscratch1, pre_val); // push_CPU_state trashes rscratch1 - __ push_CPU_state(true); + assert_different_registers(rscratch1, pre_val); // push_call_clobbered_registers trashes rscratch1 + __ push_call_clobbered_registers(); // Calling the runtime using the regular call_VM_leaf mechanism generates // code (generated by InterpreterMacroAssember::call_VM_leaf_base) @@ -238,7 +235,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); } - __ pop_CPU_state(true); + __ pop_call_clobbered_registers(); __ bind(done); diff --git a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp index 28810638379..a7778f8fcfe 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp @@ -114,8 +114,7 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS // flatten object address if needed if (!precise || (dst.index() == noreg && dst.offset() == 0)) { if (tmp3 != noreg) { - // TODO 8366717 This change is from before the 'tmp3' arg was added to mainline, check if it's still needed. Same on x64. Also, this should be a __ lea - // Called by MacroAssembler::pack_inline_helper. We cannot corrupt the dst.base() register + // When tmp3 is given, we cannot corrupt the dst.base() register (from MacroAssembler::pack_inline_helper or do_oop_store) __ mov(tmp3, dst.base()); store_check(masm, tmp3, dst); } else { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index bfd62dac8b0..cbc765b5aec 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -7162,11 +7162,18 @@ bool MacroAssembler::unpack_inline_helper(const GrowableArray* sig, in Label L_null, L_notNull; // Don't use r14 as tmp because it's used for spilling (see MacroAssembler::spill_reg_for) - // TODO 8366717 We need to make sure that r14 (and potentially other long-life regs) are kept live in slowpath runtime calls in GC barriers Register tmp1 = r10; Register tmp2 = r11; + +#ifndef ASSERT + RegSet clobbered_gp_regs = MacroAssembler::call_clobbered_gp_registers(); + assert(clobbered_gp_regs.contains(tmp1), "tmp1 must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(tmp2), "tmp2 must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(r14), "r14 must be saved explicitly if it's not a clobber"); +#endif + Register fromReg = noreg; - ScalarizedInlineArgsStream stream(sig, sig_index, to, to_count, to_index, -1); + ScalarizedInlineArgsStream stream(sig, sig_index, to, to_count, to_index, true); bool done = true; bool mark_done = true; VMReg toReg; @@ -7267,7 +7274,6 @@ bool MacroAssembler::unpack_inline_helper(const GrowableArray* sig, in } } - // TODO 8366717 This is probably okay but looks fishy because stream is reset in the "Set null marker to zero" case just above. Same on x64. sig_index = stream.sig_index(); to_index = stream.regs_index(); diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index c35d2a66a02..76799186c7a 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -208,7 +208,6 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // will allow deoptimization at this safepoint to find all possible // debug-info recordings, as well as let GC find all oops. - OopMapSet *oop_maps = new OopMapSet(); OopMap* oop_map = new OopMap(frame_size_in_slots, 0); for (int i = 0; i < Register::number_of_registers; i++) { @@ -620,18 +619,25 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ bind(skip_fixup); - // TODO 8366717 Is the comment about r13 correct? Isn't that r19_sender_sp? // Name some registers to be used in the following code. We can use // anything except r0-r7 which are arguments in the Java calling - // convention, rmethod (r12), and r13 which holds the outgoing sender + // convention, rmethod (r12), and r19 which holds the outgoing sender // SP for the interpreter. - // TODO 8366717 We need to make sure that buf_array, buf_oop (and potentially other long-life regs) are kept live in slowpath runtime calls in GC barriers Register buf_array = r10; // Array of buffered inline types Register buf_oop = r11; // Buffered inline type oop Register tmp1 = r15; Register tmp2 = r16; Register tmp3 = r17; +#ifndef ASSERT + RegSet clobbered_gp_regs = MacroAssembler::call_clobbered_gp_registers(); + assert(clobbered_gp_regs.contains(buf_array), "buf_array must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(buf_oop), "buf_oop must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(tmp1), "tmp1 must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(tmp2), "tmp2 must be saved explicitly if it's not a clobber"); + assert(clobbered_gp_regs.contains(tmp3), "tmp3 must be saved explicitly if it's not a clobber"); +#endif + if (InlineTypePassFieldsAsArgs) { // Is there an inline type argument? bool has_inline_argument = false; @@ -642,7 +648,6 @@ static void gen_c2i_adapter(MacroAssembler *masm, // There is at least an inline type argument: we're coming from // compiled code so we have no buffers to back the inline types // Allocate the buffers here with a runtime call. - // TODO 8366717 Do we need to save vectors here? They could be used as arg registers, right? Same on x64. RegisterSaver reg_save(true /* save_vectors */); OopMap* map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 2c40cc38245..c385186855d 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -236,24 +236,8 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, __ jcc(Assembler::equal, done); generate_pre_barrier_slow_path(masm, obj, pre_val, thread, tmp, done); - if (Arguments::is_valhalla_enabled() && InlineTypePassFieldsAsArgs) { - // Barriers might be emitted when converting between (scalarized) calling conventions for inline - // types. Save all argument registers before calling into the runtime. - // TODO 8366717: use push_set() (see JDK-8283327 push/pop_call_clobbered_registers & aarch64 ) - __ pusha(); - __ subptr(rsp, 64); - __ movdbl(Address(rsp, 0), j_farg0); - __ movdbl(Address(rsp, 8), j_farg1); - __ movdbl(Address(rsp, 16), j_farg2); - __ movdbl(Address(rsp, 24), j_farg3); - __ movdbl(Address(rsp, 32), j_farg4); - __ movdbl(Address(rsp, 40), j_farg5); - __ movdbl(Address(rsp, 48), j_farg6); - __ movdbl(Address(rsp, 56), j_farg7); - } else { - // Determine and save the live input values - __ push_call_clobbered_registers(); - } + // Determine and save the live input values + __ push_call_clobbered_registers(); // Calling the runtime using the regular call_VM_leaf mechanism generates // code (generated by InterpreterMacroAssember::call_VM_leaf_base) @@ -280,21 +264,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); } - if (Arguments::is_valhalla_enabled() && InlineTypePassFieldsAsArgs) { - // Restore registers - __ movdbl(j_farg0, Address(rsp, 0)); - __ movdbl(j_farg1, Address(rsp, 8)); - __ movdbl(j_farg2, Address(rsp, 16)); - __ movdbl(j_farg3, Address(rsp, 24)); - __ movdbl(j_farg4, Address(rsp, 32)); - __ movdbl(j_farg5, Address(rsp, 40)); - __ movdbl(j_farg6, Address(rsp, 48)); - __ movdbl(j_farg7, Address(rsp, 56)); - __ addptr(rsp, 64); - __ popa(); - } else { - __ pop_call_clobbered_registers(); - } + __ pop_call_clobbered_registers(); __ bind(done); } diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index ff83cbb7f27..9e26f2892f4 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -181,7 +181,7 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS // flatten object address if needed if (!precise || (dst.index() == noreg && dst.disp() == 0)) { if (tmp3 != noreg) { - // Called by MacroAssembler::pack_inline_helper. We cannot corrupt the dst.base() register + // When tmp3 is given, we cannot corrupt the dst.base() register (from MacroAssembler::pack_inline_helper or do_oop_store) __ movptr(tmp3, dst.base()); store_check(masm, tmp3, dst); } else { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 9e077cb63ba..e6b6d593480 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -6096,7 +6096,7 @@ bool MacroAssembler::unpack_inline_helper(const GrowableArray* sig, in Register tmp1 = r10; Register tmp2 = r13; Register fromReg = noreg; - ScalarizedInlineArgsStream stream(sig, sig_index, to, to_count, to_index, -1); + ScalarizedInlineArgsStream stream(sig, sig_index, to, to_count, to_index, true); bool done = true; bool mark_done = true; VMReg toReg; diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 9696993fc6a..d6fa31eb4a6 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -918,7 +918,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, // There is at least an inline type argument: we're coming from // compiled code so we have no buffers to back the inline types. // Allocate the buffers here with a runtime call. - OopMap* map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_vectors*/ false); + OopMap* map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, /*save_wide_vectors*/ false); frame_complete = __ offset(); diff --git a/src/hotspot/share/runtime/signature_cc.hpp b/src/hotspot/share/runtime/signature_cc.hpp index afe61d7d67e..1798bc79659 100644 --- a/src/hotspot/share/runtime/signature_cc.hpp +++ b/src/hotspot/share/runtime/signature_cc.hpp @@ -35,12 +35,12 @@ class ScalarizedInlineArgsStream : public StackObj { int _regs_count; int _regs_idx; int _depth; - int _step; + const int _step; DEBUG_ONLY(bool _finished); public: - ScalarizedInlineArgsStream(const GrowableArray* sig, int sig_idx, VMRegPair* regs, int regs_count, int regs_idx, int step = 1) - : _sig(sig), _sig_idx(sig_idx), _regs(regs), _regs_count(regs_count), _regs_idx(regs_idx), _step(step) { + ScalarizedInlineArgsStream(const GrowableArray* sig, int sig_idx, VMRegPair* regs, int regs_count, int regs_idx, bool reverse = false) + : _sig(sig), _sig_idx(sig_idx), _regs(regs), _regs_count(regs_count), _regs_idx(regs_idx), _step(reverse ? -1 : 1) { reset(sig_idx, regs_idx); }