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

Scalar replacement (escape analysis) fails for simple test case

XMLWordPrintable

    • Cause Known
    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.6.0_14-ea"
      Java(TM) SE Runtime Environment (build 1.6.0_14-ea-b06)
      Java HotSpot(TM) 64-Bit Server VM (build 14.0-b15, mixed mode)

      "java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b59)
      Java HotSpot(TM) 64-Bit Server VM (build 16.0-b03, mixed mode)


      FULL OS VERSION :
      Linux 2.6.28-13-generic #44-Ubuntu SMP Tue Jun 2 07:55:09 UTC 2009 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      Scalar replacement doesn't work for a situation in which the object reference clearly doesn't escape.
      Please take a look at the attached test case.
      If you run the test case as pasted below with "java -Xmx64M -server -verbose:gc -XX:+DoEscapeAnalysis Vector3Test" you'll find the following:
      The methods escapeAnalysisWorks and escapeAnalysisFails perform the same (silly) computation and print the same output.
      There's at most one gc log messages for the escapeAnalysisWorks.
      There are tons of gc log messages for the escapeAnalysisFails.
      The performance (if this can be concluded from such a microbenchmark) for escapeAnalysisWorks is much better due to scalar replacement.

      It seems as if escape analysis incorrectly assumes that result object reference escapes from escapeAnalysisFails (which is only true for the basic block containing the for-loop, but not for the escapeAnalysisFails method).

      THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No

      THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Vector3Test {

      public static class Vector3 {
      public double x,y,z;

      public Vector3(double x, double y, double z) {
      this.x = x;
      this.y = y;
      this.z = z;
      }

      public Vector3 madd(double val, Vector3 other) {
      return new Vector3(val*other.x+x,val*other.y+y,val*other.z+z);
      }
      }

      public static void main(String[] args) {
      System.out.println("Escape analysis works");
      escapeAnalysisWorks(10000);
      escapeAnalysisWorks(1000000);
      escapeAnalysisWorks(10000000);
      System.out.println("Escape analysis doesn't work");
      escapeAnalysisFails(10000);
      escapeAnalysisFails(1000000);
      escapeAnalysisFails(10000000);
      }

      public static void escapeAnalysisWorks(int count) {
      System.out.println("starting test where escape analysis works");
      long t1 = System.nanoTime();
      double x = 0;
      double y = 0;
      double z = 0;

      for (int i=0;i<count;i++)
      {
      Vector3 last = new Vector3(x,y,z);
      Vector3 result = last.madd(i / (double)count, new Vector3(i/(double)count,1.0-1/(double)count,1.0-1/(double)count));
      x = result.x;
      y = result.y;
      z = result.z;
      }
      long t2 = System.nanoTime();
      System.out.format("result = %f,%f,%f\n", x, y, z);
      System.out.println("duration: "+(t2-t1)/1000.0/1000.0+" msecs\n");
      }

      public static void escapeAnalysisFails(int count) {
      System.out.println("starting test where escape analysis fails");
      long t1 = System.nanoTime();
      Vector3 result = new Vector3(0,0,0);
      for (int i=0;i<count;i++)
      {
      result = result.madd(i / (double)count, new Vector3(i/(double)count,1.0-1/(double)count,1.0-1/(double)count));
      }
      long t2 = System.nanoTime();
      System.out.format("result = %f,%f,%f\n", result.x, result.y, result.z);
      System.out.println("duration: "+(t2-t1)/1000.0/1000.0+" msecs\n");
      }
      }

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

            kvn Vladimir Kozlov
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: