Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: Changeset: r65858:27316dbf2693 Date: 2013-07-31 12:18 +0200 http://bitbucket.org/pypy/pypy/changeset/27316dbf2693/
Log: merge foldable-getarrayitem-indexerror: constant-fold reads out of constant applevel tuples diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -54,3 +54,7 @@ speeds up list.append() and list.pop(). .. branch: curses_fixes + +.. branch: foldable-getarrayitem-indexerror +Constant-fold reading out of constant tuples in PyPy. + diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py --- a/pypy/module/pypyjit/test_pypy_c/test_containers.py +++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py @@ -209,6 +209,22 @@ opnames = log.opnames(loop.allops()) assert opnames.count('new_with_vtable') == 0 + def test_constfold_tuple(self): + code = """if 1: + tup = tuple(range(10000)) + l = [1, 2, 3, 4, 5, 6, "a"] + def main(n): + while n > 0: + sub = tup[1] # ID: getitem + l[1] = n # kill cache of tup[1] + n -= sub + """ + log = self.run(code, [1000]) + loop, = log.loops_by_filename(self.filepath) + ops = loop.ops_by_id('getitem', include_guard_not_invalidated=False) + assert log.opnames(ops) == [] + + def test_specialised_tuple(self): def main(n): import pypyjit diff --git a/rpython/jit/metainterp/test/test_immutable.py b/rpython/jit/metainterp/test/test_immutable.py --- a/rpython/jit/metainterp/test/test_immutable.py +++ b/rpython/jit/metainterp/test/test_immutable.py @@ -69,6 +69,28 @@ self.check_operations_history(getfield_gc=0, getfield_gc_pure=1, getarrayitem_gc=0, getarrayitem_gc_pure=1) + def test_array_index_error(self): + class X(object): + _immutable_fields_ = ["y[*]"] + + def __init__(self, x): + self.y = x + + def get(self, index): + try: + return self.y[index] + except IndexError: + return -41 + + def f(index): + l = [1, 2, 3, 4] + l[2] = 30 + a = escape(X(l)) + return a.get(index) + res = self.interp_operations(f, [2], listops=True) + assert res == 30 + self.check_operations_history(getfield_gc=0, getfield_gc_pure=1, + getarrayitem_gc=0, getarrayitem_gc_pure=1) def test_array_in_immutable(self): class X(object): diff --git a/rpython/rtyper/rlist.py b/rpython/rtyper/rlist.py --- a/rpython/rtyper/rlist.py +++ b/rpython/rtyper/rlist.py @@ -247,27 +247,22 @@ v_lst, v_index = hop.inputargs(r_lst, Signed) if checkidx: hop.exception_is_here() + spec = dum_checkidx else: + spec = dum_nocheck hop.exception_cannot_occur() - if hop.args_s[0].listdef.listitem.mutated or checkidx: - if hop.args_s[1].nonneg: - llfn = ll_getitem_nonneg - else: - llfn = ll_getitem - if checkidx: - spec = dum_checkidx - else: - spec = dum_nocheck - c_func_marker = hop.inputconst(Void, spec) - v_res = hop.gendirectcall(llfn, c_func_marker, v_lst, v_index) + if hop.args_s[0].listdef.listitem.mutated: + basegetitem = ll_getitem_fast else: - # this is the 'foldable' version, which is not used when - # we check for IndexError - if hop.args_s[1].nonneg: - llfn = ll_getitem_foldable_nonneg - else: - llfn = ll_getitem_foldable - v_res = hop.gendirectcall(llfn, v_lst, v_index) + basegetitem = ll_getitem_foldable_nonneg + + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg + else: + llfn = ll_getitem + c_func_marker = hop.inputconst(Void, spec) + c_basegetitem = hop.inputconst(Void, basegetitem) + v_res = hop.gendirectcall(llfn, c_func_marker, c_basegetitem, v_lst, v_index) return r_lst.recast(hop.llops, v_res) rtype_getitem_key = rtype_getitem @@ -654,16 +649,16 @@ i += 1 length_1_i -= 1 -def ll_getitem_nonneg(func, l, index): +def ll_getitem_nonneg(func, basegetitem, l, index): ll_assert(index >= 0, "unexpectedly negative list getitem index") if func is dum_checkidx: if index >= l.ll_length(): raise IndexError - return l.ll_getitem_fast(index) + return basegetitem(l, index) ll_getitem_nonneg._always_inline_ = True # no oopspec -- the function is inlined by the JIT -def ll_getitem(func, l, index): +def ll_getitem(func, basegetitem, l, index): if func is dum_checkidx: length = l.ll_length() # common case: 0 <= index < length if r_uint(index) >= r_uint(length): @@ -680,21 +675,18 @@ if index < 0: index += l.ll_length() ll_assert(index >= 0, "negative list getitem index out of bound") + return basegetitem(l, index) +# no oopspec -- the function is inlined by the JIT + +def ll_getitem_fast(l, index): return l.ll_getitem_fast(index) -# no oopspec -- the function is inlined by the JIT +ll_getitem_fast._always_inline_ = True def ll_getitem_foldable_nonneg(l, index): ll_assert(index >= 0, "unexpectedly negative list getitem index") return l.ll_getitem_fast(index) ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)' -def ll_getitem_foldable(l, index): - if index < 0: - index += l.ll_length() - return ll_getitem_foldable_nonneg(l, index) -ll_getitem_foldable._always_inline_ = True -# no oopspec -- the function is inlined by the JIT - def ll_setitem_nonneg(func, l, index, newitem): ll_assert(index >= 0, "unexpectedly negative list setitem index") if func is dum_checkidx: diff --git a/rpython/rtyper/test/test_rlist.py b/rpython/rtyper/test/test_rlist.py --- a/rpython/rtyper/test/test_rlist.py +++ b/rpython/rtyper/test/test_rlist.py @@ -14,15 +14,19 @@ from rpython.translator.translator import TranslationContext -# undo the specialization parameter +# undo the specialization parameters for n1 in 'get set del'.split(): + if n1 == "get": + extraarg = "ll_getitem_fast, " + else: + extraarg = "" for n2 in '', '_nonneg': name = 'll_%sitem%s' % (n1, n2) globals()['_' + name] = globals()[name] exec """if 1: def %s(*args): - return _%s(dum_checkidx, *args) -""" % (name, name) + return _%s(dum_checkidx, %s*args) +""" % (name, name, extraarg) del n1, n2, name @@ -1400,7 +1404,7 @@ block = graph.startblock op = block.operations[-1] assert op.opname == 'direct_call' - func = op.args[0].value._obj._callable + func = op.args[2].value assert ('foldable' in func.func_name) == \ ("y[*]" in immutable_fields) @@ -1511,8 +1515,8 @@ block = graph.startblock lst1_getitem_op = block.operations[-3] # XXX graph fishing lst2_getitem_op = block.operations[-2] - func1 = lst1_getitem_op.args[0].value._obj._callable - func2 = lst2_getitem_op.args[0].value._obj._callable + func1 = lst1_getitem_op.args[2].value + func2 = lst2_getitem_op.args[2].value assert func1.oopspec == 'list.getitem_foldable(l, index)' assert not hasattr(func2, 'oopspec') _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit