Skip to content

Commit bf5901b

Browse files
committed
8380565: PPC64: deoptimization stub should save vector registers
8381315: compiler/vectorapi/TestVectorReallocation.java fails with -XX:UseAVX=1 after JDK-8380565 Reviewed-by: rrich Backport-of: 7f4d121
1 parent 623ab91 commit bf5901b

File tree

5 files changed

+483
-15
lines changed

5 files changed

+483
-15
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2026 SAP SE. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
#include "runtime/registerMap.hpp"
26+
27+
address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const {
28+
if (base_reg->is_VectorRegister()) {
29+
// Not all physical slots belonging to a VectorRegister have corresponding
30+
// valid VMReg locations in the RegisterMap.
31+
// (See RegisterSaver::push_frame_reg_args_and_save_live_registers.)
32+
// However, the slots are always saved to the stack in a contiguous region
33+
// of memory so we can calculate the address of the upper slots by
34+
// offsetting from the base address.
35+
assert(base_reg->is_concrete(), "must pass base reg");
36+
address base_location = location(base_reg, nullptr);
37+
if (base_location != nullptr) {
38+
intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size;
39+
return base_location + offset_in_bytes;
40+
} else {
41+
return nullptr;
42+
}
43+
} else {
44+
return location(base_reg->next(slot_idx), nullptr);
45+
}
46+
}

src/hotspot/cpu/ppc/registerMap_ppc.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
2+
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,7 @@
3535
// Since there is none, we just return null.
3636
address pd_location(VMReg reg) const { return nullptr; }
3737

38-
address pd_location(VMReg base_reg, int slot_idx) const {
39-
return location(base_reg->next(slot_idx), nullptr);
40-
}
38+
address pd_location(VMReg base_reg, int slot_idx) const;
4139

4240
// no PD state to clear or copy:
4341
void pd_clear() {}

src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class RegisterSaver {
103103

104104
// During deoptimization only the result registers need to be restored
105105
// all the other values have already been extracted.
106-
static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes);
106+
static void restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors);
107107

108108
// Constants and data structures:
109109

@@ -355,7 +355,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
355355
}
356356

357357
// Note that generate_oop_map in the following loop is only used for the
358-
// polling_page_vectors_safepoint_handler_blob.
358+
// polling_page_vectors_safepoint_handler_blob and the deopt_blob.
359359
// The order in which the vector contents are stored depends on Endianess and
360360
// the utilized instructions (PowerArchitecturePPC64).
361361
assert(is_aligned(offset, StackAlignmentInBytes), "should be");
@@ -367,6 +367,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
367367

368368
__ stxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP);
369369
// Note: The contents were read in the same order (see loadV16_Power9 node in ppc.ad).
370+
// RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
370371
if (generate_oop_map) {
371372
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2),
372373
RegisterSaver_LiveVecRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg);
@@ -386,6 +387,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
386387
__ stxvd2x(as_VectorRegister(reg_num)->to_vsr(), R31, R1_SP);
387388
}
388389
// Note: The contents were read in the same order (see loadV16_Power8 / loadV16_Power9 node in ppc.ad).
390+
// RegisterMap::pd_location only uses the first VMReg for each VectorRegister.
389391
if (generate_oop_map) {
390392
VMReg vsr = RegisterSaver_LiveVecRegs[i].vmreg;
391393
map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), vsr);
@@ -572,10 +574,14 @@ void RegisterSaver::restore_argument_registers_and_pop_frame(MacroAssembler*masm
572574
}
573575

574576
// Restore the registers that might be holding a result.
575-
void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes) {
577+
void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes, bool save_vectors) {
576578
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
577579
sizeof(RegisterSaver::LiveRegType);
578-
const int register_save_size = regstosave_num * reg_size; // VS registers not relevant here.
580+
const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) /
581+
sizeof(RegisterSaver::LiveRegType))
582+
: 0;
583+
const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size;
584+
579585
const int register_save_offset = frame_size_in_bytes - register_save_size;
580586

581587
// restore all result registers (ints and floats)
@@ -604,7 +610,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_siz
604610
offset += reg_size;
605611
}
606612

607-
assert(offset == frame_size_in_bytes, "consistency check");
613+
assert(offset == frame_size_in_bytes - (save_vectors ? vecregstosave_num * vec_reg_size : 0), "consistency check");
608614
}
609615

610616
// Is vector's size (in bytes) bigger than a size saved by default?
@@ -2993,7 +2999,8 @@ void SharedRuntime::generate_deopt_blob() {
29932999
&first_frame_size_in_bytes,
29943000
/*generate_oop_map=*/ true,
29953001
return_pc_adjustment_no_exception,
2996-
RegisterSaver::return_pc_is_lr);
3002+
RegisterSaver::return_pc_is_lr,
3003+
/*save_vectors*/ SuperwordUseVSX);
29973004
assert(map != nullptr, "OopMap must have been created");
29983005

29993006
__ li(exec_mode_reg, Deoptimization::Unpack_deopt);
@@ -3028,7 +3035,8 @@ void SharedRuntime::generate_deopt_blob() {
30283035
&first_frame_size_in_bytes,
30293036
/*generate_oop_map=*/ false,
30303037
/*return_pc_adjustment_exception=*/ 0,
3031-
RegisterSaver::return_pc_is_pre_saved);
3038+
RegisterSaver::return_pc_is_pre_saved,
3039+
/*save_vectors*/ SuperwordUseVSX);
30323040

30333041
// Deopt during an exception. Save exec mode for unpack_frames.
30343042
__ li(exec_mode_reg, Deoptimization::Unpack_exception);
@@ -3046,7 +3054,8 @@ void SharedRuntime::generate_deopt_blob() {
30463054
&first_frame_size_in_bytes,
30473055
/*generate_oop_map=*/ false,
30483056
/*return_pc_adjustment_reexecute=*/ 0,
3049-
RegisterSaver::return_pc_is_pre_saved);
3057+
RegisterSaver::return_pc_is_pre_saved,
3058+
/*save_vectors*/ SuperwordUseVSX);
30503059
__ li(exec_mode_reg, Deoptimization::Unpack_reexecute);
30513060
#endif
30523061

@@ -3072,7 +3081,7 @@ void SharedRuntime::generate_deopt_blob() {
30723081

30733082
// Restore only the result registers that have been saved
30743083
// by save_volatile_registers(...).
3075-
RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes);
3084+
RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes, /*save_vectors*/ SuperwordUseVSX);
30763085

30773086
// reload the exec mode from the UnrollBlock (it might have changed)
30783087
__ lwz(exec_mode_reg, in_bytes(Deoptimization::UnrollBlock::unpack_kind_offset()), unroll_block_reg);

src/hotspot/cpu/ppc/vm_version_ppc.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "asm/assembler.inline.hpp"
2727
#include "asm/macroAssembler.inline.hpp"
28+
#include "compiler/compilerDefinitions.inline.hpp"
2829
#include "compiler/disassembler.hpp"
2930
#include "jvm.h"
3031
#include "memory/resourceArea.hpp"
@@ -103,7 +104,7 @@ void VM_Version::initialize() {
103104

104105
if (PowerArchitecturePPC64 >= 9) {
105106
// Performance is good since Power9.
106-
if (FLAG_IS_DEFAULT(SuperwordUseVSX)) {
107+
if (FLAG_IS_DEFAULT(SuperwordUseVSX) && CompilerConfig::is_c2_enabled()) {
107108
FLAG_SET_ERGO(SuperwordUseVSX, true);
108109
}
109110
}

0 commit comments

Comments
 (0)