JDK-6832293 : JIT compiler got wrong result in type checking with -server
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6u12
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-04-21
  • Updated: 2011-03-08
  • Resolved: 2011-03-08
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 Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u18Fixed 7Fixed hs16Fixed
Related Reports
Relates :  
Description
The test case below is based on one jck test case which fails on windows with -server on all version of JDK 6.   I tried to initialize some classes before the "run" method and jit compiler will return the wrong result.

The licensee added a develop-only option in the VM which tries to eagerly initialize a class when compiling a methed. So they can reduce uncommon traps in generated code. Of course some jck cases will fail if the initialize order is important. But in this case, I don't think eagerly initializing a class should cause a problem. So I traced these eagerly initializing class and initialized them in java code. I tested my new case without the develop-only option and it failed again. So I think it's a bug of jit compiler and tested it on windows platform. I tested it against 6u12.  

The test case does not fail on Solaris.

Source code:
/*
 * @(#)conv08301.java	1.8 01/12/07
 *
 * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */




import java.io.PrintStream;


interface SomeInterface {

	int SEVENS = 777;

}


interface AnotherInterface {

	int THIRDS = 33;

}


class SomeClass
implements SomeInterface {

	int i;

	SomeClass(int i) {
		this.i = i;
	}

}


class ImmediateSubclass
extends SomeClass
implements SomeInterface {

	float f;

	ImmediateSubclass(int i, float f) {
		super(i);
		this.f = f;
	}

}


final class FinalSubclass
extends ImmediateSubclass
implements AnotherInterface {

	double d;

 	FinalSubclass(int i, float f, double d) {
		super(i, f);
		this.d = d;
	}

}


public class conv08301 {

	public static void main(String args[]) throws Exception{
		/* try to pre initialize */
		SomeClass[] a=new SomeClass[10];
		Class.forName("ImmediateSubclass");
		Class.forName("FinalSubclass");
		System.exit(run(args, System.out) + 95/*STATUS_TEMP*/); 
	} 
 
	static int errorStatus = 0/*STATUS_PASSED*/;

	static void errorAlert(PrintStream out, int errorLevel) {
		out.println("conv08301: failure #" + errorLevel);
		errorStatus = 2/*STATUS_FAILED*/;
	}

	public static int run(String args[],PrintStream out) { 
		int i [], j [];
		SomeInterface u [], v[] [];
		AnotherInterface w [];
		SomeClass x [] [];

		i = new int [10];
		i[0] = 777;
		j = (int []) i;
		if (j != i)
			errorAlert(out, 2);
		else if (j.length != 10)
			errorAlert(out, 3);
		else if (j[0] != 777)
			errorAlert(out, 4);

		v = new SomeClass [3] [];
		x = (SomeClass [] []) v;
		if (! (x instanceof SomeInterface [] []))
			errorAlert(out, 5);
		else if (! (x instanceof SomeClass [] []))
			errorAlert(out, 6);
		else if (x != v)
			errorAlert(out, 7);

		x[0] = (SomeClass []) new ImmediateSubclass [4];
		if (! (x[0] instanceof ImmediateSubclass []))
			errorAlert(out, 8);
		else if (x[0].length != 4)
			errorAlert(out, 9);

		x[1] = (SomeClass []) new FinalSubclass [4];
		if (! (x[1] instanceof FinalSubclass []))
			errorAlert(out, 10);
		else if (x[1].length != 4)
			errorAlert(out, 11);

		w = (AnotherInterface []) x[1];
		if (! (w instanceof FinalSubclass []))
			errorAlert(out, 12);
		else if (w != x[1])
			errorAlert(out, 13);
		else if (w.length != 4)
			errorAlert(out, 14);

		return errorStatus;
	}

}

Steps to reproduce it (only reproduces on Windows)
JDK Version on Windows:  1.6.0_12
OS: Windows XP Professional
CPU: Intel Pentium M


> javac conv08301.java
> java -server conv08301
> java -server -Xcomp conv08301

Comments
PUBLIC COMMENTS Problem: The code in CmpPNode::sub is broken for arrays of interface types. Solution: Check for an object array of interface type.
12-05-2009

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/a9e116455022
12-05-2009

EVALUATION The code in CmpPNode::sub is broken for arrays of interface types. You can make a test that fails in 1.7 by replacing this line: x[1] = (SomeClass []) new FinalSubclass [4]; with this: x[1] = (SomeClass []) v2; where: static SomeClass[] v2 = new FinalSubclass[4]; Otherwise C2 is able to see precise types from the previous store and correctly statically fold the checks. If you hide it in a static then we get into the CmpPNode::sub code. The code in CmpPNode::sub either needs to restrict itself to TypeInstPtr or it needs to deal with the covariant subtyping of arrays properly. *** (#1 of 1): [ UNSAVED ] ###@###.###
06-05-2009