Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r91568:6cbfa075de61 Date: 2017-06-07 18:47 +0200 http://bitbucket.org/pypy/pypy/changeset/6cbfa075de61/
Log: Don't preallocate RPython lists if we only know an upper bound on the final size. See comments. diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -410,6 +410,7 @@ self.listdef.resize() self.listdef.listitem.hint_maxlength = True elif 'fence' in hints: + self.listdef.resize() self = self.listdef.offspring(getbookkeeper()) return self diff --git a/rpython/translator/simplify.py b/rpython/translator/simplify.py --- a/rpython/translator/simplify.py +++ b/rpython/translator/simplify.py @@ -1005,6 +1005,16 @@ # - add a hint(vlist, iterable, {'maxlength'}) in the iterblock, # where we can compute the known maximum length + # - new in June 2017: we do that only if 'exactlength' is True. + # found some real use cases where the over-allocation scheme + # was over-allocating far too much: the loop would only append + # an item to the list after 'if some rare condition:'. By + # dropping this hint, we disable preallocation and cause the + # append() to be done by checking the size, but still, after + # the loop, we will turn the list into a fixed-size one. + # ('maxlength_inexact' is never processed elsewhere; the hint + # is still needed to prevent this function from being entered + # in an infinite loop) link = iterblock.exits[0] vlist = self.contains_vlist(link.args) assert vlist @@ -1014,7 +1024,8 @@ break else: raise AssertionError("lost 'iter' operation") - chint = Constant({'maxlength': True}) + chint = Constant({'maxlength' if exactlength else 'maxlength_inexact': + True}) hint = op.hint(vlist, hlop.args[0], chint) iterblock.operations.append(hint) link.args = list(link.args) diff --git a/rpython/translator/test/test_simplify.py b/rpython/translator/test/test_simplify.py --- a/rpython/translator/test/test_simplify.py +++ b/rpython/translator/test/test_simplify.py @@ -336,11 +336,14 @@ interp = LLInterpreter(t.rtyper) return interp, graph - def no_resize(self, graph): + def no_resize(self, graph, expect_resize=0): + found_resize = 0 for block in graph.iterblocks(): for op in block.operations: if op.opname == 'direct_call': - assert 'list_resize' not in repr(op.args[0]) + if 'list_resize' in repr(op.args[0]): + found_resize += 1 + assert found_resize == expect_resize def test_simple(self): def main(n): @@ -367,7 +370,8 @@ interp, graph = self.specialize(main, [int]) res = interp.eval_graph(graph, [10]) assert res == 5 - self.no_resize(graph) + self.no_resize(graph, expect_resize=1) + # the non-exactness disables preallocating now, for sanity def test_mutated_after_listcomp(self): def main(n): @@ -379,6 +383,7 @@ assert res == 5 * 17 res = interp.eval_graph(graph, [5]) assert res == -42 + self.no_resize(graph, expect_resize=1) # after the loop def test_two_loops(self): def main(n, m): @@ -397,6 +402,7 @@ interp, graph = self.specialize(main, [int, int]) res = interp.eval_graph(graph, [8, 3]) assert res == 28 - 3 + self.no_resize(graph) def test_dict(self): def main(n, m): @@ -408,6 +414,7 @@ assert res == 2 + 8 * 17 + 5 * 17 res = interp.eval_graph(graph, [4, 4]) assert res == 1 + 4 * 17 + 4 * 17 + self.no_resize(graph) def test_list_iterator(self): @@ -452,3 +459,4 @@ interp, graph = self.specialize(main, [int]) res = interp.eval_graph(graph, [10]) assert res == 5 * 17 + self.no_resize(graph) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit