Author: Matti Picus <[email protected]>
Branch: cpyext-werror
Changeset: r84071:1846e020572e
Date: 2016-04-30 23:25 +0300
http://bitbucket.org/pypy/pypy/changeset/1846e020572e/

Log:    merge default into branch

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -24,7 +24,11 @@
 remove-objspace-options.
 
 .. branch: cpyext-for-merge
-Update cpyext C-API support:
+
+Update cpyext C-API support After this branch, we are almost able to support 
+upstream numpy via cpyext, so we created (yet another) fork of numpy at 
+github.com/pypy/numpy with the needed changes. Among the significant changes 
+to cpyext:
   - allow c-snippet tests to be run with -A so we can verify we are compatible
   - fix many edge cases exposed by fixing tests to run with -A
   - issequence() logic matches cpython
@@ -40,6 +44,8 @@
   - rewrite slot assignment for typeobjects
   - improve tracking of PyObject to rpython object mapping
   - support tp_as_{number, sequence, mapping, buffer} slots
-After this branch, we are almost able to support upstream numpy via cpyext, so
-we created (yet another) fork of numpy at github.com/pypy/numpy with the needed
-changes
+
+.. branch: share-mapdict-methods-2
+
+Reduce generated code for subclasses by using the same function objects in all
+generated subclasses.
diff --git a/pypy/module/cpyext/ndarrayobject.py 
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -253,12 +253,8 @@
              check_return, w_signature):
     funcs_w = [None] * ntypes
     dtypes_w = [None] * ntypes * (nin + nout)
-    # XXX For some reason funcs[i] segfaults, but this does not:
-    # cast(gufunctype, cast(CArrayPtr(CArrayPtr(gufunctype)), funcs)[i])
-    # Something is very wrong here.
-    funcs_wrong_type = rffi.cast(rffi.CArrayPtr(rffi.CArrayPtr(gufunctype)), 
funcs)
     for i in range(ntypes):
-        funcs_w[i] = ufuncs.W_GenericUFuncCaller(rffi.cast(gufunctype, 
funcs_wrong_type[i]), data)
+        funcs_w[i] = ufuncs.W_GenericUFuncCaller(funcs[i], data)
     for i in range(ntypes*(nin+nout)):
         dtypes_w[i] = get_dtype_cache(space).dtypes_by_num[ord(types[i])]
     w_funcs = space.newlist(funcs_w)
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py 
b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -366,7 +366,7 @@
     def test_ufunc(self):
         if self.runappdirect:
             from numpy import arange
-            py.test.xfail('why does this segfault on cpython?')
+            py.test.xfail('segfaults on cpython: PyUFunc_API == NULL?')
         else:
             from _numpypy.multiarray import arange
         mod = self.import_extension('foo', [
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py 
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -231,17 +231,7 @@
     assert max_n >= 0
     ITEM = A.OF
     ctypes_item = get_ctypes_type(ITEM, delayed_builders)
-    # Python 2.5 ctypes can raise OverflowError on 64-bit builds
-    for n in [maxint, 2**31]:
-        MAX_SIZE = n/64
-        try:
-            PtrType = ctypes.POINTER(MAX_SIZE * ctypes_item)
-        except (OverflowError, AttributeError), e:
-            pass      #        ^^^ bah, blame ctypes
-        else:
-            break
-    else:
-        raise e
+    ctypes_item_ptr = ctypes.POINTER(ctypes_item)
 
     class CArray(ctypes.Structure):
         if is_emulated_long:
@@ -265,35 +255,9 @@
                 bigarray.length = n
             return bigarray
 
-        _ptrtype = None
-
-        @classmethod
-        def _get_ptrtype(cls):
-            if cls._ptrtype:
-                return cls._ptrtype
-            # ctypes can raise OverflowError on 64-bit builds
-            # on windows it raises AttributeError even for 2**31 (_length_ 
missing)
-            if _MS_WINDOWS:
-                other_limit = 2**31-1
-            else:
-                other_limit = 2**31
-            for n in [maxint, other_limit]:
-                cls.MAX_SIZE = n / ctypes.sizeof(ctypes_item)
-                try:
-                    cls._ptrtype = ctypes.POINTER(cls.MAX_SIZE * ctypes_item)
-                except (OverflowError, AttributeError), e:
-                    pass
-                else:
-                    break
-            else:
-                raise e
-            return cls._ptrtype
-
         def _indexable(self, index):
-            PtrType = self._get_ptrtype()
-            assert index + 1 < self.MAX_SIZE
-            p = ctypes.cast(ctypes.pointer(self.items), PtrType)
-            return p.contents
+            p = ctypes.cast(self.items, ctypes_item_ptr)
+            return p
 
         def _getitem(self, index, boundscheck=True):
             if boundscheck:
@@ -1045,12 +1009,22 @@
                     container = _array_of_known_length(T.TO)
                     container._storage = type(cobj)(cobj.contents)
             elif isinstance(T.TO, lltype.FuncType):
+                # cobj is a CFunctionType object.  We naively think
+                # that it should be a function pointer.  No no no.  If
+                # it was read out of an array, say, then it is a *pointer*
+                # to a function pointer.  In other words, the read doesn't
+                # read anything, it just takes the address of the function
+                # pointer inside the array.  If later the array is modified
+                # or goes out of scope, then we crash.  CTypes is fun.
+                # It works if we cast it now to an int and back.
                 cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value)
                 if cobjkey in _int2obj:
                     container = _int2obj[cobjkey]
                 else:
+                    name = getattr(cobj, '__name__', '?')
+                    cobj = ctypes.cast(cobjkey, type(cobj))
                     _callable = get_ctypes_trampoline(T.TO, cobj)
-                    return lltype.functionptr(T.TO, getattr(cobj, '__name__', 
'?'),
+                    return lltype.functionptr(T.TO, name,
                                               _callable=_callable)
             elif isinstance(T.TO, lltype.OpaqueType):
                 if T == llmemory.GCREF:
diff --git a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py 
b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/test/test_ll2ctypes.py
@@ -1405,6 +1405,45 @@
         a2 = ctypes2lltype(lltype.Ptr(A), lltype2ctypes(a))
         assert a2._obj.getitem(0)._obj._parentstructure() is a2._obj
 
+    def test_array_of_function_pointers(self):
+        c_source = py.code.Source(r"""
+        #include "src/precommondefs.h"
+        #include <stdio.h>
+
+        typedef int(*funcptr_t)(void);
+        static int forty_two(void) { return 42; }
+        static int forty_three(void) { return 43; }
+        static funcptr_t testarray[2];
+        RPY_EXPORTED void runtest(void cb(funcptr_t *)) { 
+            testarray[0] = &forty_two;
+            testarray[1] = &forty_three;
+            fprintf(stderr, "&forty_two = %p\n", testarray[0]);
+            fprintf(stderr, "&forty_three = %p\n", testarray[1]);
+            cb(testarray);
+            testarray[0] = 0;
+            testarray[1] = 0;
+        }
+        """)
+        eci = ExternalCompilationInfo(include_dirs=[cdir],
+                                      separate_module_sources=[c_source])
+
+        PtrF = lltype.Ptr(lltype.FuncType([], rffi.INT))
+        ArrayPtrF = rffi.CArrayPtr(PtrF)
+        CALLBACK = rffi.CCallback([ArrayPtrF], lltype.Void)
+
+        runtest = rffi.llexternal('runtest', [CALLBACK], lltype.Void,
+                                  compilation_info=eci)
+        seen = []
+
+        def callback(testarray):
+            seen.append(testarray[0])   # read a PtrF out of testarray
+            seen.append(testarray[1])
+
+        runtest(callback)
+        assert seen[0]() == 42
+        assert seen[1]() == 43
+
+
 class TestPlatform(object):
     def test_lib_on_libpaths(self):
         from rpython.translator.platform import platform
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -544,6 +544,21 @@
         ll_compress = compression_function(r_set)
         return llops.gendirectcall(ll_compress, v)
 
+class __extend__(pairtype(FunctionReprBase, FunctionReprBase)):
+    def rtype_is_((robj1, robj2), hop):
+        if hop.s_result.is_constant():
+            return inputconst(Bool, hop.s_result.const)
+        s_pbc = annmodel.unionof(robj1.s_pbc, robj2.s_pbc)
+        r_pbc = hop.rtyper.getrepr(s_pbc)
+        v1, v2 = hop.inputargs(r_pbc, r_pbc)
+        assert v1.concretetype == v2.concretetype
+        if v1.concretetype == Char:
+            return hop.genop('char_eq', [v1, v2], resulttype=Bool)
+        elif isinstance(v1.concretetype, Ptr):
+            return hop.genop('ptr_eq', [v1, v2], resulttype=Bool)
+        else:
+            raise TyperError("unknown type %r" % (v1.concretetype,))
+
 
 def conversion_table(r_from, r_to):
     if r_to in r_from._conversion_tables:
diff --git a/rpython/rtyper/test/test_rpbc.py b/rpython/rtyper/test/test_rpbc.py
--- a/rpython/rtyper/test/test_rpbc.py
+++ b/rpython/rtyper/test/test_rpbc.py
@@ -1497,6 +1497,47 @@
         res = self.interpret(f, [2])
         assert res == False
 
+    def test_is_among_functions_2(self):
+        def g1(): pass
+        def g2(): pass
+        def f(n):
+            if n > 5:
+                g = g2
+            else:
+                g = g1
+            g()
+            return g is g2
+        res = self.interpret(f, [2])
+        assert res == False
+        res = self.interpret(f, [8])
+        assert res == True
+
+    def test_is_among_functions_3(self):
+        def g0(): pass
+        def g1(): pass
+        def g2(): pass
+        def g3(): pass
+        def g4(): pass
+        def g5(): pass
+        def g6(): pass
+        def g7(): pass
+        glist = [g0, g1, g2, g3, g4, g5, g6, g7]
+        def f(n):
+            if n > 5:
+                g = g2
+            else:
+                g = g1
+            h = glist[n]
+            g()
+            h()
+            return g is h
+        res = self.interpret(f, [2])
+        assert res == False
+        res = self.interpret(f, [1])
+        assert res == True
+        res = self.interpret(f, [6])
+        assert res == False
+
     def test_shrink_pbc_set(self):
         def g1():
             return 10
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to