]> granicus.if.org Git - python/commitdiff
Issue #5186: Reduce hash collisions for objects with no __hash__ method by
authorAntoine Pitrou <solipsis@pitrou.net>
Fri, 13 Feb 2009 13:52:33 +0000 (13:52 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Fri, 13 Feb 2009 13:52:33 +0000 (13:52 +0000)
rotating the object pointer by 4 bits to the right.

Misc/NEWS
Objects/object.c

index 70a15d779a51eb7783c5b034b1a2b83afeb12f91..b620a5a9f48f0108d394cb3ad6e2357e450c392b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
 Core and Builtins
 -----------------
 
+- Issue #5186: Reduce hash collisions for objects with no __hash__ method by
+  rotating the object pointer by 4 bits to the right.
+
 - Issue #4575: Fix Py_IS_INFINITY macro to work correctly on x87 FPUs:
   it now forces its argument to double before testing for infinity.
 
index 9108fd431ac3da682a5389d1ef17cd367e3c5c66..8006fdab4d2be0737ad118d2719581a9136577b2 100644 (file)
@@ -1072,23 +1072,15 @@ _Py_HashDouble(double v)
 long
 _Py_HashPointer(void *p)
 {
-#if SIZEOF_LONG >= SIZEOF_VOID_P
-       return (long)p;
-#else
-       /* convert to a Python long and hash that */
-       PyObject* longobj;
        long x;
-
-       if ((longobj = PyLong_FromVoidPtr(p)) == NULL) {
-               x = -1;
-               goto finally;
-       }
-       x = PyObject_Hash(longobj);
-
-finally:
-       Py_XDECREF(longobj);
+       size_t y = (size_t)p;
+       /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid
+          excessive hash collisions for dicts and sets */
+       y = (y >> 4) | (y << 8*SIZEOF_VOID_P - 4);
+       x = (long)y;
+       if (x == -1)
+               x = -2;
        return x;
-#endif
 }
 
 long