Author: Carl Friedrich Bolz <[email protected]>
Branch: type-specialized-instances
Changeset: r60055:8503866ec6b1
Date: 2013-01-14 18:26 +0100
http://bitbucket.org/pypy/pypy/changeset/8503866ec6b1/

Log:    specialize string fields

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
@@ -7,6 +7,7 @@
 from pypy.objspace.std.dictmultiobject import W_DictMultiObject, DictStrategy, 
ObjectDictStrategy
 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.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import TypeCell
 
@@ -141,6 +142,8 @@
             # XXX not so nice that the classes have to be listed
             if attrclass_key == PlainAttribute.attrclass_key:
                 attr = PlainAttribute((name, index), self)
+            elif attrclass_key == StrAttribute.attrclass_key:
+                attr = StrAttribute((name, index), self)
             else:
                 assert attrclass_key == IntAttribute.attrclass_key
                 attr = IntAttribute((name, index), self)
@@ -372,6 +375,26 @@
         erased = self.erase_item(self.space.int_w(w_value))
         obj._mapdict_write_storage(self.position, erased)
 
+class StrAttribute(AbstractStoredAttribute):
+    attrclass_key = 2
+
+    erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage 
string 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_StringObject:
+            self._replace(obj, self.selector, w_value)
+            return
+        erased = self.erase_item(self.space.str_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
     if type(w_value) is W_IntObject:
@@ -386,7 +409,8 @@
     attrclass = PlainAttribute
     if is_taggable_int(space, w_value):
         attrclass = IntAttribute
-
+    elif type(w_value) is W_StringObject:
+        attrclass = StrAttribute
     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
@@ -407,6 +407,66 @@
         assert isinstance(obj1.map, PlainAttribute)
         assert space.eq_w(obj1.getdictvalue(space, "x"), 
space.wrap(sys.maxint))
 
+    def test_str_attributes(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+        obj1.setdictvalue(space, "x", space.wrap("a"))
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap("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, StrAttribute)
+
+        obj3 = cls.instantiate()
+        obj3.setdictvalue(space, "x", space.wrap("a"))
+        assert space.eq_w(obj3.getdictvalue(space, "x"), space.wrap("a"))
+
+        assert obj1.map is obj3.map
+
+        assert StrAttribute.unerase_item(obj1.storage[0]) == "a"
+        assert PlainAttribute.unerase_item(obj2.storage[0]) == w1
+
+    def test_overwrite_str_attribute_with_another_type(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+
+        obj1.setdictvalue(space, "x", space.wrap("a"))
+        assert isinstance(obj1.map, StrAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap("a"))
+
+        w1 = W_Root()
+        obj1.setdictvalue(space, "x", w1)
+        assert isinstance(obj1.map, PlainAttribute)
+        assert obj1.getdictvalue(space, "x") is w1
+
+    def test_overwrite_str_attribute_with_another_type2(self):
+        space = self.space
+        cls = Class(sp=space)
+        obj1 = cls.instantiate()
+
+        obj1.setdictvalue(space, "x", space.wrap("a"))
+        assert isinstance(obj1.map, StrAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "x"), space.wrap("a"))
+
+        obj1.setdictvalue(space, "y", space.wrap("b"))
+        assert isinstance(obj1.map.back, StrAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "y"), space.wrap("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, StrAttribute)
+        assert space.eq_w(obj1.getdictvalue(space, "y"), space.wrap("b"))
 # ___________________________________________________________
 # dict tests
 
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to