Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/hotspot/cpu/s390/registerMap_s390.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026 IBM Corp. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#include "runtime/registerMap.hpp"

address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const {
if (base_reg->is_VectorRegister()) {
// Not all physical slots belonging to a VectorRegister have corresponding
// valid VMReg locations in the RegisterMap.
// (See RegisterSaver::save_live_registers.)
// However, the slots are always saved to the stack in a contiguous region
// of memory so we can calculate the address of the upper slots by
// offsetting from the base address.
assert(base_reg->is_concrete(), "must pass base reg");
address base_location = location(base_reg, nullptr);
if (base_location != nullptr) {
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
return base_location + offset_in_bytes;
} else {
return nullptr;
}
} else {
return location(base_reg->next(slot_idx), nullptr);
}
}
6 changes: 2 additions & 4 deletions src/hotspot/cpu/s390/registerMap_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -36,9 +36,7 @@
// Since there is none, we just return null.
address pd_location(VMReg reg) const {return nullptr;}

address pd_location(VMReg base_reg, int slot_idx) const {
return location(base_reg->next(slot_idx), nullptr);
}
address pd_location(VMReg base_reg, int slot_idx) const;

// No PD state to clear or copy.
void pd_clear() {}
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/cpu/s390/registerSaver_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -58,7 +58,7 @@ class RegisterSaver {

// During deoptimization only the result register need to be restored
// all the other values have already been extracted.
static void restore_result_registers(MacroAssembler* masm);
static void restore_result_registers(MacroAssembler* masm, bool save_vectors);

// Constants and data structures:

Expand Down
27 changes: 10 additions & 17 deletions src/hotspot/cpu/s390/sharedRuntime_s390.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg
break;
}

// Second set_callee_saved is really a waste but we'll keep things as they were for now
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), live_regs[i].vmreg);
map->set_callee_saved(VMRegImpl::stack2reg((offset + half_reg_size) >> 2), live_regs[i].vmreg->next());
}
assert(first != noreg, "Should spill at least one int reg.");
__ z_stmg(first, last, first_offset, Z_SP);
Expand All @@ -416,12 +414,6 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg

map->set_callee_saved(VMRegImpl::stack2reg(offset>>2),
RegisterSaver_LiveVRegs[i].vmreg);
map->set_callee_saved(VMRegImpl::stack2reg((offset + half_reg_size ) >> 2),
RegisterSaver_LiveVRegs[i].vmreg->next());
map->set_callee_saved(VMRegImpl::stack2reg((offset + (half_reg_size * 2)) >> 2),
RegisterSaver_LiveVRegs[i].vmreg->next(2));
map->set_callee_saved(VMRegImpl::stack2reg((offset + (half_reg_size * 3)) >> 2),
RegisterSaver_LiveVRegs[i].vmreg->next(3));
}

assert(offset == frame_size_in_bytes, "consistency check");
Expand Down Expand Up @@ -473,7 +465,6 @@ OopMap* RegisterSaver::generate_oop_map(MacroAssembler* masm, RegisterSet reg_se
for (int i = 0; i < regstosave_num; i++) {
if (live_regs[i].reg_type < RegisterSaver::excluded_reg) {
map->set_callee_saved(VMRegImpl::stack2reg(offset>>2), live_regs[i].vmreg);
map->set_callee_saved(VMRegImpl::stack2reg((offset + half_reg_size)>>2), live_regs[i].vmreg->next());
}
offset += reg_size;
}
Expand Down Expand Up @@ -580,10 +571,12 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, RegisterSet reg


// Pop the current frame and restore the registers that might be holding a result.
void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
void RegisterSaver::restore_result_registers(MacroAssembler* masm, bool save_vectors) {
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
const int register_save_offset = live_reg_frame_size(all_registers) - live_reg_save_size(all_registers);
const int vecregstosave_num = save_vectors ? calculate_vregstosave_num() : 0;
const int vreg_save_size = vecregstosave_num * v_reg_size;
const int register_save_offset = live_reg_frame_size(all_registers, save_vectors) - (live_reg_save_size(all_registers) + vreg_save_size);

// Restore all result registers (ints and floats).
int offset = register_save_offset;
Expand All @@ -609,7 +602,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
ShouldNotReachHere();
}
}
assert(offset == live_reg_frame_size(all_registers), "consistency check");
assert(offset == live_reg_frame_size(all_registers, save_vectors) - (save_vectors ? vreg_save_size : 0) , "consistency check");
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -2558,7 +2551,7 @@ void SharedRuntime::generate_deopt_blob() {
// nmethod that was valid just before the nmethod was deoptimized.
// save R14 into the deoptee frame. the `fetch_unroll_info'
// procedure called below will read it from there.
map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers);
map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R14, /* save_vectors= */ SuperwordUseVX);

// note the entry point.
__ load_const_optimized(exec_mode_reg, Deoptimization::Unpack_deopt);
Expand All @@ -2574,7 +2567,7 @@ void SharedRuntime::generate_deopt_blob() {
int reexecute_offset = __ offset() - start_off;

// No need to update map as each call to save_live_registers will produce identical oopmap
(void) RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers);
(void) RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R14, /* save_vectors= */ SuperwordUseVX);

__ load_const_optimized(exec_mode_reg, Deoptimization::Unpack_reexecute);
__ z_bru(exec_mode_initialized);
Expand Down Expand Up @@ -2612,7 +2605,7 @@ void SharedRuntime::generate_deopt_blob() {
__ z_lg(Z_R1_scratch, Address(Z_thread, JavaThread::exception_pc_offset()));

// Save everything in sight.
(void) RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R1_scratch);
(void) RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers, Z_R1_scratch, /* save_vectors= */ SuperwordUseVX);

// Now it is safe to overwrite any register

Expand Down Expand Up @@ -2662,7 +2655,7 @@ void SharedRuntime::generate_deopt_blob() {
__ z_lgr(unroll_block_reg, Z_RET);
// restore the return registers that have been saved
// (among other registers) by save_live_registers(...).
RegisterSaver::restore_result_registers(masm);
RegisterSaver::restore_result_registers(masm, /* save_vectors= */ SuperwordUseVX);

// reload the exec mode from the UnrollBlock (it might have changed)
__ z_llgf(exec_mode_reg, Address(unroll_block_reg, Deoptimization::UnrollBlock::unpack_kind_offset()));
Expand Down Expand Up @@ -2738,7 +2731,7 @@ void SharedRuntime::generate_deopt_blob() {
// Make sure all code is generated
masm->flush();

_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers)/wordSize);
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers, SuperwordUseVX)/wordSize);
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
}

Expand Down
7 changes: 4 additions & 3 deletions src/hotspot/cpu/s390/vm_version_s390.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand All @@ -24,8 +24,9 @@
*/

#include "asm/assembler.inline.hpp"
#include "compiler/disassembler.hpp"
#include "code/compiledIC.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "compiler/disassembler.hpp"
#include "jvm.h"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
Expand Down Expand Up @@ -105,7 +106,7 @@ void VM_Version::initialize() {
int model_ix = get_model_index();

if ( model_ix >= 7 ) {
if (FLAG_IS_DEFAULT(SuperwordUseVX)) {
if (FLAG_IS_DEFAULT(SuperwordUseVX) && CompilerConfig::is_c2_enabled()) {
FLAG_SET_ERGO(SuperwordUseVX, true);
}
if (model_ix > 7 && FLAG_IS_DEFAULT(UseSFPV) && SuperwordUseVX) {
Expand Down
9 changes: 7 additions & 2 deletions src/hotspot/cpu/s390/vmreg_s390.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -59,7 +59,12 @@ inline VectorRegister as_VectorRegister() {

inline bool is_concrete() {
assert(is_reg(), "must be");
return is_even(value());
if (is_Register() || is_FloatRegister()) return is_even(value());
if (is_VectorRegister()) {
int base = value() - ConcreteRegisterImpl::max_fpr;
return (base & 3) == 0;
}
return true;
}

#endif // CPU_S390_VMREG_S390_HPP