Author: Armin Rigo <ar...@tunes.org> Branch: ffi-backend Changeset: r56549:070760c85c9f Date: 2012-08-03 12:19 +0200 http://bitbucket.org/pypy/pypy/changeset/070760c85c9f/
Log: test_fficall passes again. diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py --- a/pypy/config/translationoption.py +++ b/pypy/config/translationoption.py @@ -122,8 +122,6 @@ ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], default="off"), - # jit_ffi is automatically turned on by withmod-_ffi (which is enabled by default) - BoolOption("jit_ffi", "optimize libffi calls", default=False, cmdline=None), BoolOption("check_str_without_nul", "Forbid NUL chars in strings in some external function calls", default=False, cmdline=None), diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py --- a/pypy/jit/backend/llgraph/llimpl.py +++ b/pypy/jit/backend/llgraph/llimpl.py @@ -802,7 +802,7 @@ if arraydescr.typeinfo == REF: raise NotImplementedError("getarrayitem_raw -> gcref") elif arraydescr.typeinfo == INT: - return do_getarrayitem_raw_int(array, index) + return do_getarrayitem_raw_int(array, index, arraydescr.ofs) elif arraydescr.typeinfo == FLOAT: return do_getarrayitem_raw_float(array, index) else: @@ -1448,9 +1448,13 @@ array = array._obj.container return cast_to_int(array.getitem(index)) -def do_getarrayitem_raw_int(array, index): - array = array.adr.ptr._obj - return cast_to_int(array.getitem(index)) +def do_getarrayitem_raw_int(array, index, itemsize): + array = array.adr.ptr + ITEMTYPE = lltype.typeOf(array).TO.OF + TYPE = symbolic.Size2Type[itemsize] + if TYPE.OF != ITEMTYPE: + array = rffi.cast(lltype.Ptr(TYPE), array) + return cast_to_int(array._obj.getitem(index)) def do_getarrayitem_gc_float(array, index): array = array._obj.container diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py --- a/pypy/jit/backend/llgraph/runner.py +++ b/pypy/jit/backend/llgraph/runner.py @@ -360,21 +360,21 @@ return self.getdescr(0, token[0], extrainfo=extrainfo, arg_types=''.join(arg_types)) - def calldescrof_dynamic(self, ffi_args, ffi_result, extrainfo, ffi_flags): + def calldescrof_dynamic(self, cif_description, extrainfo): from pypy.jit.backend.llsupport.ffisupport import get_ffi_type_kind from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind arg_types = [] try: - for arg in ffi_args: + for arg in cif_description.atypes: kind = get_ffi_type_kind(self, arg) if kind != history.VOID: arg_types.append(kind) - reskind = get_ffi_type_kind(self, ffi_result) + reskind = get_ffi_type_kind(self, cif_description.rtype) except UnsupportedKind: return None return self.getdescr(0, reskind, extrainfo=extrainfo, arg_types=''.join(arg_types), - ffi_flags=ffi_flags) + ffi_flags=cif_description.abi) def grab_exc_value(self): @@ -411,7 +411,7 @@ return llimpl.do_getarrayitem_gc_int(array, index) def bh_getarrayitem_raw_i(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) - return llimpl.do_getarrayitem_raw_int(array, index) + return llimpl.do_getarrayitem_raw_int(array, index, arraydescr.ofs) def bh_getarrayitem_gc_r(self, arraydescr, array, index): assert isinstance(arraydescr, Descr) return llimpl.do_getarrayitem_gc_ptr(array, index) diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py --- a/pypy/jit/backend/llsupport/ffisupport.py +++ b/pypy/jit/backend/llsupport/ffisupport.py @@ -1,5 +1,6 @@ from pypy.rlib.rarithmetic import intmask -from pypy.rpython.lltypesystem import rffi +from pypy.rlib.objectmodel import specialize +from pypy.rpython.lltypesystem import lltype, rffi from pypy.jit.backend.llsupport.descr import CallDescr class UnsupportedKind(Exception): @@ -38,3 +39,43 @@ from pypy.rlib.jit_libffi import types kind = types.getkind(ffi_type) return kind != 'u' + +@specialize.memo() +def _get_ffi2descr_dict(cpu): + d = {('v', 0): ('v', None)} + if cpu.supports_floats: + d[('f', 0)] = ('f', cpu.arraydescrof(rffi.CArray(lltype.Float))) + if cpu.supports_singlefloats: + d[('S', 0)] = cpu.arraydescrof(rffi.CArray(lltype.SingleFloat)) + for SIGNED_TYPE in [rffi.SIGNEDCHAR, + rffi.SHORT, + rffi.INT, + rffi.LONG, + rffi.LONGLONG]: + key = ('i', rffi.sizeof(SIGNED_TYPE)) + kind = 'i' + if key[1] > rffi.sizeof(lltype.Signed): + if not cpu.supports_longlong: + continue + key = ('L', 0) + kind = 'f' + d[key] = (kind, cpu.arraydescrof(rffi.CArray(SIGNED_TYPE))) + for UNSIGNED_TYPE in [rffi.UCHAR, + rffi.USHORT, + rffi.UINT, + rffi.ULONG, + rffi.ULONGLONG]: + key = ('u', rffi.sizeof(UNSIGNED_TYPE)) + if key[1] > rffi.sizeof(lltype.Signed): + continue + d[key] = ('i', cpu.arraydescrof(rffi.CArray(UNSIGNED_TYPE))) + return d + +def get_arg_descr(cpu, ffi_type): + from pypy.rlib.jit_libffi import types + kind = types.getkind(ffi_type) + if kind == 'i' or kind == 'u': + size = rffi.getintfield(ffi_type, 'c_size') + else: + size = 0 + return _get_ffi2descr_dict(cpu)[kind, size] diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py --- a/pypy/jit/metainterp/pyjitpl.py +++ b/pypy/jit/metainterp/pyjitpl.py @@ -1383,8 +1383,6 @@ if assembler_call: vablebox = self.metainterp.direct_assembler_call( assembler_call_jd) - elif effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL: - xxxx if resbox is not None: self.make_result_of_lastop(resbox) self.metainterp.vable_after_residual_call() @@ -1392,6 +1390,8 @@ if vablebox is not None: self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None) self.metainterp.handle_possible_exception() + if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL: + self.metainterp.direct_libffi_call() return resbox else: effect = effectinfo.extraeffect @@ -2535,6 +2535,85 @@ else: return None + def direct_libffi_call(self): + """Generate a direct call to C code, patching the CALL_MAY_FORCE + to jit_ffi_call() that occurred just now. + """ + from pypy.rpython.lltypesystem import llmemory + from pypy.rlib.jit_libffi import CIF_DESCRIPTION_P + from pypy.jit.backend.llsupport.ffisupport import get_arg_descr + # + num_extra_guards = 0 + while True: + op = self.history.operations[-1-num_extra_guards] + if op.getopnum() == rop.CALL_MAY_FORCE: + break + assert op.is_guard() + num_extra_guards += 1 + # + box_cif_description = op.getarg(1) + if not isinstance(box_cif_description, ConstInt): + return + cif_description = box_cif_description.getint() + cif_description = llmemory.cast_int_to_adr(cif_description) + cif_description = llmemory.cast_adr_to_ptr(cif_description, + CIF_DESCRIPTION_P) + calldescr = self.cpu.calldescrof_dynamic(cif_description, + op.getdescr().extrainfo) + if calldescr is None: + return + # + extra_guards = [] + for i in range(num_extra_guards): + extra_guards.append(self.history.operations.pop()) + extra_guards.reverse() + # + box_exchange_buffer = op.getarg(3) + self.history.operations.pop() + arg_boxes = [] + for i in range(cif_description.nargs): + kind, descr = get_arg_descr(self.cpu, cif_description.atypes[i]) + if kind == 'i': + box_arg = history.BoxInt() + elif kind == 'f': + box_arg = history.BoxFloat() + else: + assert kind == 'v' + continue + ofs = cif_description.exchange_args[i] + box_argpos = history.BoxInt() + self.history.record(rop.INT_ADD, + [box_exchange_buffer, ConstInt(ofs)], + box_argpos) + self.history.record(rop.GETARRAYITEM_RAW, + [box_argpos, ConstInt(0)], + box_arg, descr) + arg_boxes.append(box_arg) + # + kind, descr = get_arg_descr(self.cpu, cif_description.rtype) + if kind == 'i': + box_result = history.BoxInt() + elif kind == 'f': + box_result = history.BoxFloat() + else: + assert kind == 'v' + box_result = None + self.history.record(rop.CALL_RELEASE_GIL, + [op.getarg(2)] + arg_boxes, + box_result, calldescr) + # + self.history.operations.extend(extra_guards) + # + if box_result is not None: + ofs = cif_description.exchange_result + box_resultpos = history.BoxInt() + self.history.record(rop.INT_ADD, + [box_exchange_buffer, ConstInt(ofs)], + box_resultpos) + self.history.record(rop.SETARRAYITEM_RAW, + [box_resultpos, ConstInt(0), box_result], + None, descr) + # ____________________________________________________________ class ChangeFrame(JitException): diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py --- a/pypy/jit/metainterp/test/test_fficall.py +++ b/pypy/jit/metainterp/test/test_fficall.py @@ -19,7 +19,6 @@ @jit.oopspec("libffi_call(cif_description, func_addr, exchange_buffer)") def fake_call(cif_description, func_addr, exchange_buffer): - assert rffi.cast(lltype.Signed, func_addr) == 123 assert rffi.cast(rffi.SIGNEDP, exchange_buffer)[0] == 456 assert rffi.cast(rffi.SIGNEDP, exchange_buffer)[1] == 789 rffi.cast(rffi.SIGNEDP, exchange_buffer)[2] = -42 @@ -29,8 +28,19 @@ def test_call_simple(self): cif_description = get_description([types.signed]*2, types.signed) - func_addr = rffi.cast(rffi.VOIDP, 123) + + def verify(x, y): + assert x == 456 + assert y == 789 + return -42 + FUNC = lltype.FuncType([lltype.Signed]*2, lltype.Signed) + func = lltype.functionptr(FUNC, 'verify', _callable=verify) + func_addr = rffi.cast(rffi.VOIDP, func) + SIZE_SIGNED = rffi.sizeof(rffi.SIGNED) + cif_description.exchange_args[1] = SIZE_SIGNED + cif_description.exchange_result = 2 * SIZE_SIGNED + def f(n, m): exbuf = lltype.malloc(rffi.CCHARP.TO, 24, flavor='raw', zero=True) rffi.cast(rffi.SIGNEDP, exbuf)[0] = n @@ -46,6 +56,8 @@ assert res == -42 res = self.interp_operations(f, [456, 789]) assert res == -42 + self.check_operations_history(call_may_force=0, + call_release_gil=1) class TestFfiCall(FfiCallTests, LLJitMixin): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit