Author: Carl Friedrich Bolz <[email protected]>
Branch: type-specialized-instances
Changeset: r60080:e66173bbd88b
Date: 2013-01-15 12:01 +0100
http://bitbucket.org/pypy/pypy/changeset/e66173bbd88b/

Log:    also add a unicode specialization

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
@@ -8,6 +8,7 @@
 from pypy.objspace.std.dictmultiobject import BaseKeyIterator, 
BaseValueIterator, BaseItemIterator
 from pypy.objspace.std.dictmultiobject import _never_equal_to_string
 from pypy.objspace.std.stringobject import W_StringObject
+from pypy.objspace.std.unicodeobject import W_UnicodeObject
 from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import TypeCell
 
@@ -140,10 +141,14 @@
         attr = cache.get(key, None)
         if attr is None:
             # XXX not so nice that the classes have to be listed
+            # it's necessary because instantiate inside an elidable function
+            # confuses the JIT
             if attrclass_key == PlainAttribute.attrclass_key:
                 attr = PlainAttribute((name, index), self)
             elif attrclass_key == StrAttribute.attrclass_key:
                 attr = StrAttribute((name, index), self)
+            elif attrclass_key == UnicodeAttribute.attrclass_key:
+                attr = UnicodeAttribute((name, index), self)
             else:
                 assert attrclass_key == IntAttribute.attrclass_key
                 attr = IntAttribute((name, index), self)
@@ -394,6 +399,26 @@
         erased = self.erase_item(self.space.str_w(w_value))
         obj._mapdict_write_storage(self.position, erased)
 
+class UnicodeAttribute(AbstractStoredAttribute):
+    attrclass_key = 3
+
+    erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage 
unicode item")
+    erase_item = staticmethod(erase_item)
+    unerase_item = staticmethod(unerase_item)
+
+    def read_attr(self, obj):
+        erased = obj._mapdict_read_storage(self.position)
+        value = self.unerase_item(erased)
+        return self.space.wrap(value)
+
+    def write_attr(self, obj, w_value):
+        if type(w_value) is not W_UnicodeObject:
+            self._replace(obj, self.selector, w_value)
+            return
+        erased = self.erase_item(self.space.unicode_w(w_value))
+        obj._mapdict_write_storage(self.position, erased)
+
+
 
 def is_taggable_int(space, w_value):
     from pypy.objspace.std.intobject import W_IntObject
@@ -411,6 +436,8 @@
         attrclass = IntAttribute
     elif type(w_value) is W_StringObject:
         attrclass = StrAttribute
+    elif type(w_value) is W_UnicodeObject:
+        attrclass = UnicodeAttribute
     return attrclass
 
 def _become(w_obj, new_obj):
diff --git a/pypy/objspace/std/test/test_mapdict.py 
b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -467,6 +467,67 @@
         # check if 'y' is still reachable
         assert isinstance(obj1.map.back, StrAttribute)
         assert space.eq_w(obj1.getdictvalue(space, "y"), space.wrap("b"))
+
+    def test_unicode_attributes(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+        obj1.setdictvalue(space, "x", space.wrap(u"a"))
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap(u"a"))
+
+        obj2 = cls.instantiate()
+        w1 = W_Root()
+        obj2.setdictvalue(space, "x", w1)
+        assert obj2.getdictvalue(space, "x") is w1
+
+        assert obj1.map is not obj2.map
+        assert isinstance(obj1.map, UnicodeAttribute)
+
+        obj3 = cls.instantiate()
+        obj3.setdictvalue(space, "x", space.wrap(u"a"))
+        assert space.eq_w(obj3.getdictvalue(space, "x"), space.wrap(u"a"))
+
+        assert obj1.map is obj3.map
+
+        assert UnicodeAttribute.unerase_item(obj1.storage[0]) == "a"
+        assert PlainAttribute.unerase_item(obj2.storage[0]) == w1
+
+    def test_overwrite_unicode_attribute_with_another_type(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+
+        obj1.setdictvalue(space, "x", space.wrap(u"a"))
+        assert isinstance(obj1.map, UnicodeAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap(u"a"))
+
+        w1 = W_Root()
+        obj1.setdictvalue(space, "x", w1)
+        assert isinstance(obj1.map, PlainAttribute)
+        assert obj1.getdictvalue(space, "x") is w1
+
+    def test_overwrite_unicode_attribute_with_another_type2(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+
+        obj1.setdictvalue(space, "x", space.wrap(u"a"))
+        assert isinstance(obj1.map, UnicodeAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap(u"a"))
+
+        obj1.setdictvalue(space, "y", space.wrap(u"b"))
+        assert isinstance(obj1.map.back, UnicodeAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "y"), space.wrap(u"b"))
+
+        # overwrite 'x' with new type
+        w1 = W_Root()
+        obj1.setdictvalue(space, "x", w1)
+        assert isinstance(obj1.map, PlainAttribute)
+        assert obj1.getdictvalue(space, "x") is w1
+
+        # check if 'y' is still reachable
+        assert isinstance(obj1.map.back, UnicodeAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "y"), space.wrap(u"b"))
 # ___________________________________________________________
 # dict tests
 
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to