-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
1.2.0
-
generic
-
solaris_2.5.1
Name: dkC59003 Date: 11/26/98
JDK 1.2-fcsU / JIT produces incorrect result in some double
calculation under solaris/sparc and under solaris/x86,
if the calculation exploits rather deep method's stack.
Displayed below test program checks double convolution:
S = A[N-1]*B[N-1] + (... + (A[0]*B[0] + probe) ...)
intentionally using deep method's stack.
Vectors A[N],B[N] are generated especially to reveal
rounding errors, such as fused rounding, or using incorrectly
extended floating-point format to store intermediate results.
Similar test programs using the same values for A[N],B[N]
passes correctly, when calculating in low stack's depth.
This program uses two ways to trace intermediate sums:
1) partial sums are stored into C[n] for each n=0,...,N-1,
when calculating in deep stack, and
2) expected partial sums E[n] are calculated in low stack depth.
Here are calculation results:
-------- Solaris 5.5.1 / UltraSparc-1:
E[0]=1.1258999068426246E16 C[0]=1.1258999068426246E16
E[1]=2.0 C[1]=2.0
E[2]=1.1258999068426246E16 C[2]=1.1258999068426246E16
E[3]=2.0 C[3]=2.0
E[4]=1.1258999068426246E16 C[4]=4.0
E[5]=2.0 C[5]=8.0
E[6]=1.1258999068426246E16 C[6]=16.0
E[7]=2.0 C[7]=32.0
E[8]=1.1258999068426246E16 C[8]=64.0
E[9]=2.0 C[9]=128.0
E[10]=1.1258999068426246E16 C[10]=256.0
E[11]=2.0 C[11]=512.0
E[12]=1.1258999068426246E16 C[12]=1024.0
E[13]=2.0 C[13]=2048.0
E[14]=1.1258999068426246E16 C[14]=4096.0
E[15]=2.0 C[15]=8192.0
E[16]=1.1258999068426246E16 C[16]=16384.0
E[17]=2.0 C[17]=32768.0
E[18]=1.1258999068426246E16 C[18]=65536.0
E[19]=2.0 C[19]=131072.0
E[20]=1.1258999068426246E16 C[20]=262144.0
E[21]=2.0 C[21]=524288.0
Convolution failed: double result:
S = 524288.0 = Double.longBitsToDouble(0x4120000000000000L)
[ instead of the expected probe = 2.0 ]
-------- Solaris 5.5.1 / Pentium-II:
E[0]=1.1258999068426246E16 C[0]=NaN
E[1]=2.0 C[1]=NaN
E[2]=1.1258999068426246E16 C[2]=NaN
E[3]=2.0 C[3]=NaN
E[4]=1.1258999068426246E16 C[4]=NaN
E[5]=2.0 C[5]=NaN
E[6]=1.1258999068426246E16 C[6]=NaN
E[7]=2.0 C[7]=NaN
E[8]=1.1258999068426246E16 C[8]=NaN
E[9]=2.0 C[9]=NaN
E[10]=1.1258999068426246E16 C[10]=NaN
E[11]=2.0 C[11]=NaN
E[12]=1.1258999068426246E16 C[12]=NaN
E[13]=2.0 C[13]=NaN
E[14]=1.1258999068426246E16 C[14]=NaN
E[15]=2.0 C[15]=NaN
E[16]=1.1258999068426246E16 C[16]=NaN
E[17]=2.0 C[17]=NaN
E[18]=1.1258999068426246E16 C[18]=NaN
E[19]=2.0 C[19]=NaN
E[20]=1.1258999068426246E16 C[20]=NaN
E[21]=2.0 C[21]=NaN
Convolution failed: double result:
S = NaN = Double.longBitsToDouble(0x7ff8000000000000L)
[ instead of the expected probe = 2.0 ]
-------- Windows-NT 4.0 / Pentium-II:
E[0]=1.1258999068426246E16 C[0]=1.1258999068426246E16
E[1]=2.0 C[1]=2.0
E[2]=1.1258999068426246E16 C[2]=1.1258999068426246E16
E[3]=2.0 C[3]=2.0
E[4]=1.1258999068426246E16 C[4]=1.1258999068426246E16
E[5]=2.0 C[5]=2.0
E[6]=1.1258999068426246E16 C[6]=1.1258999068426246E16
E[7]=2.0 C[7]=2.0
E[8]=1.1258999068426246E16 C[8]=1.1258999068426246E16
E[9]=2.0 C[9]=2.0
E[10]=1.1258999068426246E16 C[10]=1.1258999068426246E16
E[11]=2.0 C[11]=2.0
E[12]=1.1258999068426246E16 C[12]=1.1258999068426246E16
E[13]=2.0 C[13]=2.0
E[14]=1.1258999068426246E16 C[14]=1.1258999068426246E16
E[15]=2.0 C[15]=2.0
E[16]=1.1258999068426246E16 C[16]=1.1258999068426246E16
E[17]=2.0 C[17]=2.0
E[18]=1.1258999068426246E16 C[18]=1.1258999068426246E16
E[19]=2.0 C[19]=2.0
E[20]=1.1258999068426246E16 C[20]=1.1258999068426246E16
E[21]=2.0 C[21]=2.0
--------
Both solaris/sparc and solaris/x86 results are obviously incorrect
(and pentium/win32 results are correctly equal to the expeccted).
Errors only arise (under solaris sparc or x86) when JIT is on;
there is no error when JIT is off.
The problem seems to appear in JDK 1.2beta;
earlier JDK 1.0.2, and 1.1.x pass the test.
This bug is revealed by JCK-1.2b tests:
vm/fp/fpm035/fpm03503m2/fpm03503m2.html
vm/fp/fpm035/fpm03503m4/fpm03503m4.html
vm/fp/fpm035/fpm03503m6/fpm03503m6.html
Full sources of the test program consist of the following two files:
-------- fpm03503m2a_bug.jasm:
/* Ident: @(#)fpm03503m2a.jasm generated from: @(#)fpm03503m.jmpp 1.1 98/11/12 */
/* Copyright 25.11.98 Sun Microsystems, Inc. All Rights Reserved */
// package javasoft/sqe/tests/vm/fp/fpm035/fpm03503m2;
super class fpm03503m2a_bug
{
static final Field N:I = int 22;
Method "<init>":"()V"
stack 1 locals 1
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()V";
return;
}
//
// static double convolution (double probe, double A[], double B[]) {
// double S = probe;
// for (int n=0; n<N; n++)
// S += A[n]*B[n];
// return S;
// };
//
static strict Method convolution:"(D[D[D[D)D"
stack 92 locals 7
{
aload_3;
sipush 21;
daload; // stack <-- A[21]
aload_2;
sipush 21;
daload; // stack <-- B[21]
aload_3;
sipush 20;
daload; // stack <-- A[20]
aload_2;
sipush 20;
daload; // stack <-- B[20]
aload_3;
sipush 19;
daload; // stack <-- A[19]
aload_2;
sipush 19;
daload; // stack <-- B[19]
aload_3;
sipush 18;
daload; // stack <-- A[18]
aload_2;
sipush 18;
daload; // stack <-- B[18]
aload_3;
sipush 17;
daload; // stack <-- A[17]
aload_2;
sipush 17;
daload; // stack <-- B[17]
aload_3;
sipush 16;
daload; // stack <-- A[16]
aload_2;
sipush 16;
daload; // stack <-- B[16]
aload_3;
sipush 15;
daload; // stack <-- A[15]
aload_2;
sipush 15;
daload; // stack <-- B[15]
aload_3;
sipush 14;
daload; // stack <-- A[14]
aload_2;
sipush 14;
daload; // stack <-- B[14]
aload_3;
sipush 13;
daload; // stack <-- A[13]
aload_2;
sipush 13;
daload; // stack <-- B[13]
aload_3;
sipush 12;
daload; // stack <-- A[12]
aload_2;
sipush 12;
daload; // stack <-- B[12]
aload_3;
sipush 11;
daload; // stack <-- A[11]
aload_2;
sipush 11;
daload; // stack <-- B[11]
aload_3;
sipush 10;
daload; // stack <-- A[10]
aload_2;
sipush 10;
daload; // stack <-- B[10]
aload_3;
sipush 9;
daload; // stack <-- A[9]
aload_2;
sipush 9;
daload; // stack <-- B[9]
aload_3;
sipush 8;
daload; // stack <-- A[8]
aload_2;
sipush 8;
daload; // stack <-- B[8]
aload_3;
sipush 7;
daload; // stack <-- A[7]
aload_2;
sipush 7;
daload; // stack <-- B[7]
aload_3;
sipush 6;
daload; // stack <-- A[6]
aload_2;
sipush 6;
daload; // stack <-- B[6]
aload_3;
sipush 5;
daload; // stack <-- A[5]
aload_2;
sipush 5;
daload; // stack <-- B[5]
aload_3;
sipush 4;
daload; // stack <-- A[4]
aload_2;
sipush 4;
daload; // stack <-- B[4]
aload_3;
sipush 3;
daload; // stack <-- A[3]
aload_2;
sipush 3;
daload; // stack <-- B[3]
aload_3;
sipush 2;
daload; // stack <-- A[2]
aload_2;
sipush 2;
daload; // stack <-- B[2]
aload_3;
sipush 1;
daload; // stack <-- A[1]
aload_2;
sipush 1;
daload; // stack <-- B[1]
aload_3;
sipush 0;
daload; // stack <-- A[0]
aload_2;
sipush 0;
daload; // stack <-- B[0]
dload_0; // S:=probe, and let S be on stack's top
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[0]*B[0]
dup2;
dstore 5;
aload 4;
sipush 0;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[1]*B[1]
dup2;
dstore 5;
aload 4;
sipush 1;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[2]*B[2]
dup2;
dstore 5;
aload 4;
sipush 2;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[3]*B[3]
dup2;
dstore 5;
aload 4;
sipush 3;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[4]*B[4]
dup2;
dstore 5;
aload 4;
sipush 4;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[5]*B[5]
dup2;
dstore 5;
aload 4;
sipush 5;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[6]*B[6]
dup2;
dstore 5;
aload 4;
sipush 6;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[7]*B[7]
dup2;
dstore 5;
aload 4;
sipush 7;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[8]*B[8]
dup2;
dstore 5;
aload 4;
sipush 8;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[9]*B[9]
dup2;
dstore 5;
aload 4;
sipush 9;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[10]*B[10]
dup2;
dstore 5;
aload 4;
sipush 10;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[11]*B[11]
dup2;
dstore 5;
aload 4;
sipush 11;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[12]*B[12]
dup2;
dstore 5;
aload 4;
sipush 12;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[13]*B[13]
dup2;
dstore 5;
aload 4;
sipush 13;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[14]*B[14]
dup2;
dstore 5;
aload 4;
sipush 14;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[15]*B[15]
dup2;
dstore 5;
aload 4;
sipush 15;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[16]*B[16]
dup2;
dstore 5;
aload 4;
sipush 16;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[17]*B[17]
dup2;
dstore 5;
aload 4;
sipush 17;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[18]*B[18]
dup2;
dstore 5;
aload 4;
sipush 18;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[19]*B[19]
dup2;
dstore 5;
aload 4;
sipush 19;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[20]*B[20]
dup2;
dstore 5;
aload 4;
sipush 20;
dload 5;
dastore;
dup2_x2;
pop2;
dstore 5;
dup2_x2;
pop2;
dload 5;
dmul;
dadd; // S += A[21]*B[21]
dup2;
dstore 5;
aload 4;
sipush 21;
dload 5;
dastore;
dreturn;
}
} // end class fpm03503m2a
-------- fpm03503m2_bug.java:
/* Ident: @(#)fpm03503m2.java generated from: @(#)fpm03503m.jmpp 1.1 98/11/12 */
/* Copyright 25.11.98 Sun Microsystems, Inc. All Rights Reserved */
// package javasoft.sqe.tests.vm.fp.fpm035.fpm03503m2;
import java.io.PrintStream;
public class fpm03503m2_bug {
public static void main (String args[]) {
System.exit(run(args, System.out) + 95/*STATUS_TEMP*/);
};
public static int run (String args[], PrintStream out) {
final int N = 22; // it is essential, that N is even and N/2 is odd
double A[] = new double [ N ];
double B[] = new double [ N ];
double C[] = new double [ N ];
for (int n=0; n<N; n++)
if (n%2 == 0) {
A[n] = (double) 0x8000000000001L;
B[n] = (double) 0x5L;
} else {
A[n] = (double) 0xa000000000001L;
B[n] = - (double) 0x4L;
};
final double probe = 2;
double S = fpm03503m2a_bug.convolution(probe,A,B,C);
out.println("");
double E=probe;
for (int n=0; n<N; n++) {
E += A[n]*B[n];
out.println("E["+n+"]="+E + "\tC["+n+"]="+C[n]);
};
if (S == probe)
return 0/*STATUS_PASSED*/;
out.println("\nConvolution failed: double result:");
out.println("S = " + S + " = " +
"Double.longBitsToDouble(0x" +
Long.toHexString(Double.doubleToLongBits(S)) + "L)");
out.println("[ instead of the expected probe = " + probe + " ]");
if (S == probe+N/2)
out.println("double mantissa is probably wider than standard.");
else if (S == 2*probe)
out.println("rounding of intermediate results is probably ommited.");
out.println("");
return 2/*STATUS_FAILED*/;
};
}
--------
======================================================================