JDK-5073497 : Casting long to int on 64-bit machine sometimes gives wrong result
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: itanium
  • Submitted: 2004-07-13
  • Updated: 2004-09-14
  • Resolved: 2004-09-14
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.
Other JDK 6
5.0u5Fixed 6 mustangFixed
Related Reports
Relates :  
Description

Name: gm110360			Date: 07/13/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta2-b51)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0-beta2-b51, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux amy.nz.reeltwo.com 2.6.7-rc2 #2 SMP Fri Jun 4 16:36:26 NZST 2004 x86_64 x86_64 x86_64 GNU/Linux

CPU is Opteron.

A DESCRIPTION OF THE PROBLEM :
Sometimes when casting a long to an int on an int, 0 is incorrectly returned as the result.
For example the test code below sometimes produces 0 for the result of the cast (int) 0x800000020001165fL.

I have produced this behaviour in both 1.5.0 and 1.4.2 on 64-bit machines.  I was NOT able to reproduce the problem on any 32-bit machines.

The nature of the failure to me looks like a JIT/HotSpot optimization problem, since the fault is  intermittent and highly dependent on adjacent code.   In particular, in the instructions,

      final long v = t[z];
      final long oldv = v;
      t[z] = 0L;
      if (v > 0) {
        ;
      } else {
         x = (int) v;
      }

Possibly something gets confused underneath so that when the cast is performed the new value of the array (i.e. 0) rather than the original value (i.e. v) is used.  The v>0 conditional also seems necessary to cause the problem.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the sample code.  I've used both jikes -source 1.4 and javac.

Run the sample code below.  It is important to use this exact test case since I have found that trivial variations to the test code make the problem disappear.

If everything runs as expected then there will be no output.  When the problem exists a single line appears showing the bad cast, for example:

$ java CastBug
Bad cast: 0 == (int) 0x800000020001165fL z was 59

(the exact cast that fails may vary)

You may need to run the code several times to cause the fault.  On my machine the fault occurs nine times out of ten.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The expected output is no output.
ACTUAL -
$ java CastBug
Bad cast: 0 == (int) 0x800000020001165fL z was 59


REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
/**
 * Demonstrate intermittent problem casting long to int.
 */
public class CastBug {

  /** Double the size of internal arrays and repack. */
  public static void main(String[] args) {
    int i = 0;
    long[] t = new long[100];
    for (int j = 0; j < t.length; j++) {
      t[j] = 0x8000000200011624L + (long) j;
    }
    while (++i < 100000) {
      final int z = i % t.length;
      final long v = t[z];
      final long oldv = v;
      t[z] = 0L;
      if (v > 0) {
        ;
      } else {
        int secondaryIndex = (int) v;
        if (secondaryIndex == 0) {
          System.err.println("Bad cast: " + secondaryIndex + " == (int) 0x" + Long.toHexString(v) + "L z was " + z);
          return;
        }
        for (int j = 0; j < 2; j++) {
          secondaryIndex = ~secondaryIndex;
        }
      }
      t[z] = oldv;
    }
  }

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Performing the cast twice and using the second result might work, but I would'nt rely on it.
(Incident Review ID: 284817) 
======================================================================

Comments
SUGGESTED FIX See PRT webrev for final fix: file:///net/prt-archiver/data/archived_workspaces/main/c2_baseline/2004/20040902140615.steved.tiger_bugs/workspace/webrevs/webrev-2004.09.02 ###@###.### 2005-03-15 17:45:56 GMT
15-03-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: dragon FIXED IN: mustang INTEGRATED IN: mustang
17-09-2004

PUBLIC COMMENTS Integrated in Build 04
17-09-2004

EVALUATION As there is no library code involved, transferring to the vm group ###@###.### 2004-07-15 I am able to reproduce this bug consistently on amd64 and Solaris x86 with the -Xbatch option. I suspect that the bug is intermittent for the submitter because occasionally the test finishes before the code generated by the compiler gets executed. I am unable to reproduce it on either 32 or 64 bit SPARC. The problem appears to be an optimization which converts an long to integer conversion of a long value which was just loaded to just an integer load. This optimization is only done on little-endian machines so I don't think it can occur on SPARC. I believe that the problem is that the integer load is not seen as aliasing other long references to this memory location and the integer load is getting incorrectly scheduled with respect to a subsequent long store. This bug occurs in releases back to at least 1.4.2. ###@###.### 2004-07-19 This failure is caused by a bug is in the loop optimizations. The optimiztion of a long to integer conversion triggers a situation which exposes the bug in the test case provided, but it is not necessary for the bug to occur. I have created a test case without a long to integer conversion which exhibits this bug. It fails on both SPARC and Intel. The problem is that the during the loop optimization, a load from memory is incorrectly moved past a store to the same memory location resulting in the load seing the updated value of the memory location. I will fix the code which schedules instructions in a loop by adding a check for anti-dependent stores when scheduling a load. ###@###.### 2004-08-04
04-08-2004