8210497: [PPC64] Vector registers not saved across safepoint

Reviewed-by: goetz, lucy
This commit is contained in:
Martin Doerr 2018-09-12 12:54:16 +02:00
parent 0820376744
commit 63abf144aa
5 changed files with 140 additions and 81 deletions

@ -908,6 +908,7 @@ reg_class dbl_reg(
// ----------------------------
reg_class vs_reg(
// Attention: Only these ones are saved & restored at safepoint by RegisterSaver.
VSR32,
VSR33,
VSR34,
@ -928,18 +929,7 @@ reg_class vs_reg(
VSR49,
VSR50,
VSR51
// VSR52, // nv!
// VSR53, // nv!
// VSR54, // nv!
// VSR55, // nv!
// VSR56, // nv!
// VSR57, // nv!
// VSR58, // nv!
// VSR59, // nv!
// VSR60, // nv!
// VSR61, // nv!
// VSR62, // nv!
// VSR63 // nv!
// VSR52-VSR63 // nv!
);
%}

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -26,11 +26,6 @@
#include "precompiled.hpp"
#include "register_ppc.hpp"
const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * 2;
const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::max_gpr +
FloatRegisterImpl::number_of_registers * 2;
const int ConcreteRegisterImpl::max_cnd = ConcreteRegisterImpl::max_fpr +
ConditionRegisterImpl::number_of_registers;
const char* RegisterImpl::name() const {
const char* names[number_of_registers] = {

@ -1,6 +1,6 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -515,6 +515,7 @@ class VectorSRegisterImpl: public AbstractRegisterImpl {
// accessors
int encoding() const { assert(is_valid(), "invalid register"); return value(); }
inline VMReg as_VMReg();
// testers
bool is_valid() const { return 0 <= value() && value() < number_of_registers; }
@ -668,21 +669,16 @@ const int PPC_ARGS_IN_REGS_NUM = 8;
class ConcreteRegisterImpl : public AbstractRegisterImpl {
public:
enum {
max_gpr = RegisterImpl::number_of_registers * 2,
max_fpr = max_gpr + FloatRegisterImpl::number_of_registers * 2,
max_vsr = max_fpr + VectorSRegisterImpl::number_of_registers,
max_cnd = max_vsr + ConditionRegisterImpl::number_of_registers,
max_spr = max_cnd + SpecialRegisterImpl::number_of_registers,
// This number must be large enough to cover REG_COUNT (defined by c2) registers.
// There is no requirement that any ordering here matches any ordering c2 gives
// it's optoregs.
number_of_registers =
( RegisterImpl::number_of_registers +
FloatRegisterImpl::number_of_registers )
* 2 // register halves
+ ConditionRegisterImpl::number_of_registers // condition code registers
+ SpecialRegisterImpl::number_of_registers // special registers
+ VectorSRegisterImpl::number_of_registers // VSX registers
number_of_registers = max_spr
};
static const int max_gpr;
static const int max_fpr;
static const int max_cnd;
};
// Common register declarations used in assembler code.

@ -75,10 +75,12 @@ class RegisterSaver {
int* out_frame_size_in_bytes,
bool generate_oop_map,
int return_pc_adjustment,
ReturnPCLocation return_pc_location);
ReturnPCLocation return_pc_location,
bool save_vectors = false);
static void restore_live_registers_and_pop_frame(MacroAssembler* masm,
int frame_size_in_bytes,
bool restore_ctr);
bool restore_ctr,
bool save_vectors = false);
static void push_frame_and_save_argument_registers(MacroAssembler* masm,
Register r_temp,
@ -97,14 +99,16 @@ class RegisterSaver {
// Constants and data structures:
typedef enum {
int_reg = 0,
float_reg = 1,
special_reg = 2
int_reg,
float_reg,
special_reg,
vs_reg
} RegisterType;
typedef enum {
reg_size = 8,
half_reg_size = reg_size / 2,
vs_reg_size = 16
} RegisterConstants;
typedef struct {
@ -115,15 +119,18 @@ class RegisterSaver {
};
#define RegisterSaver_LiveSpecialReg(regname) \
{ RegisterSaver::special_reg, regname->encoding(), regname->as_VMReg() }
#define RegisterSaver_LiveIntReg(regname) \
{ RegisterSaver::int_reg, regname->encoding(), regname->as_VMReg() }
#define RegisterSaver_LiveFloatReg(regname) \
{ RegisterSaver::float_reg, regname->encoding(), regname->as_VMReg() }
#define RegisterSaver_LiveSpecialReg(regname) \
{ RegisterSaver::special_reg, regname->encoding(), regname->as_VMReg() }
#define RegisterSaver_LiveVSReg(regname) \
{ RegisterSaver::vs_reg, regname->encoding(), regname->as_VMReg() }
static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = {
// Live registers which get spilled to the stack. Register
// positions in this array correspond directly to the stack layout.
@ -201,14 +208,42 @@ static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = {
RegisterSaver_LiveIntReg( R28 ),
RegisterSaver_LiveIntReg( R29 ),
RegisterSaver_LiveIntReg( R30 ),
RegisterSaver_LiveIntReg( R31 ), // must be the last register (see save/restore functions below)
RegisterSaver_LiveIntReg( R31 ) // must be the last register (see save/restore functions below)
};
static const RegisterSaver::LiveRegType RegisterSaver_LiveVSRegs[] = {
//
// live vector scalar registers (optional, only these ones are used by C2):
//
RegisterSaver_LiveVSReg( VSR32 ),
RegisterSaver_LiveVSReg( VSR33 ),
RegisterSaver_LiveVSReg( VSR34 ),
RegisterSaver_LiveVSReg( VSR35 ),
RegisterSaver_LiveVSReg( VSR36 ),
RegisterSaver_LiveVSReg( VSR37 ),
RegisterSaver_LiveVSReg( VSR38 ),
RegisterSaver_LiveVSReg( VSR39 ),
RegisterSaver_LiveVSReg( VSR40 ),
RegisterSaver_LiveVSReg( VSR41 ),
RegisterSaver_LiveVSReg( VSR42 ),
RegisterSaver_LiveVSReg( VSR43 ),
RegisterSaver_LiveVSReg( VSR44 ),
RegisterSaver_LiveVSReg( VSR45 ),
RegisterSaver_LiveVSReg( VSR46 ),
RegisterSaver_LiveVSReg( VSR47 ),
RegisterSaver_LiveVSReg( VSR48 ),
RegisterSaver_LiveVSReg( VSR49 ),
RegisterSaver_LiveVSReg( VSR50 ),
RegisterSaver_LiveVSReg( VSR51 )
};
OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssembler* masm,
int* out_frame_size_in_bytes,
bool generate_oop_map,
int return_pc_adjustment,
ReturnPCLocation return_pc_location) {
ReturnPCLocation return_pc_location,
bool save_vectors) {
// Push an abi_reg_args-frame and store all registers which may be live.
// If requested, create an OopMap: Record volatile registers as
// callee-save values in an OopMap so their save locations will be
@ -218,15 +253,16 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
// If return_pc_adjustment != 0 adjust the return pc by return_pc_adjustment.
// Updated return pc is returned in R31 (if not return_pc_is_pre_saved).
int i;
int offset;
// calcualte frame size
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
const int register_save_size = regstosave_num * reg_size;
const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) /
sizeof(RegisterSaver::LiveRegType))
: 0;
const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size;
const int frame_size_in_bytes = align_up(register_save_size, frame::alignment_in_bytes)
+ frame::abi_reg_args_size;
*out_frame_size_in_bytes = frame_size_in_bytes;
const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
const int register_save_offset = frame_size_in_bytes - register_save_size;
@ -236,17 +272,18 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
BLOCK_COMMENT("push_frame_reg_args_and_save_live_registers {");
// Save some registers in the last slots of the not yet pushed frame so that we
// can use them as scratch regs.
__ std(R31, - reg_size, R1_SP);
__ std(R30, -2*reg_size, R1_SP);
assert(-reg_size == register_save_offset - frame_size_in_bytes + ((regstosave_num-1)*reg_size),
"consistency check");
// push a new frame
__ push_frame(frame_size_in_bytes, noreg);
// Save some registers in the last (non-vector) slots of the new frame so we
// can use them as scratch regs or to determine the return pc.
__ std(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP);
__ std(R30, frame_size_in_bytes - 2*reg_size - vsregstosave_num * vs_reg_size, R1_SP);
// save the flags
// Do the save_LR_CR by hand and adjust the return pc if requested.
__ mfcr(R30);
__ std(R30, _abi(cr), R1_SP);
__ std(R30, frame_size_in_bytes + _abi(cr), R1_SP);
switch (return_pc_location) {
case return_pc_is_lr: __ mflr(R31); break;
case return_pc_is_pre_saved: assert(return_pc_adjustment == 0, "unsupported"); break;
@ -257,14 +294,12 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
if (return_pc_adjustment != 0) {
__ addi(R31, R31, return_pc_adjustment);
}
__ std(R31, _abi(lr), R1_SP);
__ std(R31, frame_size_in_bytes + _abi(lr), R1_SP);
}
// push a new frame
__ push_frame(frame_size_in_bytes, R30);
// save all registers (ints and floats)
offset = register_save_offset;
int offset = register_save_offset;
for (int i = 0; i < regstosave_num; i++) {
int reg_num = RegisterSaver_LiveRegs[i].reg_num;
int reg_type = RegisterSaver_LiveRegs[i].reg_type;
@ -302,6 +337,22 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
offset += reg_size;
}
for (int i = 0; i < vsregstosave_num; i++) {
int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
int reg_type = RegisterSaver_LiveVSRegs[i].reg_type;
__ li(R30, offset);
__ stxvd2x(as_VectorSRegister(reg_num), R30, R1_SP);
if (generate_oop_map) {
map->set_callee_saved(VMRegImpl::stack2reg(offset>>2),
RegisterSaver_LiveVSRegs[i].vmreg);
}
offset += vs_reg_size;
}
assert(offset == frame_size_in_bytes, "consistency check");
BLOCK_COMMENT("} push_frame_reg_args_and_save_live_registers");
// And we're done.
@ -313,18 +364,22 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble
// saved.
void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
int frame_size_in_bytes,
bool restore_ctr) {
int i;
int offset;
bool restore_ctr,
bool save_vectors) {
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
const int register_save_size = regstosave_num * reg_size;
const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) /
sizeof(RegisterSaver::LiveRegType))
: 0;
const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size;
const int register_save_offset = frame_size_in_bytes - register_save_size;
BLOCK_COMMENT("restore_live_registers_and_pop_frame {");
// restore all registers (ints and floats)
offset = register_save_offset;
int offset = register_save_offset;
for (int i = 0; i < regstosave_num; i++) {
int reg_num = RegisterSaver_LiveRegs[i].reg_num;
int reg_type = RegisterSaver_LiveRegs[i].reg_type;
@ -356,14 +411,30 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm,
offset += reg_size;
}
// pop the frame
__ pop_frame();
for (int i = 0; i < vsregstosave_num; i++) {
int reg_num = RegisterSaver_LiveVSRegs[i].reg_num;
int reg_type = RegisterSaver_LiveVSRegs[i].reg_type;
// restore the flags
__ restore_LR_CR(R31);
__ li(R31, offset);
__ lxvd2x(as_VectorSRegister(reg_num), R31, R1_SP);
offset += vs_reg_size;
}
assert(offset == frame_size_in_bytes, "consistency check");
// restore link and the flags
__ ld(R31, frame_size_in_bytes + _abi(lr), R1_SP);
__ mtlr(R31);
__ ld(R31, frame_size_in_bytes + _abi(cr), R1_SP);
__ mtcr(R31);
// restore scratch register's value
__ ld(R31, -reg_size, R1_SP);
__ ld(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP);
// pop the frame
__ addi(R1_SP, R1_SP, frame_size_in_bytes);
BLOCK_COMMENT("} restore_live_registers_and_pop_frame");
}
@ -447,15 +518,13 @@ void RegisterSaver::restore_argument_registers_and_pop_frame(MacroAssembler*masm
// Restore the registers that might be holding a result.
void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_size_in_bytes) {
int i;
int offset;
const int regstosave_num = sizeof(RegisterSaver_LiveRegs) /
sizeof(RegisterSaver::LiveRegType);
const int register_save_size = regstosave_num * reg_size;
const int register_save_size = regstosave_num * reg_size; // VS registers not relevant here.
const int register_save_offset = frame_size_in_bytes - register_save_size;
// restore all result registers (ints and floats)
offset = register_save_offset;
int offset = register_save_offset;
for (int i = 0; i < regstosave_num; i++) {
int reg_num = RegisterSaver_LiveRegs[i].reg_num;
int reg_type = RegisterSaver_LiveRegs[i].reg_type;
@ -479,6 +548,8 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_siz
}
offset += reg_size;
}
assert(offset == frame_size_in_bytes, "consistency check");
}
// Is vector's size (in bytes) bigger than a size saved by default?
@ -3109,12 +3180,14 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
__ tabort_();
}
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
// Save registers, fpu state, and flags. Set R31 = return pc.
map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
&frame_size_in_bytes,
/*generate_oop_map=*/ true,
/*return_pc_adjustment=*/0,
return_pc_location);
return_pc_location, save_vectors);
// The following is basically a call_VM. However, we need the precise
// address of the call in order to generate an oopmap. Hence, we do all the
@ -3148,7 +3221,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
// Exception pending
RegisterSaver::restore_live_registers_and_pop_frame(masm,
frame_size_in_bytes,
/*restore_ctr=*/true);
/*restore_ctr=*/true, save_vectors);
BLOCK_COMMENT(" Jump to forward_exception_entry.");
// Jump to forward_exception_entry, with the issuing PC in LR
@ -3175,7 +3248,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
// Normal exit, restore registers and exit.
RegisterSaver::restore_live_registers_and_pop_frame(masm,
frame_size_in_bytes,
/*restore_ctr=*/true);
/*restore_ctr=*/true, save_vectors);
__ blr();

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018 SAP SE. 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
@ -28,16 +28,21 @@
inline VMReg RegisterImpl::as_VMReg() {
if (this == noreg) return VMRegImpl::Bad();
// Two halfs, multiply by 2.
return VMRegImpl::as_VMReg(encoding() << 1);
}
// Since we don't have two halfs here, don't multiply by 2.
inline VMReg ConditionRegisterImpl::as_VMReg() {
inline VMReg FloatRegisterImpl::as_VMReg() {
// Two halfs, multiply by 2.
return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr);
}
inline VMReg VectorSRegisterImpl::as_VMReg() {
return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_fpr);
}
inline VMReg FloatRegisterImpl::as_VMReg() {
return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr);
inline VMReg ConditionRegisterImpl::as_VMReg() {
return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_vsr);
}
inline VMReg SpecialRegisterImpl::as_VMReg() {