[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