mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 17:44:40 +02:00
7196199: java/text/Bidi/Bug6665028.java failed: Bidi run count incorrect
Save whole XMM/YMM registers in safepoint interrupt handler. Reviewed-by: roland, twisti
This commit is contained in:
parent
45435c5485
commit
811c047ec1
19 changed files with 654 additions and 204 deletions
|
@ -46,11 +46,11 @@
|
|||
const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size;
|
||||
|
||||
class RegisterSaver {
|
||||
enum { FPU_regs_live = 8 /*for the FPU stack*/+8/*eight more for XMM registers*/ };
|
||||
// Capture info about frame layout
|
||||
#define DEF_XMM_OFFS(regnum) xmm ## regnum ## _off = xmm_off + (regnum)*16/BytesPerInt, xmm ## regnum ## H_off
|
||||
enum layout {
|
||||
fpu_state_off = 0,
|
||||
fpu_state_end = fpu_state_off+FPUStateSizeInWords-1,
|
||||
fpu_state_end = fpu_state_off+FPUStateSizeInWords,
|
||||
st0_off, st0H_off,
|
||||
st1_off, st1H_off,
|
||||
st2_off, st2H_off,
|
||||
|
@ -59,16 +59,16 @@ class RegisterSaver {
|
|||
st5_off, st5H_off,
|
||||
st6_off, st6H_off,
|
||||
st7_off, st7H_off,
|
||||
|
||||
xmm0_off, xmm0H_off,
|
||||
xmm1_off, xmm1H_off,
|
||||
xmm2_off, xmm2H_off,
|
||||
xmm3_off, xmm3H_off,
|
||||
xmm4_off, xmm4H_off,
|
||||
xmm5_off, xmm5H_off,
|
||||
xmm6_off, xmm6H_off,
|
||||
xmm7_off, xmm7H_off,
|
||||
flags_off,
|
||||
xmm_off,
|
||||
DEF_XMM_OFFS(0),
|
||||
DEF_XMM_OFFS(1),
|
||||
DEF_XMM_OFFS(2),
|
||||
DEF_XMM_OFFS(3),
|
||||
DEF_XMM_OFFS(4),
|
||||
DEF_XMM_OFFS(5),
|
||||
DEF_XMM_OFFS(6),
|
||||
DEF_XMM_OFFS(7),
|
||||
flags_off = xmm7_off + 16/BytesPerInt + 1, // 16-byte stack alignment fill word
|
||||
rdi_off,
|
||||
rsi_off,
|
||||
ignore_off, // extra copy of rbp,
|
||||
|
@ -83,13 +83,13 @@ class RegisterSaver {
|
|||
rbp_off,
|
||||
return_off, // slot for return address
|
||||
reg_save_size };
|
||||
|
||||
enum { FPU_regs_live = flags_off - fpu_state_end };
|
||||
|
||||
public:
|
||||
|
||||
static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words,
|
||||
int* total_frame_words, bool verify_fpu = true);
|
||||
static void restore_live_registers(MacroAssembler* masm);
|
||||
int* total_frame_words, bool verify_fpu = true, bool save_vectors = false);
|
||||
static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false);
|
||||
|
||||
static int rax_offset() { return rax_off; }
|
||||
static int rbx_offset() { return rbx_off; }
|
||||
|
@ -113,9 +113,20 @@ class RegisterSaver {
|
|||
};
|
||||
|
||||
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words,
|
||||
int* total_frame_words, bool verify_fpu) {
|
||||
|
||||
int frame_size_in_bytes = (reg_save_size + additional_frame_words) * wordSize;
|
||||
int* total_frame_words, bool verify_fpu, bool save_vectors) {
|
||||
int vect_words = 0;
|
||||
#ifdef COMPILER2
|
||||
if (save_vectors) {
|
||||
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
|
||||
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
|
||||
// Save upper half of YMM registes
|
||||
vect_words = 8 * 16 / wordSize;
|
||||
additional_frame_words += vect_words;
|
||||
}
|
||||
#else
|
||||
assert(!save_vectors, "vectors are generated only by C2");
|
||||
#endif
|
||||
int frame_size_in_bytes = (reg_save_size + additional_frame_words) * wordSize;
|
||||
int frame_words = frame_size_in_bytes / wordSize;
|
||||
*total_frame_words = frame_words;
|
||||
|
||||
|
@ -129,7 +140,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
|||
__ enter();
|
||||
__ pusha();
|
||||
__ pushf();
|
||||
__ subptr(rsp,FPU_regs_live*sizeof(jdouble)); // Push FPU registers space
|
||||
__ subptr(rsp,FPU_regs_live*wordSize); // Push FPU registers space
|
||||
__ push_FPU_state(); // Save FPU state & init
|
||||
|
||||
if (verify_fpu) {
|
||||
|
@ -183,14 +194,28 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
|||
__ movflt(Address(rsp,xmm6_off*wordSize),xmm6);
|
||||
__ movflt(Address(rsp,xmm7_off*wordSize),xmm7);
|
||||
} else if( UseSSE >= 2 ) {
|
||||
__ movdbl(Address(rsp,xmm0_off*wordSize),xmm0);
|
||||
__ movdbl(Address(rsp,xmm1_off*wordSize),xmm1);
|
||||
__ movdbl(Address(rsp,xmm2_off*wordSize),xmm2);
|
||||
__ movdbl(Address(rsp,xmm3_off*wordSize),xmm3);
|
||||
__ movdbl(Address(rsp,xmm4_off*wordSize),xmm4);
|
||||
__ movdbl(Address(rsp,xmm5_off*wordSize),xmm5);
|
||||
__ movdbl(Address(rsp,xmm6_off*wordSize),xmm6);
|
||||
__ movdbl(Address(rsp,xmm7_off*wordSize),xmm7);
|
||||
// Save whole 128bit (16 bytes) XMM regiters
|
||||
__ movdqu(Address(rsp,xmm0_off*wordSize),xmm0);
|
||||
__ movdqu(Address(rsp,xmm1_off*wordSize),xmm1);
|
||||
__ movdqu(Address(rsp,xmm2_off*wordSize),xmm2);
|
||||
__ movdqu(Address(rsp,xmm3_off*wordSize),xmm3);
|
||||
__ movdqu(Address(rsp,xmm4_off*wordSize),xmm4);
|
||||
__ movdqu(Address(rsp,xmm5_off*wordSize),xmm5);
|
||||
__ movdqu(Address(rsp,xmm6_off*wordSize),xmm6);
|
||||
__ movdqu(Address(rsp,xmm7_off*wordSize),xmm7);
|
||||
}
|
||||
|
||||
if (vect_words > 0) {
|
||||
assert(vect_words*wordSize == 128, "");
|
||||
__ subptr(rsp, 128); // Save upper half of YMM registes
|
||||
__ vextractf128h(Address(rsp, 0),xmm0);
|
||||
__ vextractf128h(Address(rsp, 16),xmm1);
|
||||
__ vextractf128h(Address(rsp, 32),xmm2);
|
||||
__ vextractf128h(Address(rsp, 48),xmm3);
|
||||
__ vextractf128h(Address(rsp, 64),xmm4);
|
||||
__ vextractf128h(Address(rsp, 80),xmm5);
|
||||
__ vextractf128h(Address(rsp, 96),xmm6);
|
||||
__ vextractf128h(Address(rsp,112),xmm7);
|
||||
}
|
||||
|
||||
// Set an oopmap for the call site. This oopmap will map all
|
||||
|
@ -253,10 +278,20 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
|||
|
||||
}
|
||||
|
||||
void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
|
||||
|
||||
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
|
||||
// Recover XMM & FPU state
|
||||
if( UseSSE == 1 ) {
|
||||
int additional_frame_bytes = 0;
|
||||
#ifdef COMPILER2
|
||||
if (restore_vectors) {
|
||||
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
|
||||
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
|
||||
additional_frame_bytes = 128;
|
||||
}
|
||||
#else
|
||||
assert(!restore_vectors, "vectors are generated only by C2");
|
||||
#endif
|
||||
if (UseSSE == 1) {
|
||||
assert(additional_frame_bytes == 0, "");
|
||||
__ movflt(xmm0,Address(rsp,xmm0_off*wordSize));
|
||||
__ movflt(xmm1,Address(rsp,xmm1_off*wordSize));
|
||||
__ movflt(xmm2,Address(rsp,xmm2_off*wordSize));
|
||||
|
@ -265,18 +300,33 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
|
|||
__ movflt(xmm5,Address(rsp,xmm5_off*wordSize));
|
||||
__ movflt(xmm6,Address(rsp,xmm6_off*wordSize));
|
||||
__ movflt(xmm7,Address(rsp,xmm7_off*wordSize));
|
||||
} else if( UseSSE >= 2 ) {
|
||||
__ movdbl(xmm0,Address(rsp,xmm0_off*wordSize));
|
||||
__ movdbl(xmm1,Address(rsp,xmm1_off*wordSize));
|
||||
__ movdbl(xmm2,Address(rsp,xmm2_off*wordSize));
|
||||
__ movdbl(xmm3,Address(rsp,xmm3_off*wordSize));
|
||||
__ movdbl(xmm4,Address(rsp,xmm4_off*wordSize));
|
||||
__ movdbl(xmm5,Address(rsp,xmm5_off*wordSize));
|
||||
__ movdbl(xmm6,Address(rsp,xmm6_off*wordSize));
|
||||
__ movdbl(xmm7,Address(rsp,xmm7_off*wordSize));
|
||||
} else if (UseSSE >= 2) {
|
||||
#define STACK_ADDRESS(x) Address(rsp,(x)*wordSize + additional_frame_bytes)
|
||||
__ movdqu(xmm0,STACK_ADDRESS(xmm0_off));
|
||||
__ movdqu(xmm1,STACK_ADDRESS(xmm1_off));
|
||||
__ movdqu(xmm2,STACK_ADDRESS(xmm2_off));
|
||||
__ movdqu(xmm3,STACK_ADDRESS(xmm3_off));
|
||||
__ movdqu(xmm4,STACK_ADDRESS(xmm4_off));
|
||||
__ movdqu(xmm5,STACK_ADDRESS(xmm5_off));
|
||||
__ movdqu(xmm6,STACK_ADDRESS(xmm6_off));
|
||||
__ movdqu(xmm7,STACK_ADDRESS(xmm7_off));
|
||||
#undef STACK_ADDRESS
|
||||
}
|
||||
if (restore_vectors) {
|
||||
// Restore upper half of YMM registes.
|
||||
assert(additional_frame_bytes == 128, "");
|
||||
__ vinsertf128h(xmm0, Address(rsp, 0));
|
||||
__ vinsertf128h(xmm1, Address(rsp, 16));
|
||||
__ vinsertf128h(xmm2, Address(rsp, 32));
|
||||
__ vinsertf128h(xmm3, Address(rsp, 48));
|
||||
__ vinsertf128h(xmm4, Address(rsp, 64));
|
||||
__ vinsertf128h(xmm5, Address(rsp, 80));
|
||||
__ vinsertf128h(xmm6, Address(rsp, 96));
|
||||
__ vinsertf128h(xmm7, Address(rsp,112));
|
||||
__ addptr(rsp, additional_frame_bytes);
|
||||
}
|
||||
__ pop_FPU_state();
|
||||
__ addptr(rsp, FPU_regs_live*sizeof(jdouble)); // Pop FPU registers
|
||||
__ addptr(rsp, FPU_regs_live*wordSize); // Pop FPU registers
|
||||
|
||||
__ popf();
|
||||
__ popa();
|
||||
|
@ -308,6 +358,13 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
|
|||
__ addptr(rsp, return_off * wordSize);
|
||||
}
|
||||
|
||||
// Is vector's size (in bytes) bigger than a size saved by default?
|
||||
// 16 bytes XMM registers are saved by default using SSE2 movdqu instructions.
|
||||
// Note, MaxVectorSize == 0 with UseSSE < 2 and vectors are not generated.
|
||||
bool SharedRuntime::is_wide_vector(int size) {
|
||||
return size > 16;
|
||||
}
|
||||
|
||||
// The java_calling_convention describes stack locations as ideal slots on
|
||||
// a frame with no abi restrictions. Since we must observe abi restrictions
|
||||
// (like the placement of the register window) the slots must be biased by
|
||||
|
@ -2732,7 +2789,6 @@ uint SharedRuntime::out_preserve_stack_slots() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------generate_deopt_blob----------------------------
|
||||
void SharedRuntime::generate_deopt_blob() {
|
||||
// allocate space for the code
|
||||
|
@ -3270,7 +3326,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
|||
// setup oopmap, and calls safepoint code to stop the compiled code for
|
||||
// a safepoint.
|
||||
//
|
||||
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause_return) {
|
||||
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_type) {
|
||||
|
||||
// Account for thread arg in our frame
|
||||
const int additional_words = 1;
|
||||
|
@ -3290,17 +3346,18 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause
|
|||
const Register java_thread = rdi; // callee-saved for VC++
|
||||
address start = __ pc();
|
||||
address call_pc = NULL;
|
||||
|
||||
bool cause_return = (poll_type == POLL_AT_RETURN);
|
||||
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
|
||||
// If cause_return is true we are at a poll_return and there is
|
||||
// the return address on the stack to the caller on the nmethod
|
||||
// that is safepoint. We can leave this return on the stack and
|
||||
// effectively complete the return and safepoint in the caller.
|
||||
// Otherwise we push space for a return address that the safepoint
|
||||
// handler will install later to make the stack walking sensible.
|
||||
if( !cause_return )
|
||||
__ push(rbx); // Make room for return address (or push it again)
|
||||
if (!cause_return)
|
||||
__ push(rbx); // Make room for return address (or push it again)
|
||||
|
||||
map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false);
|
||||
map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false, 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
|
||||
|
@ -3312,7 +3369,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause
|
|||
__ set_last_Java_frame(java_thread, noreg, noreg, NULL);
|
||||
|
||||
// if this was not a poll_return then we need to correct the return address now.
|
||||
if( !cause_return ) {
|
||||
if (!cause_return) {
|
||||
__ movptr(rax, Address(java_thread, JavaThread::saved_exception_pc_offset()));
|
||||
__ movptr(Address(rbp, wordSize), rax);
|
||||
}
|
||||
|
@ -3340,15 +3397,14 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause
|
|||
__ jcc(Assembler::equal, noException);
|
||||
|
||||
// Exception pending
|
||||
|
||||
RegisterSaver::restore_live_registers(masm);
|
||||
RegisterSaver::restore_live_registers(masm, save_vectors);
|
||||
|
||||
__ jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
|
||||
|
||||
__ bind(noException);
|
||||
|
||||
// Normal exit, register restoring and exit
|
||||
RegisterSaver::restore_live_registers(masm);
|
||||
RegisterSaver::restore_live_registers(masm, save_vectors);
|
||||
|
||||
__ ret(0);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue