Project

General

Profile

hash.patch

vmakarov (Vladimir Makarov), 04/29/2016 09:55 PM

Download (4.48 KB)

View differences:

hash.c
145 145

  
146 146
long rb_objid_hash(st_index_t index);
147 147

  
148
static st_index_t
148
long
149
rb_dbl_long_hash(double d)
150
{
151
    /* normalize -0.0 to 0.0 */
152
    if (d == 0.0) d = 0.0;
153
#if SIZEOF_INT == SIZEOF_VOIDP
154
    return rb_memhash(&d, sizeof(d));
155
#else
156
    {
157
	union {double d; uint64_t i;} u;
158
	
159
	u.d = d;
160
	return rb_objid_hash(u.i);
161
    }
162
#endif
163
}
164

  
165
static inline st_index_t
149 166
any_hash(VALUE a, st_index_t (*other_func)(VALUE))
150 167
{
151 168
    VALUE hval;
152 169
    st_index_t hnum;
153 170

  
154 171
    if (SPECIAL_CONST_P(a)) {
155
	if (a == Qundef) return 0;
156 172
	if (STATIC_SYM_P(a)) {
157 173
	    hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
158 174
	    goto out;
......
175 191
    }
176 192
    else if (BUILTIN_TYPE(a) == T_FLOAT) {
177 193
      flt:
178
	hval = rb_dbl_hash(rb_float_value(a));
179
	hnum = FIX2LONG(hval);
194
	hnum = rb_dbl_long_hash(rb_float_value(a));
180 195
    }
181 196
    else {
182 197
	hnum = other_func(a);
......
199 214
    return any_hash(a, obj_any_hash);
200 215
}
201 216

  
202
static st_index_t
203
rb_num_hash_start(st_index_t n)
217
/* Here is a hash function for 64-bit key.  It is about 5 times faster
218
   (2 times faster when uint128 type is absent) on Haswell than
219
   tailored Spooky or City hash function can be.  */
220

  
221
/* Here we two primes with random bit generation.  */
222
static const uint64_t prime1 = 0x2e0bb864e9ea7df5ULL;
223
static const uint64_t prime2 = 0xcdb32970830fcaa1ULL;
224

  
225

  
226
static inline uint64_t
227
mult_and_mix (uint64_t m1, uint64_t m2)
204 228
{
205
    /*
206
     * This hash function is lightly-tuned for Ruby.  Further tuning
207
     * should be possible.  Notes:
208
     *
209
     * - (n >> 3) alone is great for heap objects and OK for fixnum,
210
     *   however symbols perform poorly.
211
     * - (n >> (RUBY_SPECIAL_SHIFT+3)) was added to make symbols hash well,
212
     *   n.b.: +3 to remove most ID scope, +1 worked well initially, too
213
     *   n.b.: +1 (instead of 3) worked well initially, too
214
     * - (n << 16) was finally added to avoid losing bits for fixnums
215
     * - avoid expensive modulo instructions, it is currently only
216
     *   shifts and bitmask operations.
217
     */
218
    return (n >> (RUBY_SPECIAL_SHIFT + 3) ^ (n << 16)) ^ (n >> 3);
229
#if defined(__GNUC__) && UINT_MAX != ULONG_MAX
230
    __uint128_t r = (__uint128_t) m1 * (__uint128_t) m2;
231
    return (uint64_t) (r >> 64) ^ (uint64_t) r;
232
#else
233
    uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
234
    uint64_t lm1 = m1, lm2 = m2;
235
    uint64_t v64_128 = hm1 * hm2;
236
    uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
237
    uint64_t v1_32 = lm1 * lm2;
238
    
239
    return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
240
#endif
241
}
242

  
243
static inline uint64_t
244
key64_hash (uint64_t key, uint32_t seed)
245
{
246
    return mult_and_mix(key + seed, prime1);
219 247
}
220 248

  
221 249
long
222 250
rb_objid_hash(st_index_t index)
223 251
{
224
    st_index_t hnum = rb_num_hash_start(index);
225

  
226
    hnum = rb_hash_start(hnum);
227
    hnum = rb_hash_uint(hnum, (st_index_t)rb_any_hash);
228
    hnum = rb_hash_end(hnum);
229
    return hnum;
252
    return key64_hash (index, prime2);
230 253
}
231 254

  
232 255
static st_index_t
......
269 292
    }
270 293
#endif
271 294

  
272
    return (st_index_t)rb_num_hash_start((st_index_t)n);
295
    return (st_index_t) key64_hash((st_index_t)n, prime2);
273 296
}
274 297

  
275 298
static const struct st_hash_type identhash = {
numeric.c
1250 1250
VALUE
1251 1251
rb_dbl_hash(double d)
1252 1252
{
1253
    st_index_t hash;
1254

  
1255
    /* normalize -0.0 to 0.0 */
1256
    if (d == 0.0) d = 0.0;
1257
    hash = rb_memhash(&d, sizeof(d));
1258
    return LONG2FIX(hash);
1253
    return LONG2FIX(rb_dbl_long_hash (d));
1259 1254
}
1260 1255

  
1261 1256
VALUE
1262
-- a/internal.h
1257
++ b/internal.h
......
953 953
VALUE rb_hash_default_value(VALUE hash, VALUE key);
954 954
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
955 955
long rb_objid_hash(st_index_t index);
956
long rb_dbl_long_hash(double d);
956 957
st_table *rb_init_identtable(void);
957 958
st_table *rb_init_identtable_with_size(st_index_t size);
958 959