--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -3320,7 +3320,7 @@
// if tmp is invalid, then the function being called doesn't destroy the thread
if (tmp->is_valid()) {
- __ save_thread(tmp->as_register());
+ __ save_thread(tmp->as_pointer_register());
}
__ call(dest, relocInfo::runtime_call_type);
__ delayed()->nop();
@@ -3328,7 +3328,7 @@
add_call_info_here(info);
}
if (tmp->is_valid()) {
- __ restore_thread(tmp->as_register());
+ __ restore_thread(tmp->as_pointer_register());
}
#ifdef ASSERT
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -69,7 +69,7 @@
LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::Oexception_opr; }
LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::Oissuing_pc_opr; }
LIR_Opr LIRGenerator::syncTempOpr() { return new_register(T_OBJECT); }
-LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(T_INT); }
+LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); }
LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) {
LIR_Opr opr;
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -50,8 +50,13 @@
const char* VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
+// Address of instruction which causes SEGV
+address VM_Version::_cpuinfo_segv_addr = 0;
+// Address of instruction after the one which causes SEGV
+address VM_Version::_cpuinfo_cont_addr = 0;
+
static BufferBlob* stub_blob;
-static const int stub_size = 550;
+static const int stub_size = 600;
extern "C" {
typedef void (*getPsrInfo_stub_t)(void*);
@@ -234,9 +239,9 @@
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports AVX
//
- __ andl(rcx, 0x18000000);
+ __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
__ cmpl(rcx, 0x18000000);
- __ jccb(Assembler::notEqual, sef_cpuid);
+ __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
//
// XCR0, XFEATURE_ENABLED_MASK register
@@ -247,6 +252,47 @@
__ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rdx);
+ __ andl(rax, 0x6); // xcr0 bits sse | ymm
+ __ cmpl(rax, 0x6);
+ __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
+
+ //
+ // Some OSs have a bug when upper 128bits of YMM
+ // registers are not restored after a signal processing.
+ // Generate SEGV here (reference through NULL)
+ // and check upper YMM bits after it.
+ //
+ VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
+
+ // load value into all 32 bytes of ymm7 register
+ __ movl(rcx, VM_Version::ymm_test_value());
+
+ __ movdl(xmm0, rcx);
+ __ pshufd(xmm0, xmm0, 0x00);
+ __ vinsertf128h(xmm0, xmm0, xmm0);
+ __ vmovdqu(xmm7, xmm0);
+#ifdef _LP64
+ __ vmovdqu(xmm8, xmm0);
+ __ vmovdqu(xmm15, xmm0);
+#endif
+
+ __ xorl(rsi, rsi);
+ VM_Version::set_cpuinfo_segv_addr( __ pc() );
+ // Generate SEGV
+ __ movl(rax, Address(rsi, 0));
+
+ VM_Version::set_cpuinfo_cont_addr( __ pc() );
+ // Returns here after signal. Save xmm0 to check it later.
+ __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
+ __ vmovdqu(Address(rsi, 0), xmm0);
+ __ vmovdqu(Address(rsi, 32), xmm7);
+#ifdef _LP64
+ __ vmovdqu(Address(rsi, 64), xmm8);
+ __ vmovdqu(Address(rsi, 96), xmm15);
+#endif
+
+ VM_Version::clean_cpuFeatures();
+
//
// cpuid(0x7) Structured Extended Features
//
@@ -540,14 +586,28 @@
if (MaxVectorSize > 32) {
FLAG_SET_DEFAULT(MaxVectorSize, 32);
}
- if (MaxVectorSize > 16 && UseAVX == 0) {
- // Only supported with AVX+
+ if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
+ // 32 bytes vectors (in YMM) are only supported with AVX+
FLAG_SET_DEFAULT(MaxVectorSize, 16);
}
if (UseSSE < 2) {
- // Only supported with SSE2+
+ // Vectors (in XMM) are only supported with SSE2+
FLAG_SET_DEFAULT(MaxVectorSize, 0);
}
+#ifdef ASSERT
+ if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
+ tty->print_cr("State of YMM registers after signal handle:");
+ int nreg = 2 LP64_ONLY(+2);
+ const char* ymm_name[4] = {"0", "7", "8", "15"};
+ for (int i = 0; i < nreg; i++) {
+ tty->print("YMM%s:", ymm_name[i]);
+ for (int j = 7; j >=0; j--) {
+ tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
+ }
+ tty->cr();
+ }
+ }
+#endif
}
#endif
@@ -678,14 +738,6 @@
}
}
}
-#if defined(COMPILER2) && defined(_ALLBSD_SOURCE)
- if (MaxVectorSize > 16) {
- // Limit vectors size to 16 bytes on BSD until it fixes
- // restoring upper 128bit of YMM registers on return
- // from signal handler.
- FLAG_SET_DEFAULT(MaxVectorSize, 16);
- }
-#endif // COMPILER2
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
@@ -814,6 +866,11 @@
if (UseAES) {
tty->print(" UseAES=1");
}
+#ifdef COMPILER2
+ if (MaxVectorSize > 0) {
+ tty->print(" MaxVectorSize=%d", MaxVectorSize);
+ }
+#endif
tty->cr();
tty->print("Allocation");
if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Tue Mar 18 14:22:42 2014 +0100
@@ -229,6 +229,9 @@
// 0 if this instruction is not available
static const char* _features_str;
+ static address _cpuinfo_segv_addr; // address of instruction which causes SEGV
+ static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
+
enum {
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1),
@@ -361,6 +364,9 @@
// extended control register XCR0 (the XFEATURE_ENABLED_MASK register)
XemXcr0Eax xem_xcr0_eax;
uint32_t xem_xcr0_edx; // reserved
+
+ // Space to save ymm registers after signal handle
+ int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
};
// The actual cpuid info block
@@ -460,6 +466,21 @@
return result;
}
+ static bool os_supports_avx_vectors() {
+ if (!supports_avx()) {
+ return false;
+ }
+ // Verify that OS save/restore all bits of AVX registers
+ // during signal processing.
+ int nreg = 2 LP64_ONLY(+2);
+ for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
+ if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
static void get_processor_features();
public:
@@ -476,6 +497,19 @@
static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
+ static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
+
+ // The value used to check ymm register after signal handle
+ static int ymm_test_value() { return 0xCAFEBABE; }
+
+ static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
+ static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
+ static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
+ static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; }
+
+ static void clean_cpuFeatures() { _cpuFeatures = 0; }
+ static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
+
// Initialization
static void initialize();
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -2425,6 +2425,12 @@
}
}
+ if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&
+ VM_Version::is_cpuinfo_segv_addr(pc)) {
+ // Verify that OS save/restore AVX registers.
+ return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());
+ }
+
if (t != NULL && t->is_Java_thread()) {
JavaThread* thread = (JavaThread*) t;
bool in_java = thread->thread_state() == _thread_in_Java;
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -492,6 +492,11 @@
}
}
+ if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+ // Verify that OS save/restore AVX registers.
+ stub = VM_Version::cpuinfo_cont_addr();
+ }
+
// We test if stub is already set (by the stack overflow code
// above) so it is not overwritten by the code that follows. This
// check is not required on other platforms, because on other
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -338,6 +338,11 @@
}
}
+ if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+ // Verify that OS save/restore AVX registers.
+ stub = VM_Version::cpuinfo_cont_addr();
+ }
+
if (thread->thread_state() == _thread_in_Java) {
// Java thread running in Java code => find exception handler if any
// a fault inside compiled code, the interpreter, or a stub
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -459,6 +459,11 @@
}
}
+ if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) {
+ // Verify that OS save/restore AVX registers.
+ stub = VM_Version::cpuinfo_cont_addr();
+ }
+
if (thread->thread_state() == _thread_in_vm) {
if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) {
stub = StubRoutines::handler_for_unsafe_access();
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 18 14:22:42 2014 +0100
@@ -2526,7 +2526,7 @@
// need to free up storage used for OSR entry point
LIR_Opr osrBuffer = block()->next()->operand();
BasicTypeList signature;
- signature.append(T_INT);
+ signature.append(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); // pass a pointer to osrBuffer
CallingConvention* cc = frame_map()->c_calling_convention(&signature);
__ move(osrBuffer, cc->args()->at(0));
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end),
--- a/hotspot/test/compiler/6792161/Test6792161.java Fri Mar 14 10:31:11 2014 -0700
+++ b/hotspot/test/compiler/6792161/Test6792161.java Tue Mar 18 14:22:42 2014 +0100
@@ -27,7 +27,7 @@
* @bug 6792161
* @summary assert("No dead instructions after post-alloc")
*
- * @run main/othervm/timeout=300 -Xcomp -XX:MaxInlineSize=120 Test6792161
+ * @run main/othervm/timeout=600 -Xcomp -XX:MaxInlineSize=120 Test6792161
*/
import java.lang.reflect.Constructor;