Commits

Antonio Cuni  committed f99a873

use an enum instead of a bool to keep track of the comparse_by_identiy status; this way, we can cache also the False case

  • Participants
  • Parent commits 78d8ec2
  • Branches identity-dict-strategy

Comments (0)

Files changed (2)

File pypy/objspace/std/objecttype.py

     if w_oldcls.get_full_instance_layout() == w_newcls.get_full_instance_layout():
         w_obj.setclass(space, w_newcls)
         if space.config.objspace.std.trackcomparebyidentity:
-            if not w_oldcls.overrides_hash_eq_or_cmp and not w_newcls.compares_by_identity():
+            if w_oldcls.compares_by_identity() and not w_newcls.compares_by_identity():
                 space.bump_compares_by_identity_version()
     else:
         raise operationerrfmt(space.w_TypeError,

File pypy/objspace/std/typeobject.py

         for i in range(len(self.lookup_where)):
             self.lookup_where[i] = None_None
 
+# possible values of compares_by_identity_status 
+UNKNOWN = 0
+COMPARES_BY_IDENTITY = 1
+OVERRIDES_EQ_CMP_OR_HASH = 2
 
 class W_TypeObject(W_Object):
     from pypy.objspace.std.typetype import type_typedef as typedef
     uses_object_getattribute = False
 
     # for config.objspace.std.trackcomparebyidentity
-    # (True is a conservative default, fixed during real usage)
-    overrides_hash_eq_or_cmp = True
+    compares_by_identity_status = UNKNOWN
 
     # used to cache the type __new__ function if it comes from a builtin type
     # != 'type', in that case call__Type will also assumes the result
             # ^^^ conservative default, fixed during real usage
 
         if space.config.objspace.std.trackcomparebyidentity:
-            did_compare_by_identity = not w_self.overrides_hash_eq_or_cmp
-            if did_compare_by_identity and (key is None or
-                                            key == '__eq__' or
-                                            key == '__cmp__' or
-                                            key == '__hash__'):
-                w_self.overrides_hash_eq_or_cmp = True
-                w_self.space.bump_compares_by_identity_version()
+            did_compare_by_identity = (
+                w_self.compares_by_identity_status == COMPARES_BY_IDENTITY)
+            if (key is None or key == '__eq__' or
+                key == '__cmp__' or key == '__hash__'):
+                w_self.compares_by_identity_status = UNKNOWN
+                if did_compare_by_identity:
+                    w_self.space.bump_compares_by_identity_version()
                 
         if space.config.objspace.std.newshortcut:
             w_self.w_bltin_new = None
         if not track:
             return False # conservative
         #
-        if not w_self.overrides_hash_eq_or_cmp:
-            return True # fast path
+        if w_self.compares_by_identity_status != UNKNOWN:
+            # fast path
+            return w_self.compares_by_identity_status == COMPARES_BY_IDENTITY
         #
-        # XXX: if the class *does* overrides, we always hit the slow path. Do
-        # we care?
         default_hash = object_hash(w_self.space)
-        w_self.overrides_hash_eq_or_cmp = (w_self.lookup('__eq__') or
-                                           w_self.lookup('__cmp__') or
-                                           w_self.lookup('__hash__') is not default_hash)
-        return not w_self.overrides_hash_eq_or_cmp
+        overrides_eq_cmp_or_hash = (w_self.lookup('__eq__') or
+                                    w_self.lookup('__cmp__') or
+                                    w_self.lookup('__hash__') is not default_hash)
+        if overrides_eq_cmp_or_hash:
+            w_self.compares_by_identity_status = OVERRIDES_EQ_CMP_OR_HASH
+        else:
+            w_self.compares_by_identity_status = COMPARES_BY_IDENTITY
+        return w_self.compares_by_identity_status == COMPARES_BY_IDENTITY
 
     def ready(w_self):
         for w_base in w_self.bases_w: