diff options
author | Carl Friedrich Bolz-Tereick <cfbolz@gmx.de> | 2020-12-31 14:38:07 +0100 |
---|---|---|
committer | Carl Friedrich Bolz-Tereick <cfbolz@gmx.de> | 2020-12-31 14:38:07 +0100 |
commit | 02832616b916decc8e2347a14fe90f3b54c59a72 (patch) | |
tree | d53457c00f1fdf6236986294658539f39d71b4b5 /pypy | |
parent | implement type freezing for unboxed types: (diff) | |
download | pypy-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.py | 13 | ||||
-rw-r--r-- | pypy/objspace/std/test/test_mapdict.py | 35 |
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 |