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