RFR 8158039 VarHandle float/double field/array access should support CAS/set/add atomics

Paul Sandoz paul.sandoz at oracle.com
Thu Jun 2 15:25:48 UTC 2016


> On 2 Jun 2016, at 14:55, Vladimir Ivanov <vladimir.x.ivanov at oracle.com> wrote:
> 
> Paul,
> 
> Leaving practicality aspect of float/double API aside...
> 
>> I am concerned that the CAS loops could in some cases loop without termination:
> 
> Can you elaborate? I don't see how it is possible with the proposed patch.
> 

The key aspect is in the JavaDoc snippet  in my previous email.

> On Float.intBitsToFloat:
> 
> * <p>Note that this method may not be able to return a
> * {@code float} NaN with exactly same bit pattern as the
> * {@code int} argument.  IEEE 754 distinguishes between two
> * kinds of NaNs, quiet NaNs and <i>signaling NaNs</i>.  The
> * differences between the two kinds of NaN are generally not
> * visible in Java.  Arithmetic operations on signaling NaNs turn
> * them into quiet NaNs with a different, but often similar, bit
> * pattern.  However, on some processors merely copying a
> * signaling NaN also performs that conversion.  In particular,
> * copying a signaling NaN to return it to the calling method may
> * perform this conversion.  So {@code intBitsToFloat} may
> * not be able to return a {@code float} with a signaling NaN
> * bit pattern.  Consequently, for some {@code int} values,
> * {@code floatToRawIntBits(intBitsToFloat(start))} may
> * <i>not</i> equal {@code start}.  Moreover, which
> * particular bit patterns represent signaling NaNs is platform
> * dependent; although all NaN bit patterns, quiet or signaling,
> * must be in the NaN range identified above.
> 

I dunno if it can happen on x86 [*], but from reading the above I presume it could theoretically happen on some other hardware (what exactly i do not know).

Note that the loaded float value is passed to the weakCompareAndSwapFloatVolatile method as an argument. IIUC that might trigger the conversion from a signalling NaN to a quiet NaN, subtly changing the bits of the expected value that was loaded.

Paul.

[*] Here is a simple program to induce a different on x86 (at least on my machine). To induce that i am adding 0.0f to the float value.

public class AllTheNaNs {

    public static void main(String[] args) {
        for (long bits = 0x7f800001; bits <= 0x7fffffff; bits++) {
            testBits((int) bits);
        }
        for (long bits = 0xff800001; bits <= 0xffffffff; bits++) {
            testBits((int) bits);
        }
    }

    static void testBits(int vbits) {
        float v = Float.intBitsToFloat(vbits);
        assert Float.isNaN(v);

        float vv = id(v);
        assert Float.isNaN(vv);

        int vvbits = Float.floatToRawIntBits(vv);
        if (vvbits != vbits) {
            System.out.println(Integer.toHexString(vbits) + " " +
                               Integer.toHexString(vvbits) + " " +
                               Float.valueOf(v).equals(Float.valueOf(vv)) + " " +
                               Float.compare(v, vv));
        }
    }

    static float id(float f) {
        return f + 0.0f;
    }
}




> Unless getFloatVolatile() or weakCompareAndSwapFloatVolatile() change the original value, it should not happen. And both functions preserve float value bits intact:
> 
> +    @ForceInline
> +    public final boolean weakCompareAndSwapFloatVolatile(Object o, long offset,
> +                                                       float expected,
> +                                                       float x) {
> +        return weakCompareAndSwapIntVolatile(o, offset,
> + Float.floatToRawIntBits(expected),
> +                                             Float.floatToRawIntBits(x));
> +    }
> 
> Float.floatToRawIntBits() makes it safe, but with Float.intBitsToFloat() used infinite looping can happen for NaNs.
> 
> Best regards,
> Vladimir Ivanov
> 



More information about the jdk9-dev mailing list