Maintenance Notice

The bugs.java.com site will be undergoing maintenance on 15th Dec 2017 21:00 PST to 16th Dec 2017 1:00 AM PST.
JDK-6853701 : Scalar replacement (escape analysis) fails for simple test case
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9,10
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2009-06-22
  • Updated: 2017-04-11
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 Availabitlity Release.

To download the current JDK release, click here.
JDK 13
13Unresolved
Related Reports
Relates :  
Relates :  
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 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 ----------

Comments
We may still need to optimize this case in C2 EA since it may help Value Types project.
2017-03-10

Thank you for the clarification. I was confused by your comment "Should be fixed as part of 8012974 changes.".
2017-03-08

JDK-8012974 is about boxing objects optimization. This RFE is for general EA issue with objects in loops.
2017-03-07

Hi Vladimir [~kvn], can I close this issue as a duplicate of JDK-8012974? Thank you! Zoltan
2017-03-07

Should be fixed as part of 8012974 changes.
2014-01-21

It is still the issue but definitely not for jdk7. Assigning back to me.
2014-01-20

Not critical for JDK7 or earlier. Moving to tbd_minor for future investigation by Dev team. Maybe this is no longer an issue
2014-01-20

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"); }
2009-07-24