Skip to content
119 changes: 119 additions & 0 deletions src/hotspot/cpu/s390/stubGenerator_s390.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1468,11 +1468,120 @@ class StubGenerator: public StubCodeGenerator {
return __ addr_at(start_off);
}

//
// 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:
// Z_ARG1 - destination array address
// Z_ARG2 - byte count (size_t)
// Z_ARG3 - byte value
//
address generate_unsafe_setmemory(address unsafe_byte_fill) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, StubGenStubId::unsafe_setmemory_id);
unsigned int start_off = __ offset();

// bump this on entry, not on exit:
// inc_counter_np(SharedRuntime::_unsafe_set_memory_ctr);

const Register dest = Z_ARG1;
const Register size = Z_ARG2;
const Register byteVal = Z_ARG3;
NearLabel tail, finished;
// fill_to_memory_atomic(unsigned char*, unsigned long, unsigned char)

// Mark remaining code as such which performs Unsafe accesses.
UnsafeMemoryAccessMark umam(this, true, false);

__ z_vlvgb(Z_V0, byteVal, 0);
__ z_vrepb(Z_V0, Z_V0, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also use z_vzero(Vreg) to preload the vector register with all zeroes. Saves an instruction.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not loading 0 here. This is my intention: with z_vlvgb, putting value of byteVal in the first 0th index of Z_V0 and then with z_vrepb replicating the 0th index value (1 byte) to the whole register.

z_vzero will make sense if we are zeroing out the memory but that's not the case always. We do fill some non-zero 1 byte value in most of the case.


__ z_aghi(size, -32);
__ z_brl(tail);

{
NearLabel again;
__ bind(again);
__ z_vst(Z_V0, Address(dest, 0));
__ z_vst(Z_V0, Address(dest, 16));
__ z_aghi(dest, 32);
__ z_aghi(size, -32);
__ z_brnl(again);
}

__ bind(tail);

{
NearLabel dont;
__ testbit(size, 4);
__ z_brz(dont);
__ z_vst(Z_V0, Address(dest, 0));
__ z_aghi(dest, 16);
__ bind(dont);
}

{
NearLabel dont;
__ testbit(size, 3);
__ z_brz(dont);
__ z_vsteg(Z_V0, 0, Z_R0, dest, 0);
__ z_aghi(dest, 8);
__ bind(dont);
}

__ z_tmll(size, 7);
__ z_brc(Assembler::bcondAllZero, finished);

{
NearLabel dont;
__ testbit(size, 2);
__ z_brz(dont);
__ z_vstef(Z_V0, 0, Z_R0, dest, 0);
__ z_aghi(dest, 4);
__ bind(dont);
}

{
NearLabel dont;
__ testbit(size, 1);
__ z_brz(dont);
__ z_vsteh(Z_V0, 0, Z_R0, dest, 0);
__ z_aghi(dest, 2);
__ bind(dont);
}

{
NearLabel dont;
__ testbit(size, 0);
__ z_brz(dont);
__ z_vsteb(Z_V0, 0, Z_R0, dest, 0);
__ bind(dont);
}

__ bind(finished);
__ z_br(Z_R14);

return __ addr_at(start_off);
}

// This is common errorexit stub for UnsafeMemoryAccess.
address generate_unsafecopy_common_error_exit() {
unsigned int start_off = __ offset();
__ z_lghi(Z_RET, 0); // return 0
__ z_br(Z_R14);
return __ addr_at(start_off);
}

void generate_arraycopy_stubs() {

// Note: the disjoint stubs must be generated first, some of
// the conjoint stubs use them.

address ucm_common_error_exit = generate_unsafecopy_common_error_exit();
UnsafeMemoryAccess::set_common_exit_stub_pc(ucm_common_error_exit);

StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::jbyte_disjoint_arraycopy_id);
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_nonoop_copy(StubGenStubId::jshort_disjoint_arraycopy_id);
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_nonoop_copy (StubGenStubId::jint_disjoint_arraycopy_id);
Expand Down Expand Up @@ -1500,6 +1609,12 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_nonoop_copy(StubGenStubId::arrayof_jlong_arraycopy_id);
StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_id);
StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(StubGenStubId::arrayof_oop_arraycopy_uninit_id);

#ifdef COMPILER2
StubRoutines::_unsafe_setmemory =
VM_Version::has_VectorFacility() ? generate_unsafe_setmemory(StubRoutines::_jbyte_fill) : nullptr;

#endif // COMPILER2
}

// Call interface for AES_encryptBlock, AES_decryptBlock stubs.
Expand Down Expand Up @@ -3184,6 +3299,10 @@ class StubGenerator: public StubCodeGenerator {
//----------------------------------------------------------------------
// Entry points that are platform specific.

if (UnsafeMemoryAccess::_table == nullptr) {
UnsafeMemoryAccess::create_table(4); // 4 for setMemory
}

if (UseCRC32Intrinsics) {
StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table;
StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes();
Expand Down