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