[pypy-commit] pypy ffi-backend: test_fficall passes again.

arigo noreply at buildbot.pypy.org
Fri Aug 3 12:19:54 CEST 2012


Author: Armin Rigo <arigo at 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'
+
+ at 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):


More information about the pypy-commit mailing list