JDK-6968348 : Byteswapped memory access can point to wrong location after JIT
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6u21
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2010-07-12
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u25Fixed 7Fixed hs20Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) 64-Bit Server VM (build 14.0-b16, mixed mode)

java version "1.6.0_21-ea-fastdebug"
Java(TM) SE Runtime Environment (build 1.6.0_21-ea-fastdebug-b05)
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b15-fastdebug, mixed mode)

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b76)
Java HotSpot(TM) 64-Bit Server VM (build 17.0-b05, mixed mode)

FULL OS VERSION :
Linux hfdv1.aoa.twosigma.com 2.6.30.4-ts10 #4 SMP PREEMPT Thu Jan 14 20:16:13 GMT 2010 x86_64 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
In a loop using sun.misc.Unsafe to write directly to memory:

for (int i = 0; i < BUF_SIZE; i += 8)
    unsafe.putLong(addr + i, Long.reverseBytes(i));

JIT generates this byte code for the inner loop:

03b     movq    R11, 0x00002b814042b000 # ptr
045     movl    RCX, RBX        # spill
047     movslq  R8, RCX # i2l
04a     movq_bswap [R11 + R8], R8

Which translates to these instructions:

0x2b6606210741: mov    $0x2b814042b000,%r11
0x2b660621074b: mov    %ebx,%ecx
0x2b660621074d: movslq %ecx,%r8
0x2b6606210750: bswap  %r8
0x2b6606210753: mov    %r8,(%r11,%r8,1)

The movq_bswap swaps R8 and then uses the swapped version for the offset, causing the JVM to segfault.

THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: memory would be written
Actual: segfault

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
Changing the loop index to a long fixes the problem:

for (long i = 0; i < BUF_SIZE; i += 8)
    unsafe.putLong(addr + i, Long.reverseBytes(i));

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/52e82a6bedaf
09-10-2010

EVALUATION 6968348: Byteswapped memory access can point to wrong location after JIT Reviewed-by: twisti, kvn, iveresov x86_64.ad has match rules for (Store (ReverseBytes val)) but the definition is buggy since the val can be used in address of the store. It also doesn't record that it changes the input value. The fix is to simply remove these rules since they are no better than what we'd get otherwise. x86_32.ad doesn't have these rules. sparc.ad does but it can generate better code for these forms because it can use the byte swapped ASI and doesn't have to modify the register before storing it. Tested with new test case.
05-10-2010

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/52e82a6bedaf
05-10-2010