aboutsummaryrefslogtreecommitdiff
path: root/pypy
diff options
context:
space:
mode:
authorCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2020-12-31 14:38:07 +0100
committerCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2020-12-31 14:38:07 +0100
commit02832616b916decc8e2347a14fe90f3b54c59a72 (patch)
treed53457c00f1fdf6236986294658539f39d71b4b5 /pypy
parentimplement type freezing for unboxed types: (diff)
downloadpypy-02832616b916decc8e2347a14fe90f3b54c59a72.tar.gz
pypy-02832616b916decc8e2347a14fe90f3b54c59a72.tar.bz2
pypy-02832616b916decc8e2347a14fe90f3b54c59a72.zip
implement immutability of UnwrappedPlainAttributes
Diffstat (limited to 'pypy')
-rw-r--r--pypy/objspace/std/mapdict.py13
-rw-r--r--pypy/objspace/std/test/test_mapdict.py35
2 files changed, 45 insertions, 3 deletions
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
index 74c153145c..9bde356768 100644
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -526,13 +526,20 @@ class UnboxedPlainAttribute(PlainAttribute):
return self._box(unerase_unboxed(obj._mapdict_read_storage(self.storageindex))[self.listindex])
def _pure_direct_read(self, obj):
- XXX # difficult!
- return self._direct_read(obj)
+ # somewhat tricky! note that _direct_read isn't really elidable (it has
+ # potential side effects, and the boxes aren't always the same)
+ # but _pure_unboxed_read is elidable, and we can let the jit see the
+ # boxing
+ return self._box(self._pure_unboxed_read(obj))
+
+ @jit.elidable
+ def _pure_unboxed_read(self, obj):
+ return unerase_unboxed(obj._mapdict_read_storage(self.storageindex))[self.listindex]
def _direct_write(self, obj, w_value):
if type(w_value) is self.typ:
val = self._unbox(w_value)
- unboxed = erase_unboxed(obj._mapdict_read_storage(self.storageindex))
+ unboxed = unerase_unboxed(obj._mapdict_read_storage(self.storageindex))
unboxed[self.listindex] = val
return
# type change not supposed to happen. according to the principle
diff --git a/pypy/objspace/std/test/test_mapdict.py b/pypy/objspace/std/test/test_mapdict.py
index 45ed1615c1..05bed07164 100644
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -641,6 +641,41 @@ def test_unboxed_type_change_other_object():
# now it's switched
assert type(w_obj2.map) is PlainAttribute
+def test_unboxed_attr_immutability(monkeypatch):
+ cls = Class(allow_unboxing=True)
+ obj = cls.instantiate()
+ obj.setdictvalue(space, "a", 10)
+ obj.setdictvalue(space, "b", 20)
+ obj.setdictvalue(space, "b", 30)
+ assert obj.map.ever_mutated == True
+ assert obj.map.back.ever_mutated == False
+
+ indices = []
+
+ def _pure_unboxed_read(obj):
+ indices.append(0)
+ return longlong2float(10)
+
+ obj.map.back._pure_unboxed_read = _pure_unboxed_read
+ monkeypatch.setattr(jit, "isconstant", lambda c: True)
+
+ assert obj.getdictvalue(space, "a") == 10
+ assert obj.getdictvalue(space, "b") == 30
+ assert obj.getdictvalue(space, "a") == 10
+ assert indices == [0, 0]
+
+ obj2 = cls.instantiate()
+ obj2.setdictvalue(space, "a", 15)
+ obj2.setdictvalue(space, "b", 25)
+ assert obj2.map is obj.map
+ assert obj2.map.ever_mutated == True
+ assert obj2.map.back.ever_mutated == False
+
+ # mutating obj2 changes the map
+ obj2.setdictvalue(space, "a", 50)
+ assert obj2.map.back.ever_mutated == True
+ assert obj2.map is obj.map
+
# ___________________________________________________________
# dict tests