Commits

Carl Friedrich Bolz committed e66173b

also add a unicode specialization

  • Participants
  • Parent commits 4f8edbe
  • Branches type-specialized-instances

Comments (0)

Files changed (2)

pypy/objspace/std/mapdict.py

 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
 
         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)
         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
         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):

pypy/objspace/std/test/test_mapdict.py

         # 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