[pypy-commit] pypy reflex-support: const ref only worked b/c it didn't; 2nd attempt with explicit tests

wlav noreply at buildbot.pypy.org
Fri Apr 13 05:43:28 CEST 2012


Author: Wim Lavrijsen <WLavrijsen at 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")


More information about the pypy-commit mailing list