JDK-6539464 : Math.log() produces inconsistent results between successive runs.
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: hs15,6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,solaris_8
  • CPU: generic,x86
  • Submitted: 2007-03-27
  • Updated: 2020-07-15
  • Resolved: 2011-03-07
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
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux hssa1.aoa.twosigma.com 2.6.18-ts1 #1 SMP PREEMPT Fri Sep 29 14:06:04 GMT 2006 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
successive invocations of Math.log() produce inconsistent results (possibly depending on compilation because -Xint or -XX:CompleThreshold=0 always produces consistent results). The number of iterations in the actual result varies.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ javac LogTest.java
$ java -cp . LogTest

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
n=17197.0
SUCCESS!
ACTUAL -
n=17197.0
ERROR after 43235 iterations:
previous value: 9.7524902289842 (40238146663817e8)
 current value: 9.752490228984199 (40238146663817e7)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class LogTest {

    public static void main(String[] args)
    {
        double n = Integer.parseInt("17197");
        System.out.println("n=" + n);
        double d = Math.log(n);
        for (int i = 0; i < 100000; i++) {
            double e = Math.log(n);
            if (e != d) {
                System.err.println("ERROR after " + i + " iterations:\n" +
                   "previous value: " + d + " (" +
                   Long.toHexString(Double.doubleToLongBits(d)) + ")\n" +
                   " current value: " + e + " (" +
                   Long.toHexString(Double.doubleToLongBits(e)) + ")");
                System.exit(1);
            }
        }
        System.err.println("SUCCESS!");
        System.exit(0);
    }
}

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

CUSTOMER SUBMITTED WORKAROUND :
run with -Xint -XXCompilerThreshold=0 produces the expected result, on the other hand, is that a complete fix? Are floating point results reliable?

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/819880572f09
06-04-2009

SUGGESTED FIX diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1393,12 +1393,13 @@ address AbstractInterpreterGenerator::ge case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break; case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break; case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break; - case Interpreter::java_lang_math_sin : break; - case Interpreter::java_lang_math_cos : break; - case Interpreter::java_lang_math_tan : break; - case Interpreter::java_lang_math_abs : break; - case Interpreter::java_lang_math_log : break; - case Interpreter::java_lang_math_log10 : break; + + case Interpreter::java_lang_math_sin : // fall thru + case Interpreter::java_lang_math_cos : // fall thru + case Interpreter::java_lang_math_tan : // fall thru + case Interpreter::java_lang_math_abs : // fall thru + case Interpreter::java_lang_math_log : // fall thru + case Interpreter::java_lang_math_log10 : // fall thru case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break; default : ShouldNotReachHere(); break; }
26-03-2009

EVALUATION The interpreter is using the C implementation and compiled code is using the log instructions on x86 but the interpreter and compiler are required to use the same implementation so that Math.log is self consistent. The amd64 interpreter has the code to use the x86 instruction but some code in AbstractInterpreterGenerator::generate_method_entry keep it from getting used.
26-03-2009

EVALUATION Should be investigated.
03-04-2007