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