[pypy-commit] pypy default: unify the hash computation more with py3.5

arigo pypy.commits at gmail.com
Wed May 9 12:57:53 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r94505:52d2cf0086d1
Date: 2018-05-09 18:53 +0200
http://bitbucket.org/pypy/pypy/changeset/52d2cf0086d1/

Log:	unify the hash computation more with py3.5

diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -391,7 +391,6 @@
 
     def descr_hash(self, space):
         h = _hash_float(space, self.floatval)
-        h -= (h == -1)
         return space.newint(h)
 
     def descr_format(self, space, w_spec):
@@ -716,8 +715,6 @@
         # This must return the same hash as an equal int or long.
         try:
             x = ovfcheck_float_to_int(intpart)
-            # Fits in a C long == a Python int, so is its own hash.
-            return x
         except OverflowError:
             # Convert to long and use its hash.
             try:
@@ -729,6 +726,10 @@
                 else:
                     return 314159
             return space.int_w(space.hash(w_lval))
+        else:
+            # Fits in a C long == a Python int.
+            from pypy.objspace.std.intobject import _hash_int
+            return _hash_int(x)
 
     # The fractional part is non-zero, so we don't have to worry about
     # making this match the hash of some other type.
@@ -747,6 +748,7 @@
     hipart = int(v)    # take the top 32 bits
     v = (v - hipart) * 2147483648.0 # get the next 32 bits
     x = intmask(hipart + int(v) + (expo << 15))
+    x -= (x == -1)
     return x
 
 
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -361,13 +361,7 @@
         return _new_int(space, w_inttype, w_x, w_base)
 
     def descr_hash(self, space):
-        # For compatibility with CPython, we special-case -1
-        # Make sure this is consistent with the hash of floats and longs.
-        # The complete list of built-in types whose hash should be
-        # consistent is: int, long, bool, float, complex.
-        h = self.intval
-        h -= (h == -1)  # No explicit condition, to avoid JIT bridges
-        return wrapint(space, h)
+        return space.newint(_hash_int(self.intval))
 
     def _int(self, space):
         return self.int(space)
@@ -893,3 +887,12 @@
     __rpow__ = interp2app(W_IntObject.descr_rpow,
                           doc=W_AbstractIntObject.descr_rpow.__doc__),
 )
+
+
+def _hash_int(a):
+    # For compatibility with CPython, we special-case -1
+    # Make sure this is consistent with the hash of floats and longs.
+    # The complete list of built-in types whose hash should be
+    # consistent is: int, long, bool, float, complex.
+    #
+    return a - (a == -1)  # No explicit condition, to avoid JIT bridges
diff --git a/pypy/objspace/std/specialisedtupleobject.py b/pypy/objspace/std/specialisedtupleobject.py
--- a/pypy/objspace/std/specialisedtupleobject.py
+++ b/pypy/objspace/std/specialisedtupleobject.py
@@ -1,7 +1,7 @@
 from pypy.interpreter.error import oefmt
 from pypy.objspace.std.tupleobject import W_AbstractTupleObject
 from pypy.objspace.std.util import negate
-from rpython.rlib.objectmodel import compute_hash, specialize
+from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.tool.sourcetools import func_with_new_name
@@ -71,18 +71,19 @@
                 value = getattr(self, 'value%s' % i)
                 if typetuple[i] == object:
                     y = space.int_w(space.hash(value))
-                elif typetuple[i] == int:
-                    # mimic cpythons behavior of a hash value of -2 for -1
-                    y = value
-                    y -= (y == -1)  # No explicit condition, to avoid JIT bridges
                 elif typetuple[i] == float:
                     # get the correct hash for float which is an
                     # integer & other less frequent cases
                     from pypy.objspace.std.floatobject import _hash_float
                     y = _hash_float(space, value)
-                    y -= (y == -1)
+                elif typetuple[i] == int:
+                    # hash for int which is different from the hash
+                    # given by rpython
+                    from pypy.objspace.std.intobject import _hash_int
+                    y = _hash_int(value)
                 else:
-                    assert 0, "unreachable"
+                    raise NotImplementedError
+
                 x = (x ^ y) * mult
                 z -= 1
                 mult += 82520 + z + z
diff --git a/pypy/objspace/std/test/test_specialisedtupleobject.py b/pypy/objspace/std/test/test_specialisedtupleobject.py
--- a/pypy/objspace/std/test/test_specialisedtupleobject.py
+++ b/pypy/objspace/std/test/test_specialisedtupleobject.py
@@ -23,7 +23,7 @@
         w_tuple = self.space.newtuple([self.space.wrap(1), self.space.wrap(2)])
         assert w_tuple.__class__.__name__ == 'W_SpecialisedTupleObject_ii'
 
-    def hash_test(self, values, must_be_specialized=True):
+    def hash_test(self, values, must_be_specialized):
         N_values_w = [self.space.wrap(value) for value in values]
         S_values_w = [self.space.wrap(value) for value in values]
         N_w_tuple = W_TupleObject(N_values_w)


More information about the pypy-commit mailing list