JDK-6833879 : Assigning positive zero is ignored when old value is negative zero
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6u13
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_nevada
  • CPU: x86
  • Submitted: 2009-04-24
  • 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
Description
In Apache Derby there is some code that performs normalization of floating point values. The results from this normalization tend to vary, although I believe the results should be well-defined. The code is essentially like this:

// turn negative zero into positive zero
if (v == 0.0f)
    v = 0.0f;
return v;

Since (-0.0f == 0.0f) evaluates to true per the language specification, v should be assigned the value 0.0f (positive zero) if the original value of v is 0.0f or -0.0f (negative zero). Hence, negative zero should never be returned by this code. However, it sometimes does return negative zero.

It looks like this happens when the runtime optimizer has kicked in. It probably thinks the if statement is without side-effects and optimizes it away.

To reproduce, compile and run this Java class:

public class Normalize {

    public static void main(String[] args) {
        System.out.println("normalize(-0.0f): " + normalize(-0.0f));
        for (int i = 0; i < 1000000; i++) {
            normalize(-0.0f);
        }
        System.out.println("normalize(-0.0f): " + normalize(-0.0f));
    }

    public static float normalize(float v) {
        if (v == 0.0f) v = 0.0f;
        return v;
    }
}

When I run this code with the server VM, I get this output most of the time:

$ java -server Normalize
normalize(-0.0f): 0.0
normalize(-0.0f): -0.0

That is, the first time normalize(-0.0f) is called, it returns positive zero as expected. The last time normalize(-0.0f) is called, it returns negative zero.

Occationally with the server VM, and every time with the client VM or with -Xint, I see this output (which is what I expect to see):

$ java -client Normalize 
normalize(-0.0f): 0.0
normalize(-0.0f): 0.0

Comments
EVALUATION Approved for JDK 7 M3 build 3.
07-05-2009

PUBLIC COMMENTS Another, perhaps faster, idiom to get rid of negative zero is just v = v + 0.0f; If v is -0.0, -0.0 + (+0.0) results in (+)0.0 and other values are unchanged by the addition.
06-05-2009

EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/36ee9b69616e
06-05-2009