Author: Carl Friedrich Bolz <[email protected]>
Branch: guard-compatible
Changeset: r86082:71a4e8e68f14
Date: 2016-07-07 18:33 +0200
http://bitbucket.org/pypy/pypy/changeset/71a4e8e68f14/

Log:    make using objects as keys in dicts/in sets not read their types

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1766,6 +1766,11 @@
             _warnings.warn(msg, warningcls, stacklevel=stacklevel)
         """)
 
+    def compares_by_identity(self, w_obj):
+        """ returns True if the object compares by identity (ie inherits __eq__
+        and __hash__ from object) """
+        return self.type(w_obj).compares_by_identity()
+
 
 class AppExecCache(SpaceCache):
     def build(cache, source):
diff --git a/pypy/objspace/std/dictmultiobject.py 
b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -592,16 +592,16 @@
         return self.erase(None)
 
     def switch_to_correct_strategy(self, w_dict, w_key):
+        from pypy.objspace.std.intobject import W_IntObject
         if type(w_key) is self.space.StringObjectCls:
             self.switch_to_bytes_strategy(w_dict)
             return
         elif type(w_key) is self.space.UnicodeObjectCls:
             self.switch_to_unicode_strategy(w_dict)
             return
-        w_type = self.space.type(w_key)
-        if self.space.is_w(w_type, self.space.w_int):
+        elif type(w_key) is W_IntObject:
             self.switch_to_int_strategy(w_dict)
-        elif w_type.compares_by_identity():
+        if self.space.compares_by_identity(w_key):
             self.switch_to_identity_strategy(w_dict)
         else:
             self.switch_to_object_strategy(w_dict)
diff --git a/pypy/objspace/std/identitydict.py 
b/pypy/objspace/std/identitydict.py
--- a/pypy/objspace/std/identitydict.py
+++ b/pypy/objspace/std/identitydict.py
@@ -70,8 +70,7 @@
         return self.erase(d)
 
     def is_correct_type(self, w_obj):
-        w_type = self.space.type(w_obj)
-        return w_type.compares_by_identity()
+        return self.space.compares_by_identity(w_obj)
 
     def _never_equal_to(self, w_lookup_type):
         return False
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -352,6 +352,9 @@
         from pypy.objspace.std.typeobject import _issubtype
         return _issubtype(self.terminator.w_cls, w_type)
 
+    @jit.elidable_compatible(quasi_immut_field_name_for_second_arg="version")
+    def _type_compares_by_identity(self, version):
+        return self.terminator.w_cls.compares_by_identity()
 
 class Terminator(AbstractAttribute):
     _immutable_fields_ = ['w_cls']
@@ -1172,3 +1175,10 @@
                 if version_tag is not None:
                     return map._type_issubtype(w_type)
     return space.type(w_obj).issubtype(w_type)
+
+def mapdict_compares_by_identity(space, w_obj):
+    if we_are_jitted() and w_obj.user_overridden_class:
+        map = w_obj._get_mapdict_map_no_promote()
+        if map.version is not None:
+            return map._type_compares_by_identity()
+    return space.type(w_obj).compares_by_identity()
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -657,6 +657,10 @@
                     return True
         return mapdict_type_isinstance(self, w_inst, w_type)
 
+    def compares_by_identity(self, w_obj):
+        from pypy.objspace.std.mapdict import mapdict_compares_by_identity
+        return mapdict_compares_by_identity(self, w_obj)
+
     @specialize.memo()
     def _get_interplevel_cls(self, w_type):
         if not hasattr(self, "_interplevel_classes"):
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -796,7 +796,7 @@
             strategy = self.space.fromcache(BytesSetStrategy)
         elif type(w_key) is W_UnicodeObject:
             strategy = self.space.fromcache(UnicodeSetStrategy)
-        elif self.space.type(w_key).compares_by_identity():
+        elif self.space.compares_by_identity(w_key):
             strategy = self.space.fromcache(IdentitySetStrategy)
         else:
             strategy = self.space.fromcache(ObjectSetStrategy)
@@ -1399,8 +1399,7 @@
         return {}
 
     def is_correct_type(self, w_key):
-        w_type = self.space.type(w_key)
-        return w_type.compares_by_identity()
+        return self.space.compares_by_identity(w_key)
 
     def may_contain_equal_elements(self, strategy):
         #empty first, probably more likely
@@ -1645,7 +1644,7 @@
 
     # check for compares by identity
     for w_item in iterable_w:
-        if not space.type(w_item).compares_by_identity():
+        if not space.compares_by_identity(w_item):
             break
     else:
         w_set.strategy = space.fromcache(IdentitySetStrategy)
diff --git a/pypy/objspace/std/test/test_typeobject.py 
b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -1241,7 +1241,7 @@
         assert (Y < Y) is True
 
 
-class AppTestComparesByIdentity:
+class AppTestComparesByIdentity(jit.RandomWeAreJittedTestMixin):
 
     def setup_class(cls):
         if cls.runappdirect:
@@ -1251,6 +1251,10 @@
             return space.wrap(w_cls.compares_by_identity())
         cls.w_compares_by_identity = 
cls.space.wrap(interp2app(compares_by_identity))
 
+        def instance_compares_by_identity(space, w_obj):
+            return space.wrap(space.compares_by_identity(w_obj))
+        cls.w_instance_compares_by_identity = 
cls.space.wrap(interp2app(instance_compares_by_identity))
+
     def test_compares_by_identity(self):
         class Plain(object):
             pass
@@ -1282,6 +1286,15 @@
         assert self.compares_by_identity(TypeSubclass)
         assert not self.compares_by_identity(TypeSubclassCustomCmp)
 
+        assert self.instance_compares_by_identity(Plain())
+        assert not self.instance_compares_by_identity(CustomEq())
+        assert not self.instance_compares_by_identity(CustomCmp())
+        assert not self.instance_compares_by_identity(CustomHash())
+        assert self.instance_compares_by_identity(Plain)
+        assert self.instance_compares_by_identity(TypeSubclass('a', (object, 
), {}))
+        assert not 
self.instance_compares_by_identity(TypeSubclassCustomCmp('a', (object, ), {}))
+
+
     def test_modify_class(self):
         class X(object):
             pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to