Author: Alex Gaynor <alex.gay...@gmail.com> Branch: detect-immutable-fields Changeset: r68870:7244e2ea0430 Date: 2014-01-23 13:32 -0600 http://bitbucket.org/pypy/pypy/changeset/7244e2ea0430/
Log: Initial re-organization to allow detecting immutable fields in mapdicts 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 @@ -19,7 +19,7 @@ # we want to propagate knowledge that the result cannot be negative class AbstractAttribute(object): - _immutable_fields_ = ['terminator'] + _immutable_fields_ = ['terminator', 'ever_mutated?'] cache_attrs = None _size_estimate = 0 @@ -27,18 +27,21 @@ self.space = space assert isinstance(terminator, Terminator) self.terminator = terminator + self.ever_mutated = False def read(self, obj, selector): index = self.index(selector) - if index < 0: + if index is None: return self.terminator._read_terminator(obj, selector) - return obj._mapdict_read_storage(index) + return obj._mapdict_read_storage(index.position, pure=not self.ever_mutated) def write(self, obj, selector, w_value): index = self.index(selector) - if index < 0: + if index is None: return self.terminator._write_terminator(obj, selector, w_value) - obj._mapdict_write_storage(index, w_value) + obj._mapdict_write_storage(index.position, w_value) + if not index.ever_mutated: + index.ever_mutated = True return True def delete(self, obj, selector): @@ -97,9 +100,9 @@ def _index(self, selector): while isinstance(self, PlainAttribute): if selector == self.selector: - return self.position + return self self = self.back - return -1 + return None def copy(self, obj): raise NotImplementedError("abstract base class") @@ -330,7 +333,7 @@ self.attrs = [None] * SIZE self._empty_selector = (None, INVALID) self.selectors = [self._empty_selector] * SIZE - self.indices = [0] * SIZE + self.indices = [None] * SIZE if space.config.objspace.std.withmethodcachecounter: self.hits = {} self.misses = {} @@ -460,9 +463,10 @@ self.map = map self.storage = make_sure_not_resized([None] * map.size_estimate()) - def _mapdict_read_storage(self, index): + def _mapdict_read_storage(self, index, pure=False): assert index >= 0 return self.storage[index] + def _mapdict_write_storage(self, index, value): self.storage[index] = value def _mapdict_storage_length(self): @@ -519,7 +523,6 @@ rangenmin1 = unroll.unrolling_iterable(range(nmin1)) class subcls(BaseMapdictObject, supercls): def _init_empty(self, map): - from rpython.rlib.debug import make_sure_not_resized for i in rangen: setattr(self, "_value%s" % i, erase_item(None)) self.map = map @@ -531,7 +534,7 @@ erased = getattr(self, "_value%s" % nmin1) return unerase_list(erased) - def _mapdict_read_storage(self, index): + def _mapdict_read_storage(self, index, pure=False): assert index >= 0 if index < nmin1: for i in rangenmin1: @@ -879,11 +882,11 @@ # if selector[1] != INVALID: index = map.index(selector) - if index >= 0: + if index is not None: # Note that if map.terminator is a DevolvedDictTerminator, # map.index() will always return -1 if selector[1]==DICT. - _fill_cache(pycode, nameindex, map, version_tag, index) - return w_obj._mapdict_read_storage(index) + _fill_cache(pycode, nameindex, map, version_tag, index.position) + return w_obj._mapdict_read_storage(index.position) 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 @@ -64,7 +64,7 @@ current = Terminator(space, "cls") for i in range(20000): current = PlainAttribute((str(i), DICT), current) - assert current.index(("0", DICT)) == 0 + assert current.index(("0", DICT)).position == 0 def test_search(): @@ -231,7 +231,6 @@ obj = cls.instantiate() a = 0 b = 1 - c = 2 obj.setslotvalue(a, 50) obj.setslotvalue(b, 60) assert obj.getslotvalue(a) == 50 @@ -648,7 +647,7 @@ def test_delete_slot(self): class A(object): __slots__ = ['x'] - + a = A() a.x = 42 del a.x _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit