diff --git a/hash.c b/hash.c index 0d963976b9c9fe..85bbbfb6ae7020 100644 --- a/hash.c +++ b/hash.c @@ -175,8 +175,7 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE)) } else if (BUILTIN_TYPE(a) == T_FLOAT) { flt: - hval = rb_dbl_hash(rb_float_value(a)); - hnum = FIX2LONG(hval); + hnum = rb_dbl_hash_long(rb_float_value(a)); } else { hnum = other_func(a); @@ -199,34 +198,29 @@ rb_any_hash(VALUE a) return any_hash(a, obj_any_hash); } -static st_index_t -rb_num_hash_start(st_index_t n) +long +rb_dbl_hash_long(double d) { - /* - * This hash function is lightly-tuned for Ruby. Further tuning - * should be possible. Notes: - * - * - (n >> 3) alone is great for heap objects and OK for fixnum, - * however symbols perform poorly. - * - (n >> (RUBY_SPECIAL_SHIFT+3)) was added to make symbols hash well, - * n.b.: +3 to remove most ID scope, +1 worked well initially, too - * n.b.: +1 (instead of 3) worked well initially, too - * - (n << 16) was finally added to avoid losing bits for fixnums - * - avoid expensive modulo instructions, it is currently only - * shifts and bitmask operations. - */ - return (n >> (RUBY_SPECIAL_SHIFT + 3) ^ (n << 16)) ^ (n >> 3); + long hash; + unsigned i; +#define ind_in_dbl type_roomof(double, st_index_t) + union { + st_index_t i[ind_in_dbl]; + double d; + } v = { {0} }; + /* normalize -0.0 to 0.0 */ + v.d = d == 0.0 ? 0.0 : d; + hash = rb_hash_start(v.i[0]); + for (i = 1; i < ind_in_dbl; i++) { + hash = rb_hash_uint(hash, v.i[i]); + } + return rb_hash_end(hash); } long rb_objid_hash(st_index_t index) { - st_index_t hnum = rb_num_hash_start(index); - - hnum = rb_hash_start(hnum); - hnum = rb_hash_uint(hnum, (st_index_t)rb_any_hash); - hnum = rb_hash_end(hnum); - return hnum; + return rb_hash_end(index); } static st_index_t @@ -258,18 +252,7 @@ static const struct st_hash_type objhash = { static st_index_t rb_ident_hash(st_data_t n) { -#ifdef USE_FLONUM /* RUBY */ - /* - * - flonum (on 64-bit) is pathologically bad, mix the actual - * float value in, but do not use the float value as-is since - * many integers get interpreted as 2.0 or -2.0 [Bug #10761] - */ - if (FLONUM_P(n)) { - n ^= (st_data_t)rb_float_value(n); - } -#endif - - return (st_index_t)rb_num_hash_start((st_index_t)n); + return rb_hash_end((st_index_t)n); } static const struct st_hash_type identhash = { diff --git a/internal.h b/internal.h index f9bc693e0f3d43..1279f695eb77f3 100644 --- a/internal.h +++ b/internal.h @@ -1092,7 +1092,6 @@ struct st_table *rb_hash_tbl_raw(VALUE hash); VALUE rb_hash_has_key(VALUE hash, VALUE key); VALUE rb_hash_default_value(VALUE hash, VALUE key); VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc); -long rb_objid_hash(st_index_t index); st_table *rb_init_identtable(void); st_table *rb_init_identtable_with_size(st_index_t size); @@ -1159,6 +1158,7 @@ VALUE rb_int_modulo(VALUE x, VALUE y); VALUE rb_int_round(VALUE num, int ndigits); VALUE rb_int2str(VALUE num, int base); VALUE rb_dbl_hash(double d); +long rb_dbl_hash_long(double d); VALUE rb_fix_plus(VALUE x, VALUE y); VALUE rb_int_ge(VALUE x, VALUE y); diff --git a/numeric.c b/numeric.c index ffa576149e1ebd..1155ca35d94b5b 100644 --- a/numeric.c +++ b/numeric.c @@ -1350,12 +1350,7 @@ flo_hash(VALUE num) VALUE rb_dbl_hash(double d) { - st_index_t hash; - - /* normalize -0.0 to 0.0 */ - if (d == 0.0) d = 0.0; - hash = rb_memhash(&d, sizeof(d)); - return LONG2FIX(hash); + return LONG2FIX(rb_dbl_hash_long(d)); } VALUE diff --git a/object.c b/object.c index c9649253b1f2ea..147d79b9aa85f0 100644 --- a/object.c +++ b/object.c @@ -162,15 +162,7 @@ rb_obj_equal(VALUE obj1, VALUE obj2) VALUE rb_obj_hash(VALUE obj) { - VALUE oid = rb_obj_id(obj); -#if SIZEOF_LONG == SIZEOF_VOIDP - st_index_t index = NUM2LONG(oid); -#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP - st_index_t index = NUM2LL(oid); -#else -# error not supported -#endif - return LONG2FIX(rb_objid_hash(index)); + /* stub for documentation */ } #else VALUE rb_obj_hash(VALUE obj);