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