[pypy-svn] r77944 - in pypy/branch/jitffi/pypy/jit/metainterp: optimizeopt test

antocuni at codespeak.net antocuni at codespeak.net
Thu Oct 14 17:25:39 CEST 2010


Author: antocuni
Date: Thu Oct 14 17:25:37 2010
New Revision: 77944

Modified:
   pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py
   pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizefficall.py
   pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
disable the ffi call optimization if we find any operation between the various
prepare_call/push_arg/do_call (the code in rlib/libffi.py is written in such a
way that we should never get any operation in between)



Modified: pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py
==============================================================================
--- pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py	(original)
+++ pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py	Thu Oct 14 17:25:37 2010
@@ -12,10 +12,11 @@
     restype = None
     descr = None
 
-    def __init__(self, funcval, cpu):
+    def __init__(self, funcval, cpu, prepare_op):
         self.opargs = []
         argtypes, restype = self._get_signature(funcval)
         self.descr = cpu.calldescrof_dynamic(argtypes, restype)
+        self.prepare_op = prepare_op
 
     def _get_signature(self, funcval):
         """
@@ -64,7 +65,8 @@
 class OptFfiCall(Optimization):
 
     def __init__(self):
-        self.func_infos = {}
+        self.funcval = None
+        self.funcinfo = None
 
     def _get_oopspec(self, op):
         effectinfo = op.getdescr().get_extra_info()
@@ -72,6 +74,18 @@
             return effectinfo.oopspecindex
         return EffectInfo.OS_NONE
 
+    def rollback(self):
+        self.emit_operation(self.funcinfo.prepare_op)
+        for op in self.funcinfo.opargs:
+            self.emit_operation(op)
+        self.funcval = None
+        self.funcinfo = None
+
+    def optimize_default(self, op):
+        if self.funcval:
+            self.rollback()
+        self.emit_operation(op)
+
     def optimize_CALL(self, op):
         oopspec = self._get_oopspec(op)
         try:
@@ -92,31 +106,40 @@
 
     def _get_funcval(self, op):
         funcval = self.getvalue(op.getarg(1))
+        if self.funcval:
+            assert self.funcval is funcval # XXX do something nice
         if not funcval.is_constant():
             raise NonConstantFuncVal
         return funcval
 
     def do_prepare_call(self, op):
         funcval = self._get_funcval(op)
-        assert funcval not in self.func_infos # XXX: do something nice etc. etc.
-        self.func_infos[funcval] = FuncInfo(funcval, self.optimizer.cpu)
+        assert self.funcval is None # XXX: do something nice etc. etc.
+        self.funcval = funcval
+        self.funcinfo = FuncInfo(funcval, self.optimizer.cpu, op)
 
     def do_push_arg(self, op):
         # we store the op in funcs because we might want to emit it later,
         # in case we give up with the optimization
+        if self.funcval is None:
+            self.emit_operation(op)
+            return
         funcval = self._get_funcval(op)
-        self.func_infos[funcval].opargs.append(op)
+        self.funcinfo.opargs.append(op)
 
     def do_call(self, op):
+        if self.funcval is None:
+            return op
         funcval = self._get_funcval(op)
-        info = self.func_infos[funcval]
+        info = self.funcinfo
         funcsymval = self.getvalue(op.getarg(2))
         arglist = [funcsymval.force_box()]
         for push_op in info.opargs:
             argval = self.getvalue(push_op.getarg(2))
             arglist.append(argval.force_box())
         newop = ResOperation(rop.CALL_MAY_FORCE, arglist, op.result, descr=info.descr)
-        del self.func_infos[funcval]
+        self.funcval = None
+        self.funcinfo = None
         return newop
 
     def propagate_forward(self, op):
@@ -126,6 +149,6 @@
                 func(self, op)
                 break
         else:
-            self.emit_operation(op)
+            self.optimize_default(op)
 
 optimize_ops = _findall(OptFfiCall, 'optimize_')

Modified: pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizefficall.py
==============================================================================
--- pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizefficall.py	(original)
+++ pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizefficall.py	Thu Oct 14 17:25:37 2010
@@ -85,3 +85,17 @@
         expected = ops
         loop = self.optimize_loop(ops, 'Not, Not, Not', expected)
 
+    def test_rollback_if_op_in_between(self):
+        ops = """
+        [i0, f1]
+        call(0, ConstPtr(func),             descr=libffi_prepare)
+        call(0, ConstPtr(func), i0,         descr=libffi_push_arg)
+        i1 = int_add(i0, 1)
+        call(0, ConstPtr(func), f1,         descr=libffi_push_arg)
+        i3 = call_may_force(0, ConstPtr(func), 12345, descr=libffi_call)
+        guard_not_forced() []
+        guard_no_exception() []
+        jump(i3, f1)
+        """
+        expected = ops
+        loop = self.optimize_loop(ops, 'Not, Not', expected)

Modified: pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/jitffi/pypy/jit/metainterp/test/test_optimizeopt.py	Thu Oct 14 17:25:37 2010
@@ -139,6 +139,7 @@
     totwidth = py.io.get_terminal_width()
     width = totwidth / 2 - 1
     print ' Comparing lists '.center(totwidth, '-')
+    print '%s| %s' % ('optimized'.center(width), 'expected'.center(width))
     for op1, op2 in zip(oplist1, oplist2):
         txt1 = str(op1)
         txt2 = str(op2)



More information about the Pypy-commit mailing list