Author: Carl Friedrich Bolz <[email protected]>
Branch: typed-cells
Changeset: r75497:bb52cf0f8734
Date: 2015-01-23 00:47 +0100
http://bitbucket.org/pypy/pypy/changeset/bb52cf0f8734/
Log: keep a flag on PlainAttributes that indicates whether we need to
check for a MutableCell
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
@@ -41,8 +41,8 @@
result = self._pure_mapdict_read_storage(obj, attr.storageindex)
assert not isinstance(result, MutableCell)
else:
- result = unwrap_cell(
- attr.space, obj._mapdict_read_storage(attr.storageindex))
+ result = attr._read_cell(
+ obj._mapdict_read_storage(attr.storageindex))
return result
@jit.elidable
@@ -58,7 +58,7 @@
# introduce cells only on the second write, to make immutability for
# int fields still work
cell = obj._mapdict_read_storage(attr.storageindex)
- w_value = attr._write_cell(attr.space, cell, w_value)
+ w_value = attr._write_cell(cell, w_value)
if w_value is not None:
obj._mapdict_write_storage(attr.storageindex, w_value)
return True
@@ -283,7 +283,8 @@
return Terminator.set_terminator(self, obj, terminator)
class PlainAttribute(AbstractAttribute):
- _immutable_fields_ = ['selector', 'storageindex', 'back', 'ever_mutated?']
+ _immutable_fields_ = ['selector', 'storageindex', 'back',
+ 'ever_mutated?', 'can_contain_mutable_cell?']
def __init__(self, selector, back):
AbstractAttribute.__init__(self, back.space, back.terminator)
@@ -292,6 +293,16 @@
self.back = back
self._size_estimate = self.length() * NUM_DIGITS_POW2
self.ever_mutated = False
+ # this flag means: at some point there was an instance that used a
+ # derivative of this map that had a MutableCell stored into the
+ # corresponding field.
+ # if the flag is False, we don't need to unbox the attribute.
+ self.can_contain_mutable_cell = False
+
+ def _read_cell(self, w_cell):
+ if not self.can_contain_mutable_cell:
+ return w_cell
+ return unwrap_cell(self.space, w_cell)
def _write_cell(self, w_cell, w_value):
from pypy.objspace.std.intobject import W_IntObject
@@ -300,6 +311,8 @@
w_cell.intvalue = w_value.intval
return None
if type(w_value) is W_IntObject:
+ if not self.can_contain_mutable_cell:
+ self.can_contain_mutable_cell = True
return IntMutableCell(w_value.intval)
return w_value
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
@@ -169,11 +169,28 @@
assert mutcell1.intvalue == 6
obj.setdictvalue(space, "a", W_IntObject(7))
- assert obj.getdictvalue(space, "a") == 7 # because of the FakeSpace :-(
+ assert obj.getdictvalue(space, "a") == 7 # FakeSpace again
mutcell2 = obj._mapdict_read_storage(0)
assert mutcell2.intvalue == 7
assert mutcell2 is mutcell1
+
+def test_mutcell_unwrap_only_if_needed():
+ from pypy.objspace.std.intobject import W_IntObject
+ cls = Class()
+ obj = cls.instantiate()
+ obj.setdictvalue(space, "a", "foo")
+ assert not obj._get_mapdict_map().can_contain_mutable_cell
+ obj.setdictvalue(space, "a", W_IntObject(6))
+ obj.setdictvalue(space, "a", W_IntObject(6))
+ assert obj._get_mapdict_map().can_contain_mutable_cell
+
+ obj._get_mapdict_map().can_contain_mutable_cell = False
+ mutcell = IntMutableCell(1)
+ obj._mapdict_write_storage(0, mutcell)
+ assert obj.getdictvalue(space, "a") is mutcell # not unwrapped
+
+
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