Author: Carl Friedrich Bolz <[email protected]>
Branch: typed-cells
Changeset: r75493:67cd227f7eae
Date: 2015-01-23 00:14 +0100
http://bitbucket.org/pypy/pypy/changeset/67cd227f7eae/

Log:    start using mutable int boxes on instances

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,8 +8,8 @@
     W_DictMultiObject, DictStrategy, ObjectDictStrategy, BaseKeyIterator,
     BaseValueIterator, BaseItemIterator, _never_equal_to_string
 )
-from pypy.objspace.std.typeobject import MutableCell
-
+from pypy.objspace.std.typeobject import (
+    MutableCell, IntMutableCell, ObjectMutableCell, unwrap_cell)
 
 # ____________________________________________________________
 # attribute shapes
@@ -39,9 +39,12 @@
             jit.isconstant(obj) and
             not attr.ever_mutated
         ):
-            return self._pure_mapdict_read_storage(obj, attr.storageindex)
+            result = self._pure_mapdict_read_storage(obj, attr.storageindex)
+            assert not isinstance(result, MutableCell)
         else:
-            return obj._mapdict_read_storage(attr.storageindex)
+            result = unwrap_cell(
+                attr.space, obj._mapdict_read_storage(attr.storageindex))
+        return result
 
     @jit.elidable
     def _pure_mapdict_read_storage(self, obj, storageindex):
@@ -53,9 +56,25 @@
             return self.terminator._write_terminator(obj, selector, w_value)
         if not attr.ever_mutated:
             attr.ever_mutated = True
-        obj._mapdict_write_storage(attr.storageindex, w_value)
+        # introduce cells only on the second write, to make immutability for
+        # int fields still work
+        cell = obj._mapdict_read_storage(attr.storageindex)
+        w_value = self._write_cell(attr.space, cell, w_value)
+        if w_value is not None:
+            obj._mapdict_write_storage(attr.storageindex, w_value)
         return True
 
+    def _write_cell(self, space, w_cell, w_value):
+        from pypy.objspace.std.intobject import W_IntObject
+        assert not isinstance(w_cell, ObjectMutableCell)
+        if isinstance(w_cell, IntMutableCell) and type(w_value) is W_IntObject:
+            w_cell.intvalue = w_value.intval
+            return None
+        if type(w_value) is W_IntObject:
+            return IntMutableCell(w_value.intval)
+        return w_value
+
+
     def delete(self, obj, selector):
         pass
 
@@ -320,7 +339,8 @@
         new_obj = self.back.materialize_r_dict(space, obj, dict_w)
         if self.selector[1] == DICT:
             w_attr = space.wrap(self.selector[0])
-            dict_w[w_attr] = obj._mapdict_read_storage(self.storageindex)
+            dict_w[w_attr] = unwrap_cell(
+                    space, obj._mapdict_read_storage(self.storageindex))
         else:
             self._copy_attr(obj, new_obj)
         return new_obj
@@ -856,7 +876,8 @@
     map = w_obj._get_mapdict_map()
     if entry.is_valid_for_map(map) and entry.w_method is None:
         # everything matches, it's incredibly fast
-        return w_obj._mapdict_read_storage(entry.storageindex)
+        return unwrap_cell(
+                map.space, w_obj._mapdict_read_storage(entry.storageindex))
     return LOAD_ATTR_slowpath(pycode, w_obj, nameindex, map)
 LOAD_ATTR_caching._always_inline_ = True
 
@@ -901,7 +922,8 @@
                     # Note that if map.terminator is a DevolvedDictTerminator,
                     # map.find_map_attr will always return None if 
selector[1]==DICT.
                     _fill_cache(pycode, nameindex, map, version_tag, 
attr.storageindex)
-                    return w_obj._mapdict_read_storage(attr.storageindex)
+                    return unwrap_cell(
+                            space, 
w_obj._mapdict_read_storage(attr.storageindex))
     if space.config.objspace.std.withmethodcachecounter:
         INVALID_CACHE_ENTRY.failure_counter += 1
     return space.getattr(w_obj, w_name)
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
@@ -154,6 +154,26 @@
     assert obj.map.ever_mutated == True
     assert obj.map is map1
 
+def test_mutbox():
+    from pypy.objspace.std.intobject import W_IntObject
+    cls = Class()
+    obj = cls.instantiate()
+    obj.setdictvalue(space, "a", W_IntObject(5))
+    assert obj.getdictvalue(space, "a").intval == 5
+    w_val = obj._mapdict_read_storage(0)
+    assert w_val.intval == 5 # still a W_IntObject
+
+    obj.setdictvalue(space, "a", W_IntObject(6))
+    assert obj.getdictvalue(space, "a") == 6 # because of the FakeSpace :-(
+    mutbox1 = obj._mapdict_read_storage(0)
+    assert mutbox1.intvalue == 6
+
+    obj.setdictvalue(space, "a", W_IntObject(7))
+    assert obj.getdictvalue(space, "a") == 7 # because of the FakeSpace :-(
+    mutbox2 = obj._mapdict_read_storage(0)
+    assert mutbox2.intvalue == 7
+    assert mutbox2 is mutbox1
+
 def test_delete():
     for i, dattr in enumerate(["a", "b", "c"]):
         c = Class()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to