Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6853701
Votes 2
Synopsis Scalar replacement (escape analysis) fails for simple test case
Category hotspot:compiler2
Reported Against
Release Fixed
State 5-Cause Known, bug
Priority: 4-Low
Related Bugs
Submit Date 22-JUN-2009
Description
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  customer  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  customer  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 ----------
Posted Date : 2009-06-22 19:45:37.0
Work Around
N/A
Evaluation
The test case shows limitation of the current EA implementation.
Objects will not be eliminated if there is merge point in which it is undefined which object is referenced.
In escapeAnalysisFails() there are references to object fields after the loop and an object could be eigther
the one created before loop (when passed count==0) or one created inside loop (result of madd() )

	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");
	}
Posted Date : 2009-07-24 22:02:43.0
Comments
  
  Include a link with my name & email   


PLEASE NOTE: JDK6 is formerly known as Project Mustang