[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