[pypy-svn] r77483 - in pypy/branch/jitffi/pypy: jit/metainterp/optimizeopt rlib

antocuni at codespeak.net antocuni at codespeak.net
Thu Sep 30 10:58:09 CEST 2010


Author: antocuni
Date: Thu Sep 30 10:58:08 2010
New Revision: 77483

Modified:
   pypy/branch/jitffi/pypy/jit/metainterp/optimizeopt/fficall.py
   pypy/branch/jitffi/pypy/rlib/libffi.py
Log:
refactor until we manage to get a nice optimized graph from
test_direct_call.py, see the docstring of _get_signature for details.

The optimized graph still cannot be executed by the llgraph backend, because
it doesn't know how to CALL a real C function



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 Sep 30 10:58:08 2010
@@ -7,10 +7,49 @@
 
 class FuncInfo(object):
 
-    def __init__(self, cpu, func):
-        self.func = func
+    def __init__(self, funcval, cpu):
         self.opargs = []
-        self.descr = cpu.calldescrof_dynamic(func.argtypes, func.restype)
+        argtypes, restype = self._get_signature(funcval)
+        self.descr = cpu.calldescrof_dynamic(argtypes, restype)
+
+    def _get_signature(self, funcval):
+        """
+        given the funcval, return a tuple (argtypes, restype), where the
+        actuall types are libffi.ffi_type_*
+
+        The implementation is tricky because we have three possible cases:
+
+        - translated: the easiest case, we can just cast back the pointer to
+          the original Func instance and read .argtypes and .restype
+
+        - completely untranslated: this is what we get from test_optimizeopt
+          tests. funcval contains a FakeLLObject whose _fake_class is Func,
+          and we can just get .argtypes and .restype
+
+        - partially translated: this happens when running metainterp tests:
+          funcval contains the low-level equivalent of a Func, and thus we
+          have to fish inst_argtypes and inst_restype by hand.  Note that
+          inst_argtypes is actually a low-level array, but we can use it
+          directly since the only thing we do with it is to read its items
+        """
+        
+        llfunc = funcval.box.getref_base()
+        if we_are_translated():
+            XXX
+        elif getattr(llfunc, '_fake_class', None) is Func:
+            # untranslated
+            return llfunc.argtypes, llfunc.restype
+        else:
+            # partially translated
+            # llfunc contains an opaque pointer to something like the following:
+            # <GcStruct pypy.rlib.libffi.Func { super, inst_argtypes, inst_funcptr,
+            #                                   inst_funcsym, inst_restype }>
+            #
+            # Unfortunately, we cannot use the proper lltype.cast_opaque_ptr,
+            # because we don't have the exact TYPE to cast to.  Instead, we
+            # just fish it manually :-(
+            f = llfunc._obj.container
+            return f.inst_argtypes, f.inst_restype
 
 
 class OptFfiCall(Optimization):
@@ -43,43 +82,32 @@
             op = self.do_call(op)
         self.emit_operation(op)
 
-    def _cast_to_high_level(self, Class, obj):
-        if we_are_translated():
-            XXX
-        else:
-            # this is just for the tests in test_optimizeopt.py
-            cls = getattr(obj, '_fake_class', obj.__class__)
-            assert issubclass(cls, Class)
-            return obj
-
-    def _get_func(self, op):
+    def _get_funcval(self, op):
         funcval = self.getvalue(op.getarg(1))
         assert funcval.is_constant() # XXX: do something nice if it's not constant
-        llfunc = funcval.box.getref_base()
-        func = self._cast_to_high_level(Func, llfunc)
-        return func
+        return funcval
 
     def do_prepare_call(self, op):
-        func = self._get_func(op)
-        assert func not in self.func_infos # XXX: do something nice etc. etc.
-        self.func_infos[func] = FuncInfo(self.optimizer.cpu, func)
+        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)
 
     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
-        func = self._get_func(op)
-        self.func_infos[func].opargs.append(op)
+        funcval = self._get_funcval(op)
+        self.func_infos[funcval].opargs.append(op)
 
     def do_call(self, op):
-        func = self._get_func(op)
+        funcval = self._get_funcval(op)
+        info = self.func_infos[funcval]
         funcsymval = self.getvalue(op.getarg(2))
         arglist = [funcsymval.force_box()]
-        info = self.func_infos[func]
         for push_op in info.opargs:
             argval = self.getvalue(push_op.getarg(2))
             arglist.append(argval.force_box())
         newop = ResOperation(rop.CALL, arglist, op.result, descr=info.descr)
-        del self.func_infos[func]
+        del self.func_infos[funcval]
         return newop
 
     def propagate_forward(self, op):

Modified: pypy/branch/jitffi/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/jitffi/pypy/rlib/libffi.py	(original)
+++ pypy/branch/jitffi/pypy/rlib/libffi.py	Thu Sep 30 10:58:08 2010
@@ -52,7 +52,7 @@
 
     def _do_call(self, funcsym, RESULT):
         return self.funcptr.call(RESULT)
-    _do_call._annspecialcase_ = 'specialize:arg(1)'
+    _do_call._annspecialcase_ = 'specialize:arg(2)'
     _do_call.oopspec = 'libffi_call(self, funcsym, RESULT)'
 
     @jit.unroll_safe



More information about the Pypy-commit mailing list