[前][次][番号順一覧][スレッド一覧]

ruby-changes:37295

From: normal <ko1@a...>
Date: Thu, 22 Jan 2015 16:49:15 +0900 (JST)
Subject: [ruby-changes:37295] normal:r49376 (trunk): fix flonum hashing regression from r45384

normal	2015-01-22 16:48:59 +0900 (Thu, 22 Jan 2015)

  New Revision: 49376

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=49376

  Log:
    fix flonum hashing regression from r45384
    
    * st.c (st_numhash): mix float value for flonum
    * hash.c (rb_any_hash): ditto
    * benchmark/bm_hash_aref_flo.rb: new benchmark
    * benchmark/bm_hash_ident_flo.rb: ditto
      [Bug #10761]

  Added files:
    trunk/benchmark/bm_hash_aref_flo.rb
    trunk/benchmark/bm_hash_ident_flo.rb
  Modified files:
    trunk/ChangeLog
    trunk/hash.c
    trunk/st.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 49375)
+++ ChangeLog	(revision 49376)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Thu Jan 22 16:45:24 2015  Eric Wong  <e@8...>
+
+	* st.c (st_numhash): mix float value for flonum
+	* hash.c (rb_any_hash): ditto
+	* benchmark/bm_hash_aref_flo.rb: new benchmark
+	* benchmark/bm_hash_ident_flo.rb: ditto
+	  [Bug #10761]
+
 Wed Jan 21 22:33:51 2015  Akinori MUSHA  <knu@i...>
 
 	* misc/ruby-electric.el: Import version 2.2.1 from
Index: st.c
===================================================================
--- st.c	(revision 49375)
+++ st.c	(revision 49376)
@@ -1761,6 +1761,15 @@ st_numhash(st_data_t n) https://github.com/ruby/ruby/blob/trunk/st.c#L1761
      * - (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));
 }
Index: hash.c
===================================================================
--- hash.c	(revision 49375)
+++ hash.c	(revision 49376)
@@ -137,7 +137,13 @@ rb_any_hash(VALUE a) https://github.com/ruby/ruby/blob/trunk/hash.c#L137
 
     if (SPECIAL_CONST_P(a)) {
 	if (a == Qundef) return 0;
-	if (STATIC_SYM_P(a)) a >>= (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
+	if (STATIC_SYM_P(a)) {
+	    a >>= (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
+	}
+	else if (FLONUM_P(a)) {
+	    /* prevent pathological behavior: [Bug #10761] */
+	    a = (st_index_t)rb_float_value(a);
+	}
 	hnum = rb_objid_hash((st_index_t)a);
     }
     else if (BUILTIN_TYPE(a) == T_STRING) {
Index: benchmark/bm_hash_ident_flo.rb
===================================================================
--- benchmark/bm_hash_ident_flo.rb	(revision 0)
+++ benchmark/bm_hash_ident_flo.rb	(revision 49376)
@@ -0,0 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/bm_hash_ident_flo.rb#L1
+h = {}.compare_by_identity
+strs = (1..10000).to_a.map!(&:to_f)
+strs.each { |s| h[s] = s }
+50.times { strs.each { |s| h[s] } }
Index: benchmark/bm_hash_aref_flo.rb
===================================================================
--- benchmark/bm_hash_aref_flo.rb	(revision 0)
+++ benchmark/bm_hash_aref_flo.rb	(revision 49376)
@@ -0,0 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/bm_hash_aref_flo.rb#L1
+h = {}
+strs = (1..10000).to_a.map!(&:to_f)
+strs.each { |s| h[s] = s }
+50.times { strs.each { |s| h[s] } }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]