[pypy-svn] r62467 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Mar 3 13:57:14 CET 2009
Author: arigo
Date: Tue Mar 3 13:57:11 2009
New Revision: 62467
Modified:
pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py
Log:
Do the right thing for negative list indices,
and (correctly) skip optimizing at all list operations
that could raise IndexError.
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Mar 3 13:57:11 2009
@@ -1,5 +1,6 @@
from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem import lltype, llmemory, rstr
+from pypy.rpython import rlist
from pypy.objspace.flow.model import Variable, Constant, Link, c_last_exception
from pypy.rlib import objectmodel
from pypy.rlib.objectmodel import we_are_translated
@@ -737,20 +738,24 @@
#
if (oopspec_name == 'list.getitem' or
oopspec_name == 'list.getitem_foldable'): # <- XXX do better here
- # XXX check if index < 0, and check IndexError, both only if needed
+ index = self.prepare_list_getset(op, arraydescr, args)
+ if index is None:
+ return False
self.emit('getarrayitem_gc')
self.emit(self.var_position(args[0]))
self.emit(self.const_position(arraydescr))
- self.emit(self.var_position(args[1]))
+ self.emit(self.var_position(index))
self.register_var(op.result)
return True
#
if oopspec_name == 'list.setitem':
- # XXX check if index < 0, and check IndexError, both only if needed
+ index = self.prepare_list_getset(op, arraydescr, args)
+ if index is None:
+ return False
self.emit('setarrayitem_gc')
self.emit(self.var_position(args[0]))
self.emit(self.const_position(arraydescr))
- self.emit(self.var_position(args[1]))
+ self.emit(self.var_position(index))
self.emit(self.var_position(args[2]))
self.register_var(op.result)
return True
@@ -765,6 +770,27 @@
#
return False
+ def prepare_list_getset(self, op, arraydescr, args):
+ func = op.args[0].value._obj._callable # xxx break of abstraction
+ non_negative = '_nonneg' in func.__name__
+ tag = op.args[1].value
+ assert tag in (rlist.dum_nocheck, rlist.dum_checkidx)
+ can_raise = tag != rlist.dum_nocheck
+ #
+ if can_raise:
+ return None
+ if non_negative:
+ v_posindex = args[1]
+ else:
+ self.emit('check_neg_index')
+ self.emit(self.var_position(args[0]))
+ self.emit(self.const_position(arraydescr))
+ self.emit(self.var_position(args[1]))
+ v_posindex = Variable('posindex')
+ v_posindex.concretetype = lltype.Signed
+ self.register_var(v_posindex)
+ return v_posindex
+
def serialize_op_indirect_call(self, op):
self.minimize_variables()
targets = self.codewriter.policy.graphs_from(op)
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Mar 3 13:57:11 2009
@@ -334,7 +334,20 @@
@arguments("box", "constbox")
def opimpl_arraylen_gc(self, arraybox, arraydesc):
- self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int')
+ self.execute(rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True)
+
+ @arguments("orgpc", "box", "constbox", "box")
+ def opimpl_check_neg_index(self, pc, arraybox, arraydesc, indexbox):
+ negbox = self.metainterp.history.execute_and_record(
+ rop.INT_LT, [indexbox, ConstInt(0)], 'int', True)
+ negbox = self.implement_guard_value(pc, negbox)
+ if negbox.getint():
+ # the index is < 0; add the array length to it
+ lenbox = self.metainterp.history.execute_and_record(
+ rop.ARRAYLEN_GC, [arraybox, arraydesc], 'int', True)
+ indexbox = self.metainterp.history.execute_and_record(
+ rop.INT_ADD, [indexbox, lenbox], 'int', True)
+ self.make_result_box(indexbox)
@arguments("box")
def opimpl_ptr_nonzero(self, box):
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Tue Mar 3 13:57:11 2009
@@ -83,6 +83,20 @@
# two levels of list operations removed from the loop
self.check_loops(call_void=0, call__4=0)
+ def test_lazy_getitem_4(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'lst'])
+ def f(n):
+ lst = [0]
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, lst=lst)
+ myjitdriver.jit_merge_point(n=n, lst=lst)
+ lst[-1] += 2
+ n -= 1
+ return lst[0]
+ res = self.meta_interp(f, [21], listops=True)
+ assert res == 42
+ py.test.skip("not virtualized away so far")
+
class TestOOtype(ListTests, OOJitMixin):
pass
More information about the Pypy-commit
mailing list