summaryrefslogtreecommitdiff
path: root/libgo/runtime
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-22 06:06:31 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-22 06:06:31 +0000
commit603be56a77ce92ed52dd889f2bd7dc271bdf1b25 (patch)
tree2ce5d179f6bcc6d9d87f045f082c26dcf3870c0b /libgo/runtime
parentc849bb594f2d84ac5300d24c92384db338820de7 (diff)
downloadgcc-603be56a77ce92ed52dd889f2bd7dc271bdf1b25.tar.gz
runtime: Return random number of hash of NaN.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@191632 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/go-type-complex.c14
-rw-r--r--libgo/runtime/go-type-float.c14
2 files changed, 22 insertions, 6 deletions
diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c
index f923c867d99..106024f5c88 100644
--- a/libgo/runtime/go-type-complex.c
+++ b/libgo/runtime/go-type-complex.c
@@ -32,10 +32,14 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
cf = ucf.cf;
cfr = __builtin_crealf (cf);
cfi = __builtin_cimagf (cf);
- if (__builtin_isinff (cfr) || __builtin_isinff (cfi)
- || __builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
return 0;
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cfr == 0 && cfi == 0)
return 0;
@@ -62,10 +66,12 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
cd = ucd.cd;
cdr = __builtin_crealf (cd);
cdi = __builtin_cimagf (cd);
- if (__builtin_isinf (cdr) || __builtin_isinf (cdi)
- || __builtin_isnan (cdr) || __builtin_isnan (cdi))
+ if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
return 0;
+ if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
+ return runtime_fastrand1 ();
+
/* Avoid negative zero. */
if (cdr == 0 && cdi == 0)
return 0;
diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c
index cc6e247e531..e1c03e42843 100644
--- a/libgo/runtime/go-type-float.c
+++ b/libgo/runtime/go-type-float.c
@@ -29,8 +29,14 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
__builtin_memcpy (uf.a, vkey, 4);
f = uf.f;
- if (__builtin_isinff (f) || __builtin_isnanf (f) || f == 0)
+ if (__builtin_isinff (f) || f == 0)
return 0;
+
+ /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
+ random so that not all NaNs wind up in the same place. */
+ if (__builtin_isnanf (f))
+ return runtime_fastrand1 ();
+
return (uintptr_t) uf.si;
}
else if (key_size == 8)
@@ -45,8 +51,12 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
__builtin_memcpy (ud.a, vkey, 8);
d = ud.d;
- if (__builtin_isinf (d) || __builtin_isnan (d) || d == 0)
+ if (__builtin_isinf (d) || d == 0)
return 0;
+
+ if (__builtin_isnan (d))
+ return runtime_fastrand1 ();
+
return (uintptr_t) ud.di;
}
else