Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: reflex-support Changeset: r54323:1ea1ba708588 Date: 2012-04-12 20:43 -0700 http://bitbucket.org/pypy/pypy/changeset/1ea1ba708588/
Log: const ref only worked b/c it didn't; 2nd attempt with explicit tests 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 @@ -150,26 +150,39 @@ def convert_argument_libffi(self, space, w_obj, argchain): argchain.arg(self._unwrap_object(space, w_obj)) + return lltype.nullptr(rffi.VOIDP.TO) def default_argument_libffi(self, space, argchain): argchain.arg(self.default) def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) - rffiptr = rffi.cast(self.rffiptype, address) + rffiptr = rffi.cast(self.c_ptrtype, address) return space.wrap(rffiptr[0]) def to_memory(self, space, w_obj, w_value, offset): address = self._get_raw_address(space, w_obj, offset) - rffiptr = rffi.cast(self.rffiptype, address) + rffiptr = rffi.cast(self.c_ptrtype, address) rffiptr[0] = self._unwrap_object(space, w_value) +class ConstRefNumericTypeConverterMixin(NumericTypeConverterMixin): + _mixin_ = True + _immutable_ = True + + def convert_argument_libffi(self, space, w_obj, argchain): + obj = self._unwrap_object(space, w_obj) + tbuf = lltype.malloc(self.c_ptrtype.TO, rffi.sizeof(self.c_type), flavor='raw') + tbuf[0] = obj + vbuf = rffi.cast(rffi.VOIDP, tbuf) + argchain.arg(vbuf) + return vbuf + class IntTypeConverterMixin(NumericTypeConverterMixin): _mixin_ = True _immutable_ = True def convert_argument(self, space, w_obj, address): - x = rffi.cast(self.rffiptype, address) + x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) class FloatTypeConverterMixin(NumericTypeConverterMixin): @@ -177,7 +190,7 @@ _immutable_ = True def convert_argument(self, space, w_obj, address): - x = rffi.cast(self.rffiptype, address) + x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) ba[capi.c_function_arg_typeoffset()] = self.typecode @@ -212,6 +225,7 @@ def convert_argument_libffi(self, space, w_obj, argchain): argchain.arg(self._unwrap_object(space, w_obj)) + return lltype.nullptr(rffi.VOIDP.TO) def from_memory(self, space, w_obj, w_pycppclass, offset): address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset)) @@ -254,6 +268,7 @@ def convert_argument_libffi(self, space, w_obj, argchain): argchain.arg(self._unwrap_object(space, w_obj)) + return lltype.nullptr(rffi.VOIDP.TO) def from_memory(self, space, w_obj, w_pycppclass, offset): address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset)) @@ -267,7 +282,8 @@ class ShortConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.sshort - rffiptype = rffi.SHORTP + c_type = rffi.SHORT + c_ptrtype = rffi.SHORTP def __init__(self, space, default): self.default = rffi.cast(rffi.SHORT, capi.c_strtoll(default)) @@ -275,73 +291,77 @@ def _unwrap_object(self, space, w_obj): return rffi.cast(rffi.SHORT, space.int_w(w_obj)) -class ConstShortRefConverter(ShortConverter): +class ConstShortRefConverter(ConstRefNumericTypeConverterMixin, ShortConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer class UnsignedShortConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.sshort - rffiptype = rffi.USHORTP + c_type = rffi.USHORT + c_ptrtype = rffi.USHORTP def __init__(self, space, default): - self.default = rffi.cast(rffi.USHORT, capi.c_strtoull(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoull(default)) def _unwrap_object(self, space, w_obj): - return rffi.cast(rffi.USHORT, space.int_w(w_obj)) + return rffi.cast(self.c_type, space.int_w(w_obj)) -class ConstUnsignedShortRefConverter(UnsignedShortConverter): +class ConstUnsignedShortRefConverter(ConstRefNumericTypeConverterMixin, UnsignedShortConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer class IntConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.sint - rffiptype = rffi.INTP + c_type = rffi.INT + c_ptrtype = rffi.INTP def __init__(self, space, default): - self.default = rffi.cast(rffi.INT, capi.c_strtoll(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoll(default)) def _unwrap_object(self, space, w_obj): - return rffi.cast(rffi.INT, space.c_int_w(w_obj)) + return rffi.cast(self.c_type, space.c_int_w(w_obj)) -class ConstIntRefConverter(IntConverter): +class ConstIntRefConverter(ConstRefNumericTypeConverterMixin, IntConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer class UnsignedIntConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.uint - rffiptype = rffi.UINTP + c_type = rffi.UINT + c_ptrtype = rffi.UINTP def __init__(self, space, default): - self.default = rffi.cast(rffi.UINT, capi.c_strtoull(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoull(default)) def _unwrap_object(self, space, w_obj): - return rffi.cast(rffi.UINT, space.uint_w(w_obj)) + return rffi.cast(self.c_type, space.uint_w(w_obj)) -class ConstUnsignedIntRefConverter(UnsignedIntConverter): +class ConstUnsignedIntRefConverter(ConstRefNumericTypeConverterMixin, UnsignedIntConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer class LongConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.slong - rffiptype = rffi.LONGP + c_type = rffi.LONG + c_ptrtype = rffi.LONGP def __init__(self, space, default): - self.default = rffi.cast(rffi.LONG, capi.c_strtoll(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoll(default)) def _unwrap_object(self, space, w_obj): return space.int_w(w_obj) -class ConstLongRefConverter(LongConverter): +class ConstLongRefConverter(ConstRefNumericTypeConverterMixin, LongConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer typecode = 'r' def convert_argument(self, space, w_obj, address): - x = rffi.cast(self.rffiptype, address) + x = rffi.cast(self.c_ptrtype, address) x[0] = self._unwrap_object(space, w_obj) ba = rffi.cast(rffi.CCHARP, address) ba[capi.c_function_arg_typeoffset()] = self.typecode @@ -349,23 +369,25 @@ class UnsignedLongConverter(IntTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.ulong - rffiptype = rffi.ULONGP + c_type = rffi.ULONG + c_ptrtype = rffi.ULONGP def __init__(self, space, default): - self.default = rffi.cast(rffi.ULONG, capi.c_strtoull(default)) + self.default = rffi.cast(self.c_type, capi.c_strtoull(default)) def _unwrap_object(self, space, w_obj): return space.uint_w(w_obj) -class ConstUnsignedLongRefConverter(UnsignedLongConverter): +class ConstUnsignedLongRefConverter(ConstRefNumericTypeConverterMixin, UnsignedLongConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer class FloatConverter(FloatTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.float - rffiptype = rffi.FLOATP - typecode = 'f' + c_type = rffi.FLOAT + c_ptrtype = rffi.FLOATP + typecode = 'f' def __init__(self, space, default): if default: @@ -379,32 +401,37 @@ def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) - rffiptr = rffi.cast(self.rffiptype, address) + rffiptr = rffi.cast(self.c_ptrtype, address) return space.wrap(float(rffiptr[0])) class ConstFloatRefConverter(FloatConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer typecode = 'F' + def convert_argument_libffi(self, space, w_obj, argchain): + from pypy.module.cppyy.interp_cppyy import FastCallNotPossible + raise FastCallNotPossible + class DoubleConverter(FloatTypeConverterMixin, TypeConverter): _immutable_ = True libffitype = libffi.types.double - rffiptype = rffi.DOUBLEP - typecode = 'd' + c_type = rffi.DOUBLE + c_ptrtype = rffi.DOUBLEP + typecode = 'd' def __init__(self, space, default): if default: - self.default = rffi.cast(rffi.DOUBLE, rfloat.rstring_to_float(default)) + self.default = rffi.cast(self.c_type, rfloat.rstring_to_float(default)) else: - self.default = rffi.cast(rffi.DOUBLE, 0.) + self.default = rffi.cast(self.c_type, 0.) def _unwrap_object(self, space, w_obj): return space.float_w(w_obj) -class ConstDoubleRefConverter(DoubleConverter): +class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter): _immutable_ = True - libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO) + libffitype = libffi.types.pointer typecode = 'D' @@ -438,6 +465,7 @@ def convert_argument_libffi(self, space, w_obj, argchain): argchain.arg(get_rawobject(space, w_obj)) + return lltype.nullptr(rffi.VOIDP.TO) class VoidPtrPtrConverter(TypeConverter): @@ -572,6 +600,7 @@ def convert_argument_libffi(self, space, w_obj, argchain): argchain.arg(self._unwrap_object(space, w_obj)) + return lltype.nullptr(rffi.VOIDP.TO) def from_memory(self, space, w_obj, w_pycppclass, offset): address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset)) @@ -689,7 +718,7 @@ _converters["char"] = CharConverter _converters["unsigned char"] = CharConverter _converters["short int"] = ShortConverter -_converters["const short int&"] = ConstIntRefConverter +_converters["const short int&"] = ConstShortRefConverter _converters["short"] = _converters["short int"] _converters["const short&"] = _converters["const short int&"] _converters["unsigned short int"] = UnsignedShortConverter 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 @@ -158,14 +158,21 @@ argchain = libffi.ArgChain() argchain.arg(cppthis) i = len(self.arg_defs) - for i in range(len(args_w)): - conv = self.arg_converters[i] - w_arg = args_w[i] - conv.convert_argument_libffi(self.space, w_arg, argchain) - for j in range(i+1, len(self.arg_defs)): - conv = self.arg_converters[j] - conv.default_argument_libffi(self.space, argchain) - return self.executor.execute_libffi(self.space, self._libffifunc, argchain) + refbuffers = [] + try: + for i in range(len(args_w)): + conv = self.arg_converters[i] + w_arg = args_w[i] + refbuf = conv.convert_argument_libffi(self.space, w_arg, argchain) + if refbuf: + refbuffers.append(refbuf) + for j in range(i+1, len(self.arg_defs)): + conv = self.arg_converters[j] + conv.default_argument_libffi(self.space, argchain) + return self.executor.execute_libffi(self.space, self._libffifunc, argchain) + finally: + for refbuf in refbuffers: + lltype.free(refbuf, flavor='raw') def _setup(self, cppthis): self.arg_converters = [converter.get_converter(self.space, arg_type, arg_dflt) diff --git a/pypy/module/cppyy/test/bench1.py b/pypy/module/cppyy/test/bench1.py --- a/pypy/module/cppyy/test/bench1.py +++ b/pypy/module/cppyy/test/bench1.py @@ -72,6 +72,14 @@ addDataToInt.call(instance, i) return i +class CppyyInterpBench3(CppyyInterpBench1): + def __call__(self): + addDataToInt = self.cls.get_overload("addDataToIntConstRef") + instance = self.inst + for i in range(NNN): + addDataToInt.call(instance, i) + return i + class CppyyPythonBench1(object): scale = 1 def __init__(self): @@ -121,6 +129,7 @@ print "warming up ... " interp_bench1 = CppyyInterpBench1() interp_bench2 = CppyyInterpBench2() + interp_bench3 = CppyyInterpBench3() python_bench1 = CppyyPythonBench1() interp_bench1(); interp_bench2(); python_bench1() @@ -130,6 +139,7 @@ # test runs ... print_bench("cppyy interp", run_bench(interp_bench1)) print_bench("... overload", run_bench(interp_bench2)) + print_bench("... constref", run_bench(interp_bench3)) print_bench("cppyy python", run_bench(python_bench1)) stat, t_cintex = commands.getstatusoutput("python bench1.py --pycintex") print_bench("pycintex ", float(t_cintex)) diff --git a/pypy/module/cppyy/test/example01.cxx b/pypy/module/cppyy/test/example01.cxx --- a/pypy/module/cppyy/test/example01.cxx +++ b/pypy/module/cppyy/test/example01.cxx @@ -91,6 +91,10 @@ return m_somedata + a; } +int example01::addDataToIntConstRef(const int& a) { + return m_somedata + a; +} + int example01::overloadedAddDataToInt(int a, int b) { return m_somedata + a + b; } diff --git a/pypy/module/cppyy/test/example01.h b/pypy/module/cppyy/test/example01.h --- a/pypy/module/cppyy/test/example01.h +++ b/pypy/module/cppyy/test/example01.h @@ -39,6 +39,7 @@ public: // instance methods int addDataToInt(int a); + int addDataToIntConstRef(const int& a); int overloadedAddDataToInt(int a, int b); int overloadedAddDataToInt(int a); int overloadedAddDataToInt(int a, int b, int c); 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 @@ -1,3 +1,4 @@ +import py, os, sys from pypy.jit.metainterp.test.support import LLJitMixin from pypy.rlib.objectmodel import specialize, instantiate from pypy.rlib import rarithmetic, jit @@ -6,6 +7,18 @@ from pypy.module.cppyy import interp_cppyy, capi + +currpath = py.path.local(__file__).dirpath() +test_dct = str(currpath.join("example01Dict.so")) + +def setup_module(mod): + if sys.platform == 'win32': + py.test.skip("win32 not supported so far") + err = os.system("cd '%s' && make example01Dict.so" % currpath) + if err: + raise OSError("'make' failed (see stderr)") + + class FakeBase(W_Root): typename = None @@ -150,24 +163,22 @@ return True class TestFastPathJIT(LLJitMixin): - def test_simple(self): - """Test fast path being taken for methods""" - + def _run_zjit(self, method_name): if capi.identify() == 'CINT': # CINT does not support fast path return space = FakeSpace() - drv = jit.JitDriver(greens=[], reds=["i", "inst", "addDataToInt"]) + drv = jit.JitDriver(greens=[], reds=["i", "inst", "cppmethod"]) def f(): lib = interp_cppyy.load_dictionary(space, "./example01Dict.so") cls = interp_cppyy.scope_byname(space, "example01") inst = cls.get_overload("example01").call(None, [FakeInt(0)]) - addDataToInt = cls.get_overload("addDataToInt") + cppmethod = cls.get_overload(method_name) assert isinstance(inst, interp_cppyy.W_CPPInstance) i = 10 while i > 0: - drv.jit_merge_point(inst=inst, addDataToInt=addDataToInt, i=i) - addDataToInt.call(inst, [FakeInt(i)]) + drv.jit_merge_point(inst=inst, cppmethod=cppmethod, i=i) + cppmethod.call(inst, [FakeInt(i)]) i -= 1 return 7 f() @@ -175,27 +186,17 @@ result = self.meta_interp(f, [], listops=True, backendopt=True, listcomp=True) self.check_jitcell_token_count(1) - def test_overload(self): + def test01_simple(self): + """Test fast path being taken for methods""" + + self._run_zjit("addDataToInt") + + def test02_overload(self): """Test fast path being taken for overloaded methods""" - if capi.identify() == 'CINT': # CINT does not support fast path - return + self._run_zjit("overloadedAddDataToInt") - space = FakeSpace() - drv = jit.JitDriver(greens=[], reds=["i", "inst", "addDataToInt"]) - def f(): - lib = interp_cppyy.load_dictionary(space, "./example01Dict.so") - cls = interp_cppyy.scope_byname(space, "example01") - inst = cls.get_overload("example01").call(None, [FakeInt(0)]) - addDataToInt = cls.get_overload("overloadedAddDataToInt") - assert isinstance(inst, interp_cppyy.W_CPPInstance) - i = 10 - while i > 0: - drv.jit_merge_point(inst=inst, addDataToInt=addDataToInt, i=i) - addDataToInt.call(inst, [FakeInt(i)]) - i -= 1 - return 7 - f() - space = FakeSpace() - result = self.meta_interp(f, [], listops=True, backendopt=True, listcomp=True) - self.check_jitcell_token_count(1) + def test03_const_ref(self): + """Test fast path being taken for methods with const ref arguments""" + + self._run_zjit("addDataToIntConstRef") _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit