JDK-6213988 : Change in behavior of Math.log() with intrinsified version
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: x86
  • Submitted: 2005-01-04
  • Updated: 2011-09-15
  • Resolved: 2005-01-19
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
6 b20Fixed
Related Reports
Relates :  
Relates :  
Description
Rob Nugent on the javagaming.org forums has posted a small test case illustrating a change in behavior with the intrinsified version of Math.log() on x86 CPUs. Test case:

public class Test {
  public static void main(String[] args) {
    int w = 64;
    int levels = (int)(Math.log(w) / Math.log(2.0)) + 1;
    System.out.println("Width " + w + " gives " +
      levels + " mipmap levels");
  }
}

This produces an answer of 7 on JDK releases 1.5 and earlier and an answer of 6 on the current x86 builds of 1.6 with most configurations (-client -Xcomp seems to work, but -client -Xint and -server -Xint do not). It is not clear whether this change in behavior should be considered a bug due to the specification guarantees of Math.log(), but it should be investigated.

Relevant thread:
http://www.javagaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=jogl;action=display;num=1103796449;start=30#30

###@###.### 2005-1-04 22:35:29 GMT

Comments
SUGGESTED FIX --- subnode.hpp Thu Jan 6 10:09:43 2005 *************** *** 1,7 **** #ifdef USE_PRAGMA_IDENT_HDR ! #pragma ident "@(#)subnode.hpp 1.71 04/09/08 16:48:56 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ --- 1,7 ---- #ifdef USE_PRAGMA_IDENT_HDR ! #pragma ident "@(#)subnode.hpp 1.72 05/01/06 10:09:43 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ *************** *** 408,428 **** //------------------------------LogDNode--------------------------------------- // Log_e of a double class LogDNode : public Node { public: ! LogDNode( Node *c, Node *in1 ) : Node(c, in1) {} virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } }; //------------------------------Log10DNode--------------------------------------- // Log_10 of a double class Log10DNode : public Node { public: ! Log10DNode( Node *c, Node *in1 ) : Node(c, in1) {} virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } }; --- 408,428 ---- //------------------------------LogDNode--------------------------------------- // Log_e of a double class LogDNode : public Node { public: ! LogDNode( Node *in1 ) : Node(0, in1) {} virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } }; //------------------------------Log10DNode--------------------------------------- // Log_10 of a double class Log10DNode : public Node { public: ! Log10DNode( Node *in1 ) : Node(0, in1) {} virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } }; --- library_call.cpp Thu Jan 6 10:09:44 2005 *************** *** 1,7 **** #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)library_call.cpp 1.125 04/12/07 14:02:25 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ --- 1,7 ---- #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)library_call.cpp 1.126 05/01/06 10:09:43 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ *************** *** 899,919 **** //------------------------------inline_trans------------------------------------- // Inline transcendental instructions, if possible. The Intel hardware gets // these right, no funny corner cases missed. bool LibraryCallKit::inline_trans( vmIntrinsics::ID id ) { _sp += arg_size(); // restore stack pointer switch (id) { case vmIntrinsics::_dlog: ! push_pair(_gvn.transform(new (2) LogDNode(0,pop_math_arg()))); break; case vmIntrinsics::_dlog10: ! push_pair(_gvn.transform(new (2) Log10DNode(0,pop_math_arg()))); break; default: assert(false, "bad intrinsic was passed in"); return false; } return true; } //------------------------------runtime_math----------------------------- bool LibraryCallKit::runtime_math(address funcAddr, const char* funcName) { --- 899,925 ---- //------------------------------inline_trans------------------------------------- // Inline transcendental instructions, if possible. The Intel hardware gets // these right, no funny corner cases missed. bool LibraryCallKit::inline_trans( vmIntrinsics::ID id ) { _sp += arg_size(); // restore stack pointer + Node* arg = pop_math_arg(); + Node* trans = NULL; + switch (id) { case vmIntrinsics::_dlog: ! trans = _gvn.transform((Node*)new (2) LogDNode(arg)); break; case vmIntrinsics::_dlog10: ! trans = _gvn.transform((Node*)new (2) Log10DNode(arg)); break; default: assert(false, "bad intrinsic was passed in"); return false; } + + // Push result back on JVM stack + push_pair(trans); return true; } //------------------------------runtime_math----------------------------- bool LibraryCallKit::runtime_math(address funcAddr, const char* funcName) { --- interpreter_i486.cpp Thu Jan 6 10:09:45 2005 *************** *** 1,7 **** #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)interpreter_i486.cpp 1.330 04/12/07 14:02:36 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ --- 1,7 ---- #ifdef USE_PRAGMA_IDENT_SRC ! #pragma ident "@(#)interpreter_i486.cpp 1.331 05/01/06 10:09:44 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ *************** *** 614,626 **** --- 614,630 ---- case Interpreter::java_lang_math_abs: __ fabs(); break; case Interpreter::java_lang_math_log: __ flog(); + __ push_fTOS(); + __ pop_fTOS(); break; case Interpreter::java_lang_math_log10: __ flog10(); + __ push_fTOS(); + __ pop_fTOS(); break; default : ShouldNotReachHere(); } ###@###.### 2005-1-06 18:30:39 GMT
06-01-2005

EVALUATION The first log call was setting the fpu stack in 80bit mode, the second log call was being done with extended range which gave incorrect results. Added a push and pop to revert the fpu stack back to 64bit mode ###@###.### 2005-1-06 18:23:04 GMT
06-01-2005