8193009: compiler/c2/Test7029152.java crashes with SIGILL in java.lang.StringLatin1.indexOf with -XX:+UseJVMCICompiler
authordlong
Wed, 06 Dec 2017 18:37:57 -0800
changeset 48314 46e52a0ba925
parent 48313 da23405d54db
child 48315 32fd4be602d5
8193009: compiler/c2/Test7029152.java crashes with SIGILL in java.lang.StringLatin1.indexOf with -XX:+UseJVMCICompiler Reviewed-by: iveresov, kvn
src/hotspot/cpu/x86/nativeInst_x86.hpp
src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
--- a/src/hotspot/cpu/x86/nativeInst_x86.hpp	Wed Dec 06 20:06:43 2017 -0500
+++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp	Wed Dec 06 18:37:57 2017 -0800
@@ -706,14 +706,11 @@
 inline bool NativeInstruction::is_safepoint_poll() {
 #ifdef AMD64
   if (SafepointMechanism::uses_thread_local_poll()) {
-    // We know that the poll must have a REX_B prefix since we enforce its source to be
-    // a rex-register and the destination to be rax.
     const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
-    const bool is_test_opcode = ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl;
-    const bool is_rax_target = (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
-    if (has_rex_prefix && is_test_opcode && is_rax_target) {
-      return true;
-    }
+    const int test_offset = has_rex_prefix ? 1 : 0;
+    const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
+    const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
+    return is_test_opcode && is_rax_target;
   }
   // Try decoding a near safepoint first:
   if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Wed Dec 06 20:06:43 2017 -0500
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp	Wed Dec 06 18:37:57 2017 -0800
@@ -3388,23 +3388,57 @@
   // No exception case
   __ bind(noException);
 
-  Label no_adjust, bail, no_prefix;
+  Label no_adjust, bail, no_prefix, not_special;
   if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
     // If our stashed return pc was modified by the runtime we avoid touching it
     __ cmpptr(rbx, Address(rbp, wordSize));
     __ jccb(Assembler::notEqual, no_adjust);
 
-    // Verify the correct encoding of the poll we're about to skip.
+    // Skip over the poll instruction.
     // See NativeInstruction::is_safepoint_poll()
+    // Possible encodings:
+    //      85 00       test   %eax,(%rax)
+    //      85 01       test   %eax,(%rcx)
+    //      85 02       test   %eax,(%rdx)
+    //      85 03       test   %eax,(%rbx)
+    //      85 06       test   %eax,(%rsi)
+    //      85 07       test   %eax,(%rdi)
+    //
+    //   41 85 00       test   %eax,(%r8)
+    //   41 85 01       test   %eax,(%r9)
+    //   41 85 02       test   %eax,(%r10)
+    //   41 85 03       test   %eax,(%r11)
+    //   41 85 06       test   %eax,(%r14)
+    //   41 85 07       test   %eax,(%r15)
+    //
+    //      85 04 24    test   %eax,(%rsp)
+    //   41 85 04 24    test   %eax,(%r12)
+    //      85 45 00    test   %eax,0x0(%rbp)
+    //   41 85 45 00    test   %eax,0x0(%r13)
+
     __ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_rex_b_prefix);
     __ jcc(Assembler::notEqual, no_prefix);
     __ addptr(rbx, 1);
     __ bind(no_prefix);
 #ifdef ASSERT
-    __ cmpb(Address(rbx, 0), NativeTstRegMem::instruction_code_memXregl);
+    __ movptr(rax, rbx); // remember where 0x85 should be, for verification below
+#endif
+    // r12/r13/rsp/rbp base encoding takes 3 bytes with the following register values:
+    // r12/rsp 0x04
+    // r13/rbp 0x05
+    __ movzbq(rcx, Address(rbx, 1));
+    __ andptr(rcx, 0x07); // looking for 0x04 .. 0x05
+    __ subptr(rcx, 4);    // looking for 0x00 .. 0x01
+    __ cmpptr(rcx, 1);
+    __ jcc(Assembler::above, not_special);
+    __ addptr(rbx, 1);
+    __ bind(not_special);
+#ifdef ASSERT
+    // Verify the correct encoding of the poll we're about to skip.
+    __ cmpb(Address(rax, 0), NativeTstRegMem::instruction_code_memXregl);
     __ jcc(Assembler::notEqual, bail);
     // Mask out the modrm bits
-    __ testb(Address(rbx, 1), NativeTstRegMem::modrm_mask);
+    __ testb(Address(rax, 1), NativeTstRegMem::modrm_mask);
     // rax encodes to 0, so if the bits are nonzero it's incorrect
     __ jcc(Assembler::notZero, bail);
 #endif