Author: Armin Rigo <ar...@tunes.org>
Branch: cffi-static-callback
Changeset: r80684:08efac09ddaa
Date: 2015-11-15 14:23 +0100
http://bitbucket.org/pypy/pypy/changeset/08efac09ddaa/

Log:    Translation fixes and sharing more logic

diff --git a/pypy/module/_cffi_backend/call_python.py 
b/pypy/module/_cffi_backend/call_python.py
--- a/pypy/module/_cffi_backend/call_python.py
+++ b/pypy/module/_cffi_backend/call_python.py
@@ -19,22 +19,6 @@
                             lltype.Void)
 
 
-def get_printable_location(callpython):
-    with callpython as ptr:
-        callpy = rffi.cast(parse_c_type.PCALLPY, ptr)
-        return 'cffi_call_python ' + rffi.charp2str(callpy.g_name)
-
-jitdriver = jit.JitDriver(name='cffi_call_python',
-                          greens=['callpython'],
-                          reds=['ll_args'],
-                          get_printable_location=get_printable_location)
-
-def py_invoke_callpython(callpython, ll_args):
-    jitdriver.jit_merge_point(callpython=callpython, ll_args=ll_args)
-    # the same buffer is used both for passing arguments and the result value
-    callpython.do_invoke(ll_args, ll_args)
-
-
 def _cffi_call_python(ll_callpy, ll_args):
     """Invoked by the helpers generated from CFFI_CALL_PYTHON in the cdef.
 
@@ -73,23 +57,9 @@
             ll_args[i] = '\x00'
     else:
         callpython = reveal_callback(ll_callpy.c_reserved1)
-        space = callpython.space
-        must_leave = False
-        try:
-            must_leave = space.threadlocals.try_enter_thread(space)
-            py_invoke_callpython(callpython, ll_args)
-            #
-        except Exception, e:
-            # oups! last-level attempt to recover.
-            try:
-                os.write(STDERR, "SystemError: call_python function raised ")
-                os.write(STDERR, str(e))
-                os.write(STDERR, "\n")
-            except:
-                pass
-            callpython.write_error_return_value(ll_res)
-        if must_leave:
-            space.threadlocals.leave_thread(space)
+        # the same buffer is used both for passing arguments and
+        # the result value
+        callpython.invoke(ll_args, ll_args)
 
     cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
 
@@ -131,12 +101,12 @@
     # binding.  Note that the W_CallPython is never exposed to the user.
     callpy = rffi.cast(parse_c_type.PCALLPY, g.c_address)
     callpython = instantiate(W_CallPython, nonmovable=True)
-    callpython.__init__(space, rffi.cast(rffi.CCHARP, callpy), w_ct,
-                        w_python_callable, w_error, w_onerror)
+    W_CallPython.__init__(callpython, space, rffi.cast(rffi.CCHARP, callpy),
+                          w_ct, w_python_callable, w_error, w_onerror)
 
     key = rffi.cast(lltype.Signed, callpy)
     space.fromcache(KeepaliveCache).cache_dict[key] = callpython
-    callpy.c_reserved1 = rffi.cast(rffi.CCHARP, callpython.hide_object())
+    callpy.c_reserved1 = callpython.hide_object()
 
     # return a cdata of type function-pointer, equal to the one
     # obtained by reading 'lib.bar' (see lib_obj.py)
diff --git a/pypy/module/_cffi_backend/ccallback.py 
b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -8,7 +8,7 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 
 from pypy.interpreter.error import OperationError, oefmt
-from pypy.module._cffi_backend import cerrno, misc
+from pypy.module._cffi_backend import cerrno, misc, parse_c_type
 from pypy.module._cffi_backend.cdataobj import W_CData
 from pypy.module._cffi_backend.ctypefunc import SIZE_OF_FFI_ARG, W_CTypeFunc
 from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned
@@ -25,7 +25,8 @@
     # we can cast to a plain VOIDP.  As long as the object is not freed,
     # we can cast the VOIDP back to a W_CDataCallback in reveal_callback().
     cdata = objectmodel.instantiate(W_CDataCallback, nonmovable=True)
-    cdata.__init__(space, ctype, w_callable, w_error, w_onerror)
+    W_CDataCallback.__init__(cdata, space, ctype,
+                             w_callable, w_error, w_onerror)
     return cdata
 
 def reveal_callback(raw_ptr):
@@ -93,7 +94,8 @@
 
     def hide_object(self):
         gcref = rgc.cast_instance_to_gcref(self)
-        return rgc.hide_nonmovable_gcref(gcref)
+        raw = rgc.hide_nonmovable_gcref(gcref)
+        return rffi.cast(rffi.VOIDP, raw)
 
     def _repr_extra(self):
         space = self.space
@@ -104,6 +106,35 @@
         for i in range(len(error_string)):
             ll_res[i] = error_string[i]
 
+    def invoke(self, ll_res, ll_args):
+        space = self.space
+        must_leave = False
+        try:
+            must_leave = space.threadlocals.try_enter_thread(space)
+            self.py_invoke(ll_res, ll_args)
+            #
+        except Exception, e:
+            # oups! last-level attempt to recover.
+            try:
+                os.write(STDERR, "SystemError: callback raised ")
+                os.write(STDERR, str(e))
+                os.write(STDERR, "\n")
+            except:
+                pass
+            self.write_error_return_value(ll_res)
+        if must_leave:
+            space.threadlocals.leave_thread(space)
+
+    def py_invoke(self, ll_res, ll_args):
+        # For W_CallPython only; overridden in W_CDataCallback.  Note
+        # that the details of the two jitdrivers differ.  For
+        # W_CallPython, it depends on the identity of 'self', which
+        # means every @ffi.call_python() gets its own machine code,
+        # which sounds reasonable here.  Moreover, 'll_res' is ignored
+        # as it is always equal to 'll_args'.
+        jitdriver2.jit_merge_point(callpython=self, ll_args=ll_args)
+        self.do_invoke(ll_args, ll_args)
+
     def do_invoke(self, ll_res, ll_args):
         space = self.space
         extra_line = ''
@@ -124,9 +155,9 @@
         decode_args_from_libffi = self.decode_args_from_libffi
         for i, farg in enumerate(ctype.fargs):
             if decode_args_from_libffi:
-                ll_arg = rffi.cast(rffi.CCHARP, ll_args[i])
+                ll_arg = rffi.cast(rffi.CCHARPP, ll_args)[i]
             else:
-                ll_arg = rffi.ptradd(rffi.cast(rffi.CCHARP, ll_args), 8 * i)
+                ll_arg = rffi.ptradd(ll_args, 8 * i)
                 if farg.is_indirect_arg_for_call_python:
                     ll_arg = rffi.cast(rffi.CCHARPP, ll_arg)[0]
             args_w.append(farg.convert_to_object(ll_arg))
@@ -183,7 +214,7 @@
                         "return type or with '...'", self.getfunctype().name)
         with self as ptr:
             closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
-            unique_id = rffi.cast(rffi.VOIDP, self.hide_object())
+            unique_id = self.hide_object()
             res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
                                              invoke_callback,
                                              unique_id)
@@ -191,6 +222,12 @@
             raise OperationError(space.w_SystemError,
                 space.wrap("libffi failed to build this callback"))
 
+    def py_invoke(self, ll_res, ll_args):
+        jitdriver1.jit_merge_point(callback=self,
+                                   ll_res=ll_res,
+                                   ll_args=ll_args)
+        self.do_invoke(ll_res, ll_args)
+
 
 def convert_from_object_fficallback(fresult, ll_res, w_res,
                                     encode_result_for_libffi):
@@ -240,21 +277,30 @@
 STDERR = 2
 
 
-def get_printable_location(key_pycode):
+# jitdrivers, for both W_CDataCallback and W_CallPython
+
+def get_printable_location1(key_pycode):
     if key_pycode is None:
         return 'cffi_callback <?>'
     return 'cffi_callback ' + key_pycode.get_repr()
 
-jitdriver = jit.JitDriver(name='cffi_callback',
-                          greens=['callback.key_pycode'],
-                          reds=['ll_res', 'll_args', 'callback'],
-                          get_printable_location=get_printable_location)
+jitdriver1 = jit.JitDriver(name='cffi_callback',
+                           greens=['callback.key_pycode'],
+                           reds=['ll_res', 'll_args', 'callback'],
+                           get_printable_location=get_printable_location1)
 
-def py_invoke_callback(callback, ll_res, ll_args):
-    jitdriver.jit_merge_point(callback=callback, ll_res=ll_res, 
ll_args=ll_args)
-    callback.do_invoke(ll_res, ll_args)
+def get_printable_location2(callpython):
+    with callpython as ptr:
+        callpy = rffi.cast(parse_c_type.PCALLPY, ptr)
+        return 'cffi_call_python ' + rffi.charp2str(callpy.c_name)
 
-def _invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
+jitdriver2 = jit.JitDriver(name='cffi_call_python',
+                           greens=['callpython'],
+                           reds=['ll_args'],
+                           get_printable_location=get_printable_location2)
+
+
+def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
     """ Callback specification.
     ffi_cif - something ffi specific, don't care
     ll_args - rffi.VOIDPP - pointer to array of pointers to args
@@ -262,6 +308,7 @@
     ll_userdata - a special structure which holds necessary information
                   (what the real callback is for example), casted to VOIDP
     """
+    cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
     ll_res = rffi.cast(rffi.CCHARP, ll_res)
     callback = reveal_callback(ll_userdata)
     if callback is None:
@@ -274,27 +321,6 @@
         # In this case, we don't even know how big ll_res is.  Let's assume
         # it is just a 'ffi_arg', and store 0 there.
         misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG)
-        return
-    #
-    space = callback.space
-    must_leave = False
-    try:
-        must_leave = space.threadlocals.try_enter_thread(space)
-        py_invoke_callback(callback, ll_res, ll_args)
-        #
-    except Exception, e:
-        # oups! last-level attempt to recover.
-        try:
-            os.write(STDERR, "SystemError: callback raised ")
-            os.write(STDERR, str(e))
-            os.write(STDERR, "\n")
-        except:
-            pass
-        callback.write_error_return_value(ll_res)
-    if must_leave:
-        space.threadlocals.leave_thread(space)
-
-def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
-    cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
-    _invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata)
+    else:
+        callback.invoke(ll_res, rffi.cast(rffi.CCHARP, ll_args))
     cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
diff --git a/pypy/module/_cffi_backend/parse_c_type.py 
b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -74,8 +74,8 @@
 PCALLPY = rffi.CStructPtr('_cffi_callpy_s',
                           ('name', rffi.CCHARP),
                           ('size_of_result', rffi.SIZE_T),
-                          ('reserved1', rffi.CCHARP),
-                          ('reserved2', rffi.CCHARP))
+                          ('reserved1', rffi.VOIDP),
+                          ('reserved2', rffi.VOIDP))
 
 GETCONST_S = rffi.CStruct('_cffi_getconst_s',
                           ('value', rffi.ULONGLONG),
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to