[pypy-commit] pypy reflex-support: make use of the new jit_libffi instead of libffi module; it's still
wlav
noreply at buildbot.pypy.org
Sat Aug 18 00:38:50 CEST 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56744:3348ef4e320f
Date: 2012-08-17 15:38 -0700
http://bitbucket.org/pypy/pypy/changeset/3348ef4e320f/
Log: make use of the new jit_libffi instead of libffi module; it's still
about 3x slower for now, due to mallocs, and only used on the fast
path (i.e. Reflex backend)
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -65,10 +65,9 @@
def c_load_dictionary(name):
result = _c_load_dictionary(name)
- if not result:
- err = rdynload.dlerror()
- raise rdynload.DLOpenError(err)
- return libffi.CDLL(name) # should return handle to already open file
+ # ignore result: libffi.CDLL(name) either returns a handle to the already
+ # open file, or will fail as well and produce a correctly formatted error
+ return libffi.CDLL(name)
# CINT-specific pythonizations ===============================================
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -4,7 +4,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import libffi, clibffi, rfloat
+from pypy.rlib import jit_libffi, rfloat
from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
from pypy.module._rawffi.array import W_Array
@@ -68,7 +68,7 @@
class TypeConverter(object):
_immutable_ = True
- libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+ libffitype = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
uses_local = False
name = ""
@@ -91,11 +91,11 @@
def convert_argument(self, space, w_obj, address, call_local):
self._is_abstract(space)
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
- def default_argument_libffi(self, space, argchain):
+ def default_argument_libffi(self, space, address):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -129,6 +129,7 @@
class ArrayTypeConverterMixin(object):
_mixin_ = True
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
def __init__(self, space, array_size):
if array_size <= 0:
@@ -158,6 +159,7 @@
class PtrTypeConverterMixin(object):
_mixin_ = True
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
def __init__(self, space, array_size):
self.size = sys.maxint
@@ -167,9 +169,9 @@
if w_tc is not None and space.str_w(w_tc) != self.typecode:
msg = "expected %s pointer type, but received %s" % (self.typecode, space.str_w(w_tc))
raise OperationError(space.w_TypeError, space.wrap(msg))
- x = rffi.cast(rffi.LONGP, address)
+ x = rffi.cast(rffi.VOIDPP, address)
try:
- x[0] = rffi.cast(rffi.LONG, get_rawbuffer(space, w_obj))
+ x[0] = rffi.cast(rffi.VOIDP, get_rawbuffer(space, w_obj))
except TypeError:
raise OperationError(space.w_TypeError,
space.wrap("raw buffer interface not supported"))
@@ -200,11 +202,13 @@
_mixin_ = True
_immutable_ = True
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- argchain.arg(self._unwrap_object(space, w_obj))
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ x = rffi.cast(self.c_ptrtype, address)
+ x[0] = self._unwrap_object(space, w_obj)
- def default_argument_libffi(self, space, argchain):
- argchain.arg(self.default)
+ def default_argument_libffi(self, space, address):
+ x = rffi.cast(self.c_ptrtype, address)
+ x[0] = self.default
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = self._get_raw_address(space, w_obj, offset)
@@ -221,12 +225,13 @@
_immutable_ = True
uses_local = True
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
assert rffi.sizeof(self.c_type) <= 2*rffi.sizeof(rffi.VOIDP) # see interp_cppyy.py
obj = self._unwrap_object(space, w_obj)
typed_buf = rffi.cast(self.c_ptrtype, call_local)
typed_buf[0] = obj
- argchain.arg(call_local)
+ x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = call_local
class IntTypeConverterMixin(NumericTypeConverterMixin):
_mixin_ = True
@@ -249,7 +254,7 @@
class VoidConverter(TypeConverter):
_immutable_ = True
- libffitype = libffi.types.void
+ libffitype = jit_libffi.types.void
def __init__(self, space, name):
self.name = name
@@ -266,8 +271,9 @@
x = rffi.cast(rffi.LONGP, address)
x[0] = self._unwrap_object(space, w_obj)
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- argchain.arg(self._unwrap_object(space, w_obj))
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ x = rffi.cast(rffi.LONGP, address)
+ x[0] = self._unwrap_object(space, w_obj)
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
@@ -290,8 +296,9 @@
x = rffi.cast(rffi.CCHARP, address)
x[0] = self._unwrap_object(space, w_obj)
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- argchain.arg(self._unwrap_object(space, w_obj))
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ x = rffi.cast(self.c_ptrtype, address)
+ x[0] = self._unwrap_object(space, w_obj)
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
@@ -318,10 +325,10 @@
class ConstFloatRefConverter(FloatConverter):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
typecode = 'F'
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -336,7 +343,7 @@
class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
typecode = 'D'
@@ -361,18 +368,24 @@
class VoidPtrConverter(TypeConverter):
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
+
+ def _unwrap_object(self, space, w_obj):
+ try:
+ obj = get_rawbuffer(space, w_obj)
+ except TypeError:
+ obj = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
+ return obj
def convert_argument(self, space, w_obj, address, call_local):
x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = self._unwrap_object(space, w_obj)
ba = rffi.cast(rffi.CCHARP, address)
- try:
- x[0] = get_rawbuffer(space, w_obj)
- except TypeError:
- x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
ba[capi.c_function_arg_typeoffset()] = 'o'
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- argchain.arg(get_rawobject(space, w_obj))
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = self._unwrap_object(space, w_obj)
class VoidPtrPtrConverter(TypeConverter):
_immutable_ = True
@@ -402,6 +415,7 @@
class InstancePtrConverter(TypeConverter):
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
def __init__(self, space, cppclass):
from pypy.module.cppyy.interp_cppyy import W_CPPClass
@@ -428,8 +442,9 @@
ba = rffi.cast(rffi.CCHARP, address)
ba[capi.c_function_arg_typeoffset()] = 'o'
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- argchain.arg(self._unwrap_object(space, w_obj))
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
@@ -444,6 +459,10 @@
class InstanceConverter(InstancePtrConverter):
_immutable_ = True
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+ raise FastCallNotPossible # TODO: by-value is a jit_libffi special case
+
def from_memory(self, space, w_obj, w_pycppclass, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module.cppyy import interp_cppyy
@@ -466,6 +485,11 @@
ba = rffi.cast(rffi.CCHARP, address)
ba[capi.c_function_arg_typeoffset()] = 'o'
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ # TODO: finalize_call not yet called for fast call (see interp_cppyy.py)
+ from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+ raise FastCallNotPossible
+
def from_memory(self, space, w_obj, w_pycppclass, offset):
self._is_abstract(space)
@@ -523,6 +547,7 @@
class PyObjectConverter(TypeConverter):
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
def convert_argument(self, space, w_obj, address, call_local):
if hasattr(space, "fake"):
@@ -535,13 +560,19 @@
ba = rffi.cast(rffi.CCHARP, address)
ba[capi.c_function_arg_typeoffset()] = 'a'
- def convert_argument_libffi(self, space, w_obj, argchain, call_local):
- if hasattr(space, "fake"):
+ def convert_argument_libffi(self, space, w_obj, address, call_local):
+ # TODO: free_argument not yet called for fast call (see interp_cppyy.py)
+ from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+ raise FastCallNotPossible
+
+ # proposed implementation:
+ """if hasattr(space, "fake"):
raise NotImplementedError
space.getbuiltinmodule("cpyext")
from pypy.module.cpyext.pyobject import make_ref
ref = make_ref(space, w_obj)
- argchain.arg(rffi.cast(rffi.VOIDP, ref))
+ x = rffi.cast(rffi.VOIDPP, address)
+ x[0] = rffi.cast(rffi.VOIDP, ref)"""
def free_argument(self, space, arg, call_local):
if hasattr(space, "fake"):
@@ -649,7 +680,7 @@
self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
for name in names:
_converters[name] = BasicConverter
_converters["const "+name+"&"] = ConstRefConverter
@@ -666,7 +697,7 @@
self.default = rffi.cast(self.c_type, capi.c_strtoll(default))
class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
typecode = 'r'
def convert_argument(self, space, w_obj, address, call_local):
x = rffi.cast(self.c_ptrtype, address)
@@ -692,7 +723,7 @@
self.default = rffi.cast(self.c_type, capi.c_strtoull(default))
class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
for name in names:
_converters[name] = BasicConverter
_converters["const "+name+"&"] = ConstRefConverter
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -3,7 +3,7 @@
from pypy.interpreter.error import OperationError
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib import libffi, clibffi
+from pypy.rlib import jit_libffi
from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
from pypy.module._rawffi.array import W_Array, W_ArrayInstance
@@ -24,7 +24,7 @@
# exact match for the qualified type.
-NULL = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+NULL = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
class FunctionExecutor(object):
_immutable_ = True
@@ -37,13 +37,14 @@
raise OperationError(space.w_TypeError,
space.wrap('return type not available or supported'))
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
class PtrTypeExecutor(FunctionExecutor):
_immutable_ = True
+ libffitype = jit_libffi.types.pointer
typecode = 'P'
def execute(self, space, cppmethod, cppthis, num_args, args):
@@ -65,14 +66,14 @@
class VoidExecutor(FunctionExecutor):
_immutable_ = True
- libffitype = libffi.types.void
+ libffitype = jit_libffi.types.void
def execute(self, space, cppmethod, cppthis, num_args, args):
capi.c_call_v(cppmethod, cppthis, num_args, args)
return space.w_None
- def execute_libffi(self, space, libffifunc, argchain):
- libffifunc.call(argchain, lltype.Void)
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
return space.w_None
@@ -87,9 +88,11 @@
result = self.c_stubcall(cppmethod, cppthis, num_args, args)
return self._wrap_object(space, rffi.cast(self.c_type, result))
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, self.c_type)
- return self._wrap_object(space, result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ data = rffi.ptradd(buffer, cif_descr.exchange_args[1])
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+ result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ return self._wrap_object(space, rffi.cast(self.c_ptrtype, result)[0])
class NumericRefExecutorMixin(object):
_mixin_ = True
@@ -117,9 +120,11 @@
result = capi.c_call_r(cppmethod, cppthis, num_args, args)
return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, self.c_ptrtype)
- return self._wrap_reference(space, result)
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+ result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ return self._wrap_reference(space,
+ rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
class CStringExecutor(FunctionExecutor):
@@ -142,7 +147,7 @@
class InstancePtrExecutor(FunctionExecutor):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
def __init__(self, space, cppclass):
FunctionExecutor.__init__(self, space, cppclass)
@@ -155,9 +160,11 @@
return interp_cppyy.wrap_cppobject(
space, space.w_None, self.cppclass, ptr_result, isref=False, python_owns=False)
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+ result = rffi.ptradd(buffer, cif_descr.exchange_result)
from pypy.module.cppyy import interp_cppyy
- ptr_result = rffi.cast(capi.C_OBJECT, libffifunc.call(argchain, rffi.VOIDP))
+ ptr_result = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0])
return interp_cppyy.wrap_cppobject(
space, space.w_None, self.cppclass, ptr_result, isref=False, python_owns=False)
@@ -172,7 +179,7 @@
return interp_cppyy.wrap_cppobject(
space, space.w_None, self.cppclass, ptr_result, isref=False, python_owns=False)
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -186,7 +193,7 @@
return interp_cppyy.wrap_cppobject(
space, space.w_None, self.cppclass, ptr_result, isref=False, python_owns=True)
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -198,7 +205,7 @@
charp_result = capi.c_call_s(cppmethod, cppthis, num_args, args)
return space.wrap(capi.charp2str_free(charp_result))
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
raise FastCallNotPossible
@@ -221,11 +228,12 @@
lresult = capi.c_call_l(cppmethod, cppthis, num_args, args)
return self.wrap_result(space, lresult)
- def execute_libffi(self, space, libffifunc, argchain):
+ def execute_libffi(self, space, cif_descr, funcaddr, buffer):
if hasattr(space, "fake"):
raise NotImplementedError
- lresult = libffifunc.call(argchain, rffi.LONG)
- return self.wrap_result(space, lresult)
+ jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
+ result = rffi.ptradd(buffer, cif_descr.exchange_result)
+ return self.wrap_result(space, rffi.cast(rffi.LONGP, result)[0])
_executors = {}
@@ -322,7 +330,7 @@
c_stubcall = staticmethod(stub)
class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, FunctionExecutor):
_immutable_ = True
- libffitype = libffi.types.pointer
+ libffitype = jit_libffi.types.pointer
for name in names:
_executors[name] = BasicExecutor
_executors[name+'&'] = BasicRefExecutor
diff --git a/pypy/module/cppyy/ffitypes.py b/pypy/module/cppyy/ffitypes.py
--- a/pypy/module/cppyy/ffitypes.py
+++ b/pypy/module/cppyy/ffitypes.py
@@ -2,18 +2,18 @@
from pypy.rpython.lltypesystem import rffi
from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import libffi, rfloat
+from pypy.rlib import jit_libffi, rfloat
# Mixins to share between converter and executor classes (in converter.py and
# executor.py, respectively). Basically these mixins allow grouping of the
-# sets of libffi, rffi, and different space unwrapping calls. To get the right
-# mixin, a non-RPython function typeid() is used.
+# sets of jit_libffi, rffi, and different space unwrapping calls. To get the
+# right mixin, a non-RPython function typeid() is used.
class BoolTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.uchar
+ libffitype = jit_libffi.types.uchar
c_type = rffi.UCHAR
c_ptrtype = rffi.UCHARP
@@ -30,7 +30,7 @@
class CharTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.schar
+ libffitype = jit_libffi.types.schar
c_type = rffi.CHAR
c_ptrtype = rffi.CCHARP # there's no such thing as rffi.CHARP
@@ -54,7 +54,7 @@
class ShortTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.sshort
+ libffitype = jit_libffi.types.sshort
c_type = rffi.SHORT
c_ptrtype = rffi.SHORTP
@@ -64,7 +64,7 @@
class UShortTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.ushort
+ libffitype = jit_libffi.types.ushort
c_type = rffi.USHORT
c_ptrtype = rffi.USHORTP
@@ -74,7 +74,7 @@
class IntTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.sint
+ libffitype = jit_libffi.types.sint
c_type = rffi.INT
c_ptrtype = rffi.INTP
@@ -84,7 +84,7 @@
class UIntTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.uint
+ libffitype = jit_libffi.types.uint
c_type = rffi.UINT
c_ptrtype = rffi.UINTP
@@ -94,8 +94,8 @@
class LongTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.slong
- c_type = rffi.LONG
+ libffitype = jit_libffi.types.slong
+ c_type = rffi.LONG
c_ptrtype = rffi.LONGP
def _unwrap_object(self, space, w_obj):
@@ -104,9 +104,9 @@
class ULongTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.ulong
- c_type = rffi.ULONG
- c_ptrtype = rffi.ULONGP
+ libffitype = jit_libffi.types.ulong
+ c_type = rffi.ULONG
+ c_ptrtype = rffi.ULONGP
def _unwrap_object(self, space, w_obj):
return space.uint_w(w_obj)
@@ -114,7 +114,7 @@
class LongLongTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.sint64
+ libffitype = jit_libffi.types.sint64
c_type = rffi.LONGLONG
c_ptrtype = rffi.LONGLONGP
@@ -124,9 +124,9 @@
class ULongLongTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.uint64
- c_type = rffi.ULONGLONG
- c_ptrtype = rffi.ULONGLONGP
+ libffitype = jit_libffi.types.uint64
+ c_type = rffi.ULONGLONG
+ c_ptrtype = rffi.ULONGLONGP
def _unwrap_object(self, space, w_obj):
return space.r_ulonglong_w(w_obj)
@@ -134,7 +134,7 @@
class FloatTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.float
+ libffitype = jit_libffi.types.float
c_type = rffi.FLOAT
c_ptrtype = rffi.FLOATP
typecode = 'f'
@@ -148,7 +148,7 @@
class DoubleTypeMixin(object):
_mixin_ = True
_immutable_ = True
- libffitype = libffi.types.double
+ libffitype = jit_libffi.types.double
c_type = rffi.DOUBLE
c_ptrtype = rffi.DOUBLEP
typecode = 'd'
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -5,10 +5,11 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
from pypy.interpreter.baseobjspace import Wrappable, W_Root
-from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem import rffi, lltype, llmemory
-from pypy.rlib import libffi, rdynload, rweakref
-from pypy.rlib import jit, debug, objectmodel
+from pypy.rlib import jit, rdynload, rweakref
+from pypy.rlib import jit_libffi, clibffi
+from pypy.rlib.objectmodel import we_are_translated
from pypy.module.cppyy import converter, executor, helper
@@ -117,7 +118,7 @@
also takes care of offset casting and recycling of known objects through
the memory_regulator."""
_immutable_ = True
-
+
def __init__(self, space, containing_scope, method_index, arg_defs, args_required):
self.space = space
self.scope = containing_scope
@@ -131,7 +132,9 @@
# the method is actually used.
self.converters = None
self.executor = None
- self._libffifunc = None
+ self.cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
+ self._funcaddr = lltype.nullptr(rffi.VOIDP.TO)
+ self.uses_local = False
def _address_from_local_buffer(self, call_local, idx):
if not call_local:
@@ -154,18 +157,21 @@
# initial setup of converters, executors, and libffi (if available)
if self.converters is None:
- self._setup(cppthis)
-
+ try:
+ self._setup(cppthis)
+ except Exception, e:
+ pass
+
# some calls, e.g. for ptr-ptr or reference need a local array to store data for
# the duration of the call
- if [conv for conv in self.converters if conv.uses_local]:
+ if self.uses_local:
call_local = lltype.malloc(rffi.VOIDP.TO, 2*len(args_w), flavor='raw')
else:
call_local = lltype.nullptr(rffi.VOIDP.TO)
try:
# attempt to call directly through ffi chain
- if self._libffifunc:
+ if self._funcaddr:
try:
return self.do_fast_call(cppthis, args_w, call_local)
except FastCallNotPossible:
@@ -184,37 +190,126 @@
@jit.unroll_safe
def do_fast_call(self, cppthis, args_w, call_local):
jit.promote(self)
- argchain = libffi.ArgChain()
- argchain.arg(cppthis)
- i = len(self.arg_defs)
- for i in range(len(args_w)):
- conv = self.converters[i]
- w_arg = args_w[i]
- conv.convert_argument_libffi(self.space, w_arg, argchain, call_local)
- for j in range(i+1, len(self.arg_defs)):
- conv = self.converters[j]
- conv.default_argument_libffi(self.space, argchain)
- return self.executor.execute_libffi(self.space, self._libffifunc, argchain)
+ if self.cif_descr is None:
+ raise FastCallNotPossible
+ cif_descr = self.cif_descr
+ buffer = lltype.malloc(rffi.CCHARP.TO, cif_descr.exchange_size, flavor='raw')
+ try:
+ # this pointer
+ data = rffi.ptradd(buffer, cif_descr.exchange_args[0])
+ x = rffi.cast(rffi.LONGP, data) # LONGP needed for test_zjit.py
+ x[0] = rffi.cast(rffi.LONG, cppthis)
+
+ # other arguments and defaults
+ i = len(self.arg_defs) + 1
+ for i in range(len(args_w)):
+ conv = self.converters[i]
+ w_arg = args_w[i]
+ data = rffi.ptradd(buffer, cif_descr.exchange_args[i+1])
+ conv.convert_argument_libffi(self.space, w_arg, data, call_local)
+ for j in range(i+1, len(self.arg_defs)):
+ conv = self.converters[j]
+ data = rffi.ptradd(buffer, cif_descr.exchange_args[j+1])
+ conv.default_argument_libffi(self.space, data)
+
+ w_res = self.executor.execute_libffi(
+ self.space, cif_descr, self._funcaddr, buffer)
+ finally:
+ lltype.free(buffer, flavor='raw')
+ return w_res
def _setup(self, cppthis):
self.converters = [converter.get_converter(self.space, arg_type, arg_dflt)
for arg_type, arg_dflt in self.arg_defs]
self.executor = executor.get_executor(self.space, capi.c_method_result_type(self.scope, self.index))
+ for conv in self.converters:
+ if conv.uses_local:
+ self.uses_local = True
+ break
+
# Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
# has been offset to the matching class. Hence, the libffi pointer is
# uniquely defined and needs to be setup only once.
methgetter = capi.c_get_methptr_getter(self.scope, self.index)
if methgetter and cppthis: # methods only for now
- funcptr = methgetter(rffi.cast(capi.C_OBJECT, cppthis))
- argtypes_libffi = [conv.libffitype for conv in self.converters if conv.libffitype]
- if (len(argtypes_libffi) == len(self.converters) and
- self.executor.libffitype):
- # add c++ this to the arguments
- libffifunc = libffi.Func("XXX",
- [libffi.types.pointer] + argtypes_libffi,
- self.executor.libffitype, funcptr)
- self._libffifunc = libffifunc
+ cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
+ try:
+ funcaddr = methgetter(rffi.cast(capi.C_OBJECT, cppthis))
+ self._funcaddr = rffi.cast(rffi.VOIDP, funcaddr)
+
+ nargs = self.args_expected + 1 # +1: cppthis
+
+ # memory block for CIF description (note: not tracked as the life
+ # time of methods is normally the duration of the application)
+ size = llmemory.sizeof(jit_libffi.CIF_DESCRIPTION, nargs)
+
+ # allocate the buffer
+ cif_descr = lltype.malloc(jit_libffi.CIF_DESCRIPTION_P.TO,
+ llmemory.raw_malloc_usage(size),
+ flavor='raw', track_allocation=False)
+
+ # array of 'ffi_type*' values, one per argument
+ size = rffi.sizeof(jit_libffi.FFI_TYPE_P) * nargs
+ atypes = lltype.malloc(rffi.CCHARP.TO, llmemory.raw_malloc_usage(size),
+ flavor='raw', track_allocation=False)
+ cif_descr.atypes = rffi.cast(jit_libffi.FFI_TYPE_PP, atypes)
+
+ # argument type specification
+ cif_descr.atypes[0] = jit_libffi.types.pointer # cppthis
+ for i, conv in enumerate(self.converters):
+ if not conv.libffitype:
+ raise FastCallNotPossible
+ cif_descr.atypes[i+1] = conv.libffitype
+
+ # result type specification
+ cif_descr.rtype = self.executor.libffitype
+
+ # exchange ---
+
+ # first, enough room for an array of 'nargs' pointers
+ exchange_offset = rffi.sizeof(rffi.CCHARP) * nargs
+ exchange_offset = (exchange_offset + 7) & ~7 # alignment
+ cif_descr.exchange_result = exchange_offset
+ cif_descr.exchange_result_libffi = exchange_offset
+
+ # TODO: left this out while testing (see ctypefunc.py)
+ # For results of precisely these types, libffi has a
+ # strange rule that they will be returned as a whole
+ # 'ffi_arg' if they are smaller. The difference
+ # only matters on big-endian.
+
+ # then enough room for the result, rounded up to sizeof(ffi_arg)
+ exchange_offset += max(rffi.getintfield(cif_descr.rtype, 'c_size'),
+ jit_libffi.SIZE_OF_FFI_ARG)
+
+ # loop over args
+ for i in range(nargs):
+ exchange_offset = (exchange_offset + 7) & ~7 # alignment
+ cif_descr.exchange_args[i] = exchange_offset
+ exchange_offset += rffi.getintfield(cif_descr.atypes[i], 'c_size')
+
+ # store the exchange data size
+ cif_descr.exchange_size = exchange_offset
+
+ # --- exchange
+
+ # extra
+ cif_descr.abi = clibffi.FFI_DEFAULT_ABI
+ cif_descr.nargs = self.args_expected + 1 # +1: cppthis
+
+ res = jit_libffi.jit_ffi_prep_cif(cif_descr)
+ if res != clibffi.FFI_OK:
+ raise FastCallNotPossible
+
+ except Exception, e:
+ if cif_descr:
+ lltype.free(cif_descr.atypes, flavor='raw', track_allocation=False)
+ lltype.free(cif_descr, flavor='raw', track_allocation=False)
+ cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
+ self._funcaddr = lltype.nullptr(rffi.VOIDP.TO)
+
+ self.cif_descr = cif_descr
@jit.unroll_safe
def prepare_arguments(self, args_w, call_local):
@@ -253,6 +348,11 @@
def signature(self):
return capi.c_method_signature(self.scope, self.index)
+ def __del__(self):
+ if self.cif_descr:
+ lltype.free(self.cif_descr.atypes, flavor='raw')
+ lltype.free(self.cif_descr, flavor='raw')
+
def __repr__(self):
return "CPPMethod: %s" % self.signature()
@@ -317,6 +417,7 @@
def __init__(self, space, containing_scope, functions):
self.space = space
self.scope = containing_scope
+ from pypy.rlib import debug
self.functions = debug.make_sure_not_resized(functions)
def is_static(self):
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -14,6 +14,34 @@
# (note that the module is not otherwise used in the test itself)
import pypy.module.cpyext
+# change capi's direct_ptradd to being jit-opaque
+ at jit.dont_look_inside
+def _opaque_direct_ptradd(ptr, offset):
+ address = rffi.cast(rffi.CCHARP, ptr)
+ return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
+capi.direct_ptradd = _opaque_direct_ptradd
+
+# change the runner to use nargs in the loop, rather than rely on atypes
+# bounding, as atypes is actually of unknown size
+from pypy.jit.backend.llgraph import runner
+def _ranged_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 itp in range(cif_description.nargs):
+ arg = cif_description.atypes[itp]
+ kind = get_ffi_type_kind(self, arg)
+ if kind != runner.history.VOID:
+ arg_types.append(kind)
+ 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=cif_description.abi)
+runner.LLtypeCPU.calldescrof_dynamic = _ranged_calldescrof_dynamic
+
currpath = py.path.local(__file__).dirpath()
test_dct = str(currpath.join("example01Dict.so"))
@@ -58,12 +86,6 @@
FakeType.__init__(self, name)
self.message = name
- at jit.dont_look_inside
-def _opaque_direct_ptradd(ptr, offset):
- address = rffi.cast(rffi.CCHARP, ptr)
- return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
-capi.direct_ptradd = _opaque_direct_ptradd
-
class FakeUserDelAction(object):
def __init__(self, space):
pass
More information about the pypy-commit
mailing list