diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index a798dea08cc79..6a0c4871545f1 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -779,9 +779,17 @@ void MacroAssembler::warn(const char* msg) { andq(rsp, -16); // align stack as required by push_CPU_state and call push_CPU_state(); // keeps alignment at 16 bytes +#ifdef _WIN64 + // Windows always allocates space for its register args + subq(rsp, frame::arg_reg_save_area_bytes); +#endif lea(c_rarg0, ExternalAddress((address) msg)); call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); +#ifdef _WIN64 + // restore stack pointer + addq(rsp, frame::arg_reg_save_area_bytes); +#endif pop_CPU_state(); mov(rsp, rbp); pop(rbp); @@ -2376,6 +2384,22 @@ void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst, Register rscratch } } +void MacroAssembler::cmp32_mxcsr_std(Address mxcsr_save, Register tmp, Register rscratch) { + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); + assert(rscratch != noreg || always_reachable(mxcsr_std), "missing"); + + stmxcsr(mxcsr_save); + movl(tmp, mxcsr_save); + if (EnableX86ECoreOpts) { + // The mxcsr_std has status bits set for performance on ECore + orl(tmp, 0x003f); + } else { + // Mask out status bits (only check control and mask bits) + andl(tmp, 0xFFC0); + } + cmp32(tmp, mxcsr_std, rscratch); +} + void MacroAssembler::ldmxcsr(AddressLiteral src, Register rscratch) { assert(rscratch != noreg || always_reachable(src), "missing"); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index c6e5b2a115f03..b6f229661a8e9 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1135,6 +1135,7 @@ class MacroAssembler: public Assembler { void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); } #endif // !_LP64 + void cmp32_mxcsr_std(Address mxcsr_save, Register tmp, Register rscratch = noreg); void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } void ldmxcsr(AddressLiteral src, Register rscratch = noreg); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp index de13772dcfb0d..88490dabccbe8 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp @@ -62,7 +62,6 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions const int FPU_CNTRL_WRD_MASK = 0xFFFF; ATTRIBUTE_ALIGNED(16) static const uint32_t KEY_SHUFFLE_MASK[] = { @@ -175,11 +174,7 @@ class StubGenerator: public StubCodeGenerator { // save and initialize %mxcsr if (sse_save) { Label skip_ldmx; - __ stmxcsr(mxcsr_save); - __ movl(rax, mxcsr_save); - __ andl(rax, MXCSR_MASK); // Only check control and mask bits - ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); - __ cmp32(rax, mxcsr_std); + __ cmp32_mxcsr_std(mxcsr_save, rax); __ jcc(Assembler::equal, skip_ldmx); __ ldmxcsr(mxcsr_std); __ bind(skip_ldmx); @@ -462,17 +457,14 @@ class StubGenerator: public StubCodeGenerator { if (CheckJNICalls && UseSSE > 0 ) { Label ok_ret; - ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); __ push(rax); __ subptr(rsp, wordSize); // allocate a temp location - __ stmxcsr(mxcsr_save); - __ movl(rax, mxcsr_save); - __ andl(rax, MXCSR_MASK); - __ cmp32(rax, mxcsr_std); + __ cmp32_mxcsr_std(mxcsr_save, rax); __ jcc(Assembler::equal, ok_ret); __ warn("MXCSR changed by native JNI code."); + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); __ ldmxcsr(mxcsr_std); __ bind(ok_ret); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 3979237619c92..705511914b700 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -248,12 +248,9 @@ address StubGenerator::generate_call_stub(address& return_address) { const Address mxcsr_save(rbp, mxcsr_off * wordSize); { Label skip_ldmx; - __ stmxcsr(mxcsr_save); - __ movl(rax, mxcsr_save); - __ andl(rax, 0xFFC0); // Mask out any pending exceptions (only check control and mask bits) - ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); - __ cmp32(rax, mxcsr_std, rscratch1); + __ cmp32_mxcsr_std(mxcsr_save, rax, rscratch1); __ jcc(Assembler::equal, skip_ldmx); + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); __ ldmxcsr(mxcsr_std, rscratch1); __ bind(skip_ldmx); } @@ -574,10 +571,7 @@ address StubGenerator::generate_verify_mxcsr() { ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); __ push(rax); __ subptr(rsp, wordSize); // allocate a temp location - __ stmxcsr(mxcsr_save); - __ movl(rax, mxcsr_save); - __ andl(rax, 0xFFC0); // Mask out any pending exceptions (only check control and mask bits) - __ cmp32(rax, mxcsr_std, rscratch1); + __ cmp32_mxcsr_std(mxcsr_save, rax, rscratch1); __ jcc(Assembler::equal, ok_ret); __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall"); diff --git a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp index e2dadf7f0ef98..7769316714957 100644 --- a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp @@ -77,8 +77,6 @@ static int compute_reg_save_area_size(const ABIDescriptor& abi) { return size; } -constexpr int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions - static void preserve_callee_saved_registers(MacroAssembler* _masm, const ABIDescriptor& abi, int reg_save_area_offset) { // 1. iterate all registers in the architecture // - check if they are volatile or not for the given abi @@ -115,12 +113,9 @@ static void preserve_callee_saved_registers(MacroAssembler* _masm, const ABIDesc { const Address mxcsr_save(rsp, offset); Label skip_ldmx; - __ stmxcsr(mxcsr_save); - __ movl(rax, mxcsr_save); - __ andl(rax, MXCSR_MASK); // Only check control and mask bits - ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); - __ cmp32(rax, mxcsr_std, rscratch1); + __ cmp32_mxcsr_std(mxcsr_save, rax, rscratch1); __ jcc(Assembler::equal, skip_ldmx); + ExternalAddress mxcsr_std(StubRoutines::x86::addr_mxcsr_std()); __ ldmxcsr(mxcsr_std, rscratch1); __ bind(skip_ldmx); } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index afd8fe01752b0..6487bb692cddc 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2570,38 +2570,6 @@ LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) { return EXCEPTION_CONTINUE_EXECUTION; } -#if defined(_M_AMD64) -//----------------------------------------------------------------------------- -static bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo) { - // handle exception caused by native method modifying control word - DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; - - switch (exception_code) { - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_STACK_CHECK: - case EXCEPTION_FLT_UNDERFLOW: { - PCONTEXT ctx = exceptionInfo->ContextRecord; - // On Windows, the mxcsr control bits are non-volatile across calls - // See also CR 6192333 - // - jint MxCsr = INITIAL_MXCSR; - // we can't use StubRoutines::x86::addr_mxcsr_std() - // because in Win64 mxcsr is not saved there - if (MxCsr != ctx->MxCsr) { - ctx->MxCsr = MxCsr; - return true; - } - } - } - - return false; -} -#endif - static inline void report_error(Thread* t, DWORD exception_code, address addr, void* siginfo, void* context) { VMError::report_and_die(t, exception_code, addr, siginfo, context); @@ -2786,6 +2754,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } #if defined(_M_AMD64) + extern bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo); if ((in_java || in_native) && handle_FLT_exception(exceptionInfo)) { return EXCEPTION_CONTINUE_EXECUTION; } diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 9a23ac6733521..ff59c637c3053 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -160,6 +160,43 @@ bool os::win32::register_code_area(char *low, char *high) { return true; } +#if defined(_M_AMD64) +//----------------------------------------------------------------------------- +bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo) { + // handle exception caused by native method modifying control word + DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; + + switch (exception_code) { + case EXCEPTION_FLT_DENORMAL_OPERAND: + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + case EXCEPTION_FLT_INEXACT_RESULT: + case EXCEPTION_FLT_INVALID_OPERATION: + case EXCEPTION_FLT_OVERFLOW: + case EXCEPTION_FLT_STACK_CHECK: + case EXCEPTION_FLT_UNDERFLOW: { + PCONTEXT ctx = exceptionInfo->ContextRecord; + // On Windows, the mxcsr control bits are non-volatile across calls + // See also CR 6192333 + // + jint MxCsr = INITIAL_MXCSR; // set to 0x1f80` in winnt.h + if (EnableX86ECoreOpts) { + // On ECore restore with status bits enabled + MxCsr |= 0x3F; + } + + // we can't use StubRoutines::x86::addr_mxcsr_std() + // because in Win64 mxcsr is not saved there + if (MxCsr != ctx->MxCsr) { + ctx->MxCsr = MxCsr; + return true; + } + } + } + + return false; +} +#endif + #ifdef HAVE_PLATFORM_PRINT_NATIVE_STACK /* * Windows/x64 does not use stack frames the way expected by Java: diff --git a/test/jdk/java/lang/String/IndexOf.java b/test/jdk/java/lang/String/IndexOf.java index e37e253f2516c..b4fd17105a8a5 100644 --- a/test/jdk/java/lang/String/IndexOf.java +++ b/test/jdk/java/lang/String/IndexOf.java @@ -34,7 +34,7 @@ * @summary test String indexOf() intrinsic * @requires vm.cpu.features ~= ".*avx2.*" * @requires vm.compiler2.enabled - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:-CheckJNICalls IndexOf + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation -XX:UseAVX=2 -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts IndexOf */ public class IndexOf { diff --git a/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java b/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java index 942486e85b8dc..ccaee0f77ea22 100644 --- a/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java +++ b/test/jdk/java/lang/StringBuffer/ECoreIndexOf.java @@ -34,7 +34,7 @@ * @summary Test indexOf and lastIndexOf * @requires vm.cpu.features ~= ".*avx2.*" * @requires vm.compiler2.enabled - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:-CheckJNICalls -XX:UseAVX=2 -Xbatch -XX:-TieredCompilation -XX:CompileCommand=dontinline,ECoreIndexOf.indexOfKernel ECoreIndexOf + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+EnableX86ECoreOpts -XX:UseAVX=2 -Xbatch -XX:-TieredCompilation -XX:CompileCommand=dontinline,ECoreIndexOf.indexOfKernel ECoreIndexOf * @key randomness */