From fdcd2092bf5e00dd35230d7aaaaf5f289dfc9c59 Mon Sep 17 00:00:00 2001 From: TheRealMDoerr Date: Wed, 26 Mar 2025 15:11:28 +0100 Subject: [PATCH 1/3] 8352972: PPC64: Intrinsify Unsafe::setMemory --- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index fa356ec13ac16..864e0c1c85439 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -2383,6 +2383,114 @@ class StubGenerator: public StubCodeGenerator { } + // Helper for generate_unsafe_setmemory + // + // Atomically fill an array of memory using 1-, 2-, 4-, or 8-byte chunks and return. + static void do_setmemory_atomic_loop(int elem_size, Register dest, Register size, Register byteVal, + MacroAssembler *_masm) { + + Label L_Loop, L_Tail; // 2x unrolled loop + + // Propagate byte to required width + if (elem_size > 1) __ rldimi(byteVal, byteVal, 8, 64 - 2 * 8); + if (elem_size > 2) __ rldimi(byteVal, byteVal, 16, 64 - 2 * 16); + if (elem_size > 4) __ rldimi(byteVal, byteVal, 32, 64 - 2 * 32); + + __ srwi_(R0, size, exact_log2(2 * elem_size)); // size is a 32 bit value + __ beq(CR0, L_Tail); + __ mtctr(R0); + + __ align(32); // loop alignment + __ bind(L_Loop); + __ store_sized_value(byteVal, 0, dest, elem_size); + __ store_sized_value(byteVal, elem_size, dest, elem_size); + __ addi(dest, dest, 2 * elem_size); + __ bdnz(L_Loop); + + __ bind(L_Tail); + __ andi_(R0, size, elem_size); + __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CR0, Assembler::equal), Assembler::bhintbhBCLRisReturn); + __ store_sized_value(byteVal, 0, dest, elem_size); + __ blr(); + } + + // + // Generate 'unsafe' set memory stub + // Though just as safe as the other stubs, it takes an unscaled + // size_t (# bytes) argument instead of an element count. + // + // Input: + // R3_ARG1 - destination array address + // R4_ARG2 - byte count (size_t) + // R5_ARG3 - byte value + // + address generate_unsafe_setmemory(address unsafe_byte_fill) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id); + address start = __ function_entry(); + + // bump this on entry, not on exit: + // inc_counter_np(SharedRuntime::_unsafe_set_memory_ctr); + + { + Label L_exit, L_fill8Bytes, L_fill4Bytes, L_fillBytes; + + const Register dest = R3_ARG1; + const Register size = R4_ARG2; + const Register byteVal = R5_ARG3; + const Register rScratch1 = R6; + + // fill_to_memory_atomic(unsigned char*, unsigned long, unsigned char) + + // Check for pointer & size alignment + __ orr(rScratch1, dest, size); + + __ andi_(R0, rScratch1, 7); + __ beq(CR0, L_fill8Bytes); + + __ andi_(R0, rScratch1, 3); + __ beq(CR0, L_fill4Bytes); + + __ andi_(R0, rScratch1, 1); + __ bne(CR0, L_fillBytes); + + { + UnsafeMemoryAccessMark umam(this, true, true); + // At this point, we know the lower bit of size is zero and a + // multiple of 2 + do_setmemory_atomic_loop(2, dest, size, byteVal, _masm); + } + + __ align(32); + __ bind(L_fill8Bytes); + { + UnsafeMemoryAccessMark umam(this, true, true); + // At this point, we know the lower 3 bits of size are zero and a + // multiple of 8 + do_setmemory_atomic_loop(8, dest, size, byteVal, _masm); + } + + __ align(32); + __ bind(L_fill4Bytes); + { + UnsafeMemoryAccessMark umam(this, true, true); + // At this point, we know the lower 2 bits of size are zero and a + // multiple of 4 + do_setmemory_atomic_loop(4, dest, size, byteVal, _masm); + } + + __ align(32); + __ bind(L_fillBytes); + { + UnsafeMemoryAccessMark umam(this, true, true); + do_setmemory_atomic_loop(1, dest, size, byteVal, _masm); + } + } + + return start; + } + + // // Generate generic array copy stubs // @@ -3207,6 +3315,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_jshort_fill = generate_fill(StubGenStubId::arrayof_jshort_fill_id); StubRoutines::_arrayof_jint_fill = generate_fill(StubGenStubId::arrayof_jint_fill_id); } + StubRoutines::_unsafe_setmemory = generate_unsafe_setmemory(StubRoutines::_jbyte_fill); #endif } From b47017cc3f518243c021c80076513703d4b90506 Mon Sep 17 00:00:00 2001 From: TheRealMDoerr Date: Wed, 26 Mar 2025 16:10:03 +0100 Subject: [PATCH 2/3] Remove unused Label. --- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index 864e0c1c85439..3d9c30c0a04e9 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -2433,7 +2433,7 @@ class StubGenerator: public StubCodeGenerator { // inc_counter_np(SharedRuntime::_unsafe_set_memory_ctr); { - Label L_exit, L_fill8Bytes, L_fill4Bytes, L_fillBytes; + Label L_fill8Bytes, L_fill4Bytes, L_fillBytes; const Register dest = R3_ARG1; const Register size = R4_ARG2; From d4bc3feb06fcf46591a28512160660ce02230d45 Mon Sep 17 00:00:00 2001 From: TheRealMDoerr Date: Wed, 26 Mar 2025 17:32:38 +0100 Subject: [PATCH 3/3] Simplify usage of UnsafeMemoryAccessMark. --- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 35 +++++++++-------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index 3d9c30c0a04e9..939c3d3094a1a 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -2454,37 +2454,28 @@ class StubGenerator: public StubCodeGenerator { __ andi_(R0, rScratch1, 1); __ bne(CR0, L_fillBytes); - { - UnsafeMemoryAccessMark umam(this, true, true); - // At this point, we know the lower bit of size is zero and a - // multiple of 2 - do_setmemory_atomic_loop(2, dest, size, byteVal, _masm); - } + // Mark remaining code as such which performs Unsafe accesses. + UnsafeMemoryAccessMark umam(this, true, false); + + // At this point, we know the lower bit of size is zero and a + // multiple of 2 + do_setmemory_atomic_loop(2, dest, size, byteVal, _masm); __ align(32); __ bind(L_fill8Bytes); - { - UnsafeMemoryAccessMark umam(this, true, true); - // At this point, we know the lower 3 bits of size are zero and a - // multiple of 8 - do_setmemory_atomic_loop(8, dest, size, byteVal, _masm); - } + // At this point, we know the lower 3 bits of size are zero and a + // multiple of 8 + do_setmemory_atomic_loop(8, dest, size, byteVal, _masm); __ align(32); __ bind(L_fill4Bytes); - { - UnsafeMemoryAccessMark umam(this, true, true); - // At this point, we know the lower 2 bits of size are zero and a - // multiple of 4 - do_setmemory_atomic_loop(4, dest, size, byteVal, _masm); - } + // At this point, we know the lower 2 bits of size are zero and a + // multiple of 4 + do_setmemory_atomic_loop(4, dest, size, byteVal, _masm); __ align(32); __ bind(L_fillBytes); - { - UnsafeMemoryAccessMark umam(this, true, true); - do_setmemory_atomic_loop(1, dest, size, byteVal, _masm); - } + do_setmemory_atomic_loop(1, dest, size, byteVal, _masm); } return start;