From 059ea6e4d8233606d7dd522155744501b274acd4 Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 23 Jan 2015 02:36:50 +0000 Subject: hash.c: move Hash specific functions * hash.c (rb_ident_hash): move compare_by_identity specific function from st.c. * hash.c (rb_ident_hash_new): ditto from thread.c. * st.c (st_numhash): remove ruby's Hash specific implementation. * thread.c (recursive_list_access): use rb_ident_hash_new(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49386 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- hash.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index b7e2c66849..bae417c642 100644 --- a/hash.c +++ b/hash.c @@ -177,7 +177,39 @@ static const struct st_hash_type objhash = { rb_any_hash, }; -#define identhash st_hashtype_num +#define rb_ident_cmp st_numcmp + +static st_index_t +rb_ident_hash(st_data_t n) +{ + /* + * 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 ID scope, +1 worked well initially, too + * - (n << 3) was finally added to avoid losing bits for fixnums + * - avoid expensive modulo instructions, it is currently only + * shifts and bitmask operations. + * - 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] + */ +#ifdef USE_FLONUM /* RUBY */ + if (FLONUM_P(n)) { + n ^= (st_data_t)rb_float_value(n); + } +#endif + + return (st_index_t)((n>>(RUBY_SPECIAL_SHIFT+3)|(n<<3)) ^ (n>>3)); +} + +static const struct st_hash_type identhash = { + rb_ident_cmp, + rb_ident_hash, +}; typedef int st_foreach_func(st_data_t, st_data_t, st_data_t); @@ -2509,6 +2541,14 @@ rb_hash_compare_by_id_p(VALUE hash) return Qfalse; } +VALUE +rb_ident_hash_new(void) +{ + VALUE hash = rb_hash_new(); + RHASH(hash)->ntbl = st_init_table(&identhash); + return hash; +} + static int any_p_i(VALUE key, VALUE value, VALUE arg) { -- cgit v1.2.3