Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6357214

Hotspot server compiler gets integer comparison wrong

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0, 6u6
    • hotspot
    • x86, sparc
    • linux, solaris_10

      FULL PRODUCT VERSION :
      java version "1.5.0_05"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
      Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode)

      1.5.0_05, also 1.4.2_10 and 1.3.1_16.

      FULL OS VERSION :
      Solaris 10

      A DESCRIPTION OF THE PROBLEM :
      In the example code, the test "if (i>limit) {" in method create() gives the wrong result. It indicates that i > limit when i is zero and limit is Integer.MAX_VALUE.

      Look

      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the attached demo code as

      javac SCPF.java

      Then run as

      java -server -DshowAll=ffo -DeventID=444 SCPF



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      SHOULD DO:
      The test should run forever printing out line after line

      DOES:
      The test stops after a couple of iterations. If you run with -Xint the test runs as expected.

      The problem appears to be with the way the optimizer chooses to rewrite the test. In this case, the value of limit is going to be Integer.MAX_VALUE.

      Looking at the generated SPARC code, the test has been re-written as:

      if ((i+1) >= (limit+2))

      And (limit+2) is calculated in advance by the simple expedient of adding 2 to Integer.MAX_VALUE. This produces the value 0x80000001, which of course is a big negative number, so the test

      if (0 > 0x7FFFFFFF)

      comes out TRUE!
      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      class MyResult {
              public boolean next() {
                      return true;
              }

              public String getString(String in) {
                      if (in.equals("id"))
                              return "idFoo";
                      if (in.equals("contentKey"))
                              return "ckFoo";
                      return "Foo";
              }

              public int getInt(String in) {
                      if (in.equals("processingComplete"))
                              return 0;
                      return 1;
              }

              public byte[] getBytes(String in) {
                      byte[] arr = null;
                      if (in.equals("content")) {
                              arr = new byte[65536];
                              byte j = 32;
                              for (int i=0; i<65536; i++) {
                                      arr[i] = j;
                                      if (++j == 127)
                                              j=32;
                              }
                      }
                      return arr;
              }
      }

      public class SCPF {
              public static volatile boolean bollocks = true;
          public String create(String context) throws Exception {

              //
              // Extract HTTP parameters
              //

              boolean showAll = System.getProperty("showAll") != null;
                String eventID = System.getProperty("eventID");
                String eventContentKey = System.getProperty("cKey");
              //
              // Build ContentStaging query based on eventID or eventContentKey
              //

              String sql = "select id, processingComplete, contentKey, content "
                         + "from ContentStaging cs, ContentStagingKey csk "
                         + "where cs.eventContentKey = csk.eventContentKey ";

              if (eventID != null) {
                  sql += "and id = " + eventID;
              }
              else if (eventContentKey != null) {
                  sql += "and cs.eventContentKey = '"
                      + eventContentKey
                      + "' having id = max(id)";
              }
              else {
                  throw new Exception("Need eventID or eventContentKey");
              }

              //
              // This factory builds a static panel, there is no JSP
              //

              StringBuffer html = new StringBuffer();

              try {

                      MyResult result = new MyResult();
                  if (result.next()) {

                      eventID = result.getString("id");
                      int processingComplete = result.getInt("processingComplete");
                      String contentKey = result.getString("contentKey");
                      byte[] bytes = result.getBytes("content");

                      //
                      // Print content status and associated controls
                      //

                      html.append("<br/><font class=\"small\">");
                      html.append("Status: ");
                      switch (processingComplete) {
                          case 0 :
                          case 1 : html.append("PENDING"); break;
                          case 2 : html.append(contentKey); break;
                          case 3 : html.append(eventID); break;
                          default : html.append("UNKNONW");
                      }
                      html.append("</font><br/>");

                      //
                      // Print at most 20Kb of content unless "showAll" is set
                      //

                      int limit = showAll ? Integer.MAX_VALUE : 1024 * 20;
                      System.out.println(limit);
                      html.append("<pre>");
                      for (int i = 0; bytes != null && i < bytes.length; i++) {
                          char c = (char) bytes[i];
                          switch (c) {
                              case '<' : html.append("&lt;"); break;
                              case '>' : html.append("&gt;"); break;
                              case '&' : html.append("&amp;"); break;
                              default : html.append(c);
                          }

                          if (i > limit) {
                              while (bollocks);
                              // System.out.println("i is " + i);
                              // System.out.println("limit is " + limit);
                              html.append("...\n</pre>");
                              html.append(eventID);
                              html.append("<pre>");
                              break;
                          }
                      }
                      html.append("</pre>");
                  }
              }
              catch (Exception exception) {
                  throw exception;
              }
              finally {
                  html.append("Oof!!");
              }
              String ret = html.toString();
              System.out.println("Returning string length = "+ ret.length());
              return ret;
          }

          public static void main(String[] args) throws Exception {
                      int length=0;

                      while (true) {
                              length = new SCPF().create("boo").length();
                              System.out.println(length);
                      }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Tweak the code to work around the dodgy optimizer

            cfang Changpeng Fang (Inactive)
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: