JDK-6992759 : Bad code generated for integer <= comparison, fails for Integer.MAX_VALUE
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2010-10-18
  • Updated: 2011-04-18
  • Resolved: 2011-04-18
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
$ java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

On Solaris 10 we used 1.5.0_05-b05.

It also failed on a 6.0 release we tried.

FULL OS VERSION :
$ uname -a
Linux localhost.localdomain 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 i686 i686 i386 GNU/Linux


EXTRA RELEVANT SYSTEM CONFIGURATION :
Also fails on all other platforms we tried:
  - Solaris 10
  - Windows XP

A DESCRIPTION OF THE PROBLEM :
The original problem encountered was that the following expression, when Y is Integer.MAX_VALUE and list.size() is four, was evaluating to true when X is zero but to false when X is one:

         ((X <= Y) && (X < list.size()))

Of course, this should be true for all values of X between zero and three when Y is Integer.MAX_VALUE.  (Perhaps a Hotspot optimization based on the fact that (X <= Integer.MAX_VALUE) is always true is misbehaving.)

Although it was clearly failing in my application I was unable to reproduce the particular case above in a standalone test, but I was able to produce a (hopefully) related problem.  After a number of iterations, giving Hotspot time to compile the code, the following expression is always evaluated to true:

       ((X <= Y) && (X < 10))

Where:
      X varies between 0 and Integer.MAX_VALUE
      Y is Integer.MAX_VALUE

The expression should be only true when X is less than 10.  This is the case when -client is used, but after compilation with -server the expression is always true.  The included test demonstrates this problem.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test included with the java -server option.  It will fail.  Run it with -client and it won't fail.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected result:

No failure

Actual result:

Exception in thread "main" java.lang.RuntimeException: Failed test iteration=9029 max=2147483647 counted=2147483647 expected=10
        at MaxValueBug.doTest(MaxValueBug.java:27)
        at MaxValueBug.main(MaxValueBug.java:14)

ERROR MESSAGES/STACK TRACES THAT OCCUR :
$ javac MaxValueBug.java && java -server -cp . MaxValueBug
Exception in thread "main" java.lang.RuntimeException: Failed test iteration=9029 max=2147483647 counted=2147483647 expected=10
        at MaxValueBug.doTest(MaxValueBug.java:27)
        at MaxValueBug.main(MaxValueBug.java:14)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class MaxValueBug {

    static final int N_TESTS = 1000000000;

    public static void main(String[] args) throws Exception {

        /*
         * If MAX_VALUE is changed to MAX_VALUE - 1 below, the test passes
         * because (apparently) bad code is only generated when comparing
         * <= MAX_VALUE in the doTest method.
         */
        MaxValueBug test = new MaxValueBug();
        for (int i = 0; i < N_TESTS; i += 1) {
            test.doTest(10, Integer.MAX_VALUE, i);
            //test.doTest(10, Integer.MAX_VALUE - 1, i);
        }
        System.out.println("No failure");
    }

    void doTest(int expected, int max, int i) {
        int counted;
        for (counted = 0;
             (counted <= max) && (counted < expected);
             counted += 1) {
        }
        if (counted != expected) {
            throw new RuntimeException("Failed test iteration=" + i +
                                       " max=" + max +
                                       " counted=" + counted +
                                       " expected=" + expected);
        }
    }
}

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

CUSTOMER SUBMITTED WORKAROUND :
The workaround, for the specific case we encountered, is to not use Integer.MAX_VALUE as a maximum value but rather (Integer.MAX_VALUE - 1).  This happens to be acceptable for this one case.  We are, of course, very concerned about this bug in other contexts.

Comments
EVALUATION There are two issues reported here: - the comparison <= MAX_INT is 5091921 - the problem with ((X <= Y) && (X < 10)) may be the same issue manifesting differently As this is a server issue I've reassigned to compiler2 so the compiler folks can comment on whether this is all 5091921 or not. If so it will be closed as a duplicate.
18-10-2010