hg: jdk7/hotspot-comp/hotspot: 6778657: Casts in SharedRuntime::f2i, f2l, d2i and d2l rely on undefined C++ behaviour
Gary Benson
gbenson at redhat.com
Tue Jan 6 05:17:24 PST 2009
Florian Weimer wrote:
> * vladimir kozlov:
> > 6778657: Casts in SharedRuntime::f2i, f2l, d2i and d2l rely on undefined C++ behaviour
> > Summary: Replaces SharedRuntime::f2i et al with versions that should work
>
> This:
>
> JRT_LEAF(jlong, SharedRuntime::f2l(jfloat x))
> - if (g_isnan(x)) {return 0;}
> - jlong lltmp = (jlong)x;
> - if (lltmp != min_jlong) {
> - return lltmp;
> - } else {
> - if (x < 0) {
> - return min_jlong;
> - } else {
> - return max_jlong;
> - }
> - }
> + if (g_isnan(x))
> + return 0;
> + if (x >= (jfloat) max_jlong)
> + return max_jlong;
> + if (x <= (jfloat) min_jlong)
> + return min_jlong;
> + return (jlong) x;
> JRT_END
>
> doesn't look right because
>
> (jfloat) max_jlong and (jfloat) min_jlong
>
> are not fully specified, either (they can be off by one, and so the
> comparison could be false even if the subsequent cast is undefined).
It's true that (jfloat) max_jlong cannot be represented exactly, but
this doesn't matter here because the argument x is also a jfloat and
so subject to the same limitation. (jfloat) max_jlong is 0x1p+63,
and the predecessor of 0x1p+63 is 0x1.fffffep+62. If you check the
return value of f2l across the boundary you get:
Input Output
0x1.fffffep+62 0x7fffff8000000000 // return (jlong) x
0x1p+63 0x7fffffffffffffff // return max_jlong;
There is no float between 0x1.fffffep+62 and 0x1p+63, so there's
no input to f2l that can be off by one.
This affects (jfloat) max_jint too, but the same logic applies.
As exact powers of two, (jfloat) min_jlong and (jfloat) min_jint
are exactly representable, so there's no problem there either.
(Thanks to Andrew Haley for explaining some of this to me.)
Cheers,
Gary
--
http://gbenson.net/
More information about the hotspot-compiler-dev
mailing list