[PATCH] 6779290: Casts in SharedRuntime::f2i, f2l, d2i and d2l rely on undefined behaviour
Gary Benson
gbenson at redhat.com
Wed Dec 3 03:52:05 PST 2008
Hi all,
In C++, the result of an overflowing cast to a signed integer is
undefined. The functions used to implement f2i, f2l, d2i and d2l,
however, rely on the assumption that the result of an overflowing
cast will be the largest magnitude number with the correct sign.
The attached patch fixes.
Cheers,
Gary
--
http://gbenson.net/
-------------- next part --------------
diff -r dcb49b482348 -r f63a8dee04ae openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp
--- openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Nov 03 14:00:57 2008 +0000
+++ openjdk/hotspot/src/share/vm/runtime/sharedRuntime.cpp Mon Nov 03 15:56:17 2008 +0000
@@ -173,64 +173,46 @@ JRT_END
JRT_LEAF(jint, SharedRuntime::f2i(jfloat x))
- if (g_isnan(x)) {return 0;}
- jlong lltmp = (jlong)x;
- jint ltmp = (jint)lltmp;
- if (ltmp == lltmp) {
- return ltmp;
- } else {
- if (x < 0) {
- return min_jint;
- } else {
- return max_jint;
- }
- }
+ if (g_isnan(x))
+ return 0;
+ if (x >= (jfloat) max_jint)
+ return max_jint;
+ if (x <= (jfloat) min_jint)
+ return min_jint;
+ return (jint) x;
JRT_END
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
JRT_LEAF(jint, SharedRuntime::d2i(jdouble x))
- if (g_isnan(x)) {return 0;}
- jlong lltmp = (jlong)x;
- jint ltmp = (jint)lltmp;
- if (ltmp == lltmp) {
- return ltmp;
- } else {
- if (x < 0) {
- return min_jint;
- } else {
- return max_jint;
- }
- }
+ if (g_isnan(x))
+ return 0;
+ if (x >= (jdouble) max_jint)
+ return max_jint;
+ if (x <= (jdouble) min_jint)
+ return min_jint;
+ return (jint) x;
JRT_END
JRT_LEAF(jlong, SharedRuntime::d2l(jdouble 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 >= (jdouble) max_jlong)
+ return max_jlong;
+ if (x <= (jdouble) min_jlong)
+ return min_jlong;
+ return (jlong) x;
JRT_END
-------------- next part --------------
/* @test
* @bug 6779290
* @summary Check that [fd]2[il] overflow correctly
*/
public class Test6779290 {
public static void check_f2i(int expect) {
float check = expect;
check *= 2;
int actual = (int) check;
if (actual != expect)
throw new RuntimeException("expecting " + expect + ", got " + actual);
}
public static void check_f2l(long expect) {
float check = expect;
check *= 2;
long actual = (long) check;
if (actual != expect)
throw new RuntimeException("expecting " + expect + ", got " + actual);
}
public static void check_d2i(int expect) {
double check = expect;
check *= 2;
int actual = (int) check;
if (actual != expect)
throw new RuntimeException("expecting " + expect + ", got " + actual);
}
public static void check_d2l(long expect) {
double check = expect;
check *= 2;
long actual = (long) check;
if (actual != expect)
throw new RuntimeException("expecting " + expect + ", got " + actual);
}
public static void main(String[] args) {
check_f2i(Integer.MAX_VALUE);
check_f2i(Integer.MIN_VALUE);
check_f2l(Long.MAX_VALUE);
check_f2l(Long.MIN_VALUE);
check_d2i(Integer.MAX_VALUE);
check_d2i(Integer.MIN_VALUE);
check_d2l(Long.MAX_VALUE);
check_d2l(Long.MIN_VALUE);
}
}
More information about the hotspot-dev
mailing list