[pypy-commit] pypy default: merge heads

arigo noreply at buildbot.pypy.org
Thu Oct 24 20:12:06 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r67581:643412f149d4
Date: 2013-10-24 20:11 +0200
http://bitbucket.org/pypy/pypy/changeset/643412f149d4/

Log:	merge heads

diff --git a/lib_pypy/numpypy/lib/utils.py b/lib_pypy/numpypy/lib/utils.py
--- a/lib_pypy/numpypy/lib/utils.py
+++ b/lib_pypy/numpypy/lib/utils.py
@@ -21,14 +21,4 @@
         ...
 
     """
-    try:
-        import numpy
-    except:
-        # running from pypy source directory
-        head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
-        return os.path.join(head, '../include')
-    else:
-        # using installed numpy core headers
-        import numpy.core as core
-        d = os.path.join(os.path.dirname(core.__file__), 'include')
-    return d
+    return os.path.join(os.path.dirname(__file__), '../../../include')
diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py
--- a/pypy/module/_cffi_backend/cdataobj.py
+++ b/pypy/module/_cffi_backend/cdataobj.py
@@ -283,10 +283,18 @@
         return self.ctype.iter(self)
 
     def unpackiterable_int(self, space):
-        return self.ctype.aslist_int(self)
+        from pypy.module._cffi_backend import ctypearray
+        ctype = self.ctype
+        if isinstance(ctype, ctypearray.W_CTypeArray):
+            return ctype.ctitem.unpack_list_of_int_items(self)
+        return None
 
     def unpackiterable_float(self, space):
-        return self.ctype.aslist_float(self)
+        from pypy.module._cffi_backend import ctypearray
+        ctype = self.ctype
+        if isinstance(ctype, ctypearray.W_CTypeArray):
+            return ctype.ctitem.unpack_list_of_float_items(self)
+        return None
 
     @specialize.argtype(1)
     def write_raw_signed_data(self, source):
diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py
--- a/pypy/module/_cffi_backend/ctypearray.py
+++ b/pypy/module/_cffi_backend/ctypearray.py
@@ -105,26 +105,6 @@
     def iter(self, cdata):
         return W_CDataIter(self.space, self.ctitem, cdata)
 
-    def aslist_int(self, cdata):
-        from rpython.rlib.rarray import populate_list_from_raw_array
-        if self.ctitem.is_long():
-            res = []
-            buf = rffi.cast(rffi.LONGP, cdata._cdata)
-            length = cdata.get_array_length()
-            populate_list_from_raw_array(res, buf, length)
-            return res
-        return None
-
-    def aslist_float(self, cdata):
-        from rpython.rlib.rarray import populate_list_from_raw_array
-        if self.ctitem.is_double():
-            res = []
-            buf = rffi.cast(rffi.DOUBLEP, cdata._cdata)
-            length = cdata.get_array_length()
-            populate_list_from_raw_array(res, buf, length)
-            return res
-        return None
-
     def get_vararg_type(self):
         return self.ctptr
 
diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -43,10 +43,13 @@
     def is_unichar_ptr_or_array(self):
         return False
 
-    def is_long(self):
-        return False
+    def unpack_list_of_int_items(self, cdata):
+        return None
 
-    def is_double(self):
+    def unpack_list_of_float_items(self, cdata):
+        return None
+
+    def pack_list_of_items(self, cdata, w_ob):
         return False
 
     def newp(self, w_init):
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -2,6 +2,7 @@
 Primitives.
 """
 
+import sys
 from pypy.interpreter.error import operationerrfmt
 
 from rpython.rlib.rarithmetic import r_uint, r_ulonglong, intmask
@@ -169,9 +170,9 @@
             sh = self.size * 8
             self.vmin = r_uint(-1) << (sh - 1)
             self.vrangemax = (r_uint(1) << sh) - 1
-
-    def is_long(self):
-        return self.size == rffi.sizeof(lltype.Signed)
+        else:
+            self.vmin = r_uint(0)
+            self.vrangemax = r_uint(-1)
 
     def cast_to_int(self, cdata):
         return self.convert_to_object(cdata)
@@ -204,6 +205,35 @@
     def write_raw_integer_data(self, w_cdata, value):
         w_cdata.write_raw_signed_data(value)
 
+    def unpack_list_of_int_items(self, w_cdata):
+        if self.size == rffi.sizeof(rffi.LONG):
+            from rpython.rlib.rarray import populate_list_from_raw_array
+            res = []
+            buf = rffi.cast(rffi.LONGP, w_cdata._cdata)
+            length = w_cdata.get_array_length()
+            populate_list_from_raw_array(res, buf, length)
+            return res
+        elif self.value_fits_long:
+            res = [0] * w_cdata.get_array_length()
+            misc.unpack_list_from_raw_array(res, w_cdata._cdata, self.size)
+            return res
+        return None
+
+    def pack_list_of_items(self, cdata, w_ob):
+        int_list = self.space.listview_int(w_ob)
+        if int_list is not None:
+            if self.size == rffi.sizeof(rffi.LONG): # fastest path
+                from rpython.rlib.rarray import copy_list_to_raw_array
+                cdata = rffi.cast(rffi.LONGP, cdata)
+                copy_list_to_raw_array(int_list, cdata)
+            else:
+                overflowed = misc.pack_list_to_raw_array_bounds(
+                    int_list, cdata, self.size, self.vmin, self.vrangemax)
+                if overflowed != 0:
+                    self._overflow(self.space.wrap(overflowed))
+            return True
+        return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+
 
 class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
     _attrs_            = ['value_fits_long', 'value_fits_ulong', 'vrangemax']
@@ -216,6 +246,8 @@
         self.value_fits_ulong = self.size <= rffi.sizeof(lltype.Unsigned)
         if self.value_fits_long:
             self.vrangemax = self._compute_vrange_max()
+        else:
+            self.vrangemax = r_uint(sys.maxint)
 
     def _compute_vrange_max(self):
         sh = self.size * 8
@@ -255,6 +287,24 @@
     def write_raw_integer_data(self, w_cdata, value):
         w_cdata.write_raw_unsigned_data(value)
 
+    def unpack_list_of_int_items(self, w_cdata):
+        if self.value_fits_long:
+            res = [0] * w_cdata.get_array_length()
+            misc.unpack_unsigned_list_from_raw_array(res, w_cdata._cdata,
+                                                     self.size)
+            return res
+        return None
+
+    def pack_list_of_items(self, cdata, w_ob):
+        int_list = self.space.listview_int(w_ob)
+        if int_list is not None:
+            overflowed = misc.pack_list_to_raw_array_bounds(
+                int_list, cdata, self.size, r_uint(0), self.vrangemax)
+            if overflowed != 0:
+                self._overflow(self.space.wrap(overflowed))
+            return True
+        return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+
 
 class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
     _attrs_ = []
@@ -276,9 +326,6 @@
 class W_CTypePrimitiveFloat(W_CTypePrimitive):
     _attrs_ = []
 
-    def is_double(self):
-        return self.size == rffi.sizeof(lltype.Float)
-
     def cast(self, w_ob):
         space = self.space
         if isinstance(w_ob, cdataobj.W_CData):
@@ -318,6 +365,34 @@
         value = space.float_w(space.float(w_ob))
         misc.write_raw_float_data(cdata, value, self.size)
 
+    def unpack_list_of_float_items(self, w_cdata):
+        if self.size == rffi.sizeof(rffi.DOUBLE):
+            from rpython.rlib.rarray import populate_list_from_raw_array
+            res = []
+            buf = rffi.cast(rffi.DOUBLEP, w_cdata._cdata)
+            length = w_cdata.get_array_length()
+            populate_list_from_raw_array(res, buf, length)
+            return res
+        elif self.size == rffi.sizeof(rffi.FLOAT):
+            res = [0.0] * w_cdata.get_array_length()
+            misc.unpack_cfloat_list_from_raw_array(res, w_cdata._cdata)
+            return res
+        return None
+
+    def pack_list_of_items(self, cdata, w_ob):
+        float_list = self.space.listview_float(w_ob)
+        if float_list is not None:
+            if self.size == rffi.sizeof(rffi.DOUBLE):   # fastest path
+                from rpython.rlib.rarray import copy_list_to_raw_array
+                cdata = rffi.cast(rffi.DOUBLEP, cdata)
+                copy_list_to_raw_array(float_list, cdata)
+                return True
+            elif self.size == rffi.sizeof(rffi.FLOAT):
+                misc.pack_float_list_to_raw_array(float_list, cdata,
+                                                  rffi.FLOAT, rffi.FLOATP)
+                return True
+        return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+
 
 class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat):
     _attrs_ = []
@@ -328,7 +403,6 @@
         return misc.longdouble2str(lvalue)
 
     def cast(self, w_ob):
-        space = self.space
         if (isinstance(w_ob, cdataobj.W_CData) and
                 isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)):
             w_cdata = self.convert_to_object(w_ob._cdata)
@@ -372,3 +446,15 @@
         else:
             value = space.float_w(space.float(w_ob))
             self._to_longdouble_and_write(value, cdata)
+
+    # Cannot have unpack_list_of_float_items() here:
+    # 'list(array-of-longdouble)' returns a list of cdata objects,
+    # not a list of floats.
+
+    def pack_list_of_items(self, cdata, w_ob):
+        float_list = self.space.listview_float(w_ob)
+        if float_list is not None:
+            misc.pack_float_list_to_raw_array(float_list, cdata,
+                                             rffi.LONGDOUBLE, rffi.LONGDOUBLEP)
+            return True
+        return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -42,12 +42,6 @@
     def is_char_or_unichar_ptr_or_array(self):
         return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveCharOrUniChar)
 
-    def aslist_int(self, cdata):
-        return None
-
-    def aslist_float(self, cdata):
-        return None
-
     def cast(self, w_ob):
         # cast to a pointer, to a funcptr, or to an array.
         # Note that casting to an array is an extension to the C language,
@@ -64,24 +58,10 @@
             value = rffi.cast(rffi.CCHARP, value)
         return cdataobj.W_CData(space, value, self)
 
-    def _convert_array_from_list_strategy_maybe(self, cdata, w_ob):
-        from rpython.rlib.rarray import copy_list_to_raw_array
-        int_list = self.space.listview_int(w_ob)
-        float_list = self.space.listview_float(w_ob)
+    def _convert_array_from_listview(self, cdata, w_ob):
+        if self.ctitem.pack_list_of_items(cdata, w_ob):   # fast path
+            return
         #
-        if self.ctitem.is_long() and int_list is not None:
-            cdata = rffi.cast(rffi.LONGP, cdata)
-            copy_list_to_raw_array(int_list, cdata)
-            return True
-        #
-        if self.ctitem.is_double() and float_list is not None:
-            cdata = rffi.cast(rffi.DOUBLEP, cdata)
-            copy_list_to_raw_array(float_list, cdata)
-            return True
-        #
-        return False
-
-    def _convert_array_from_listview(self, cdata, w_ob):
         space = self.space
         lst_w = space.listview(w_ob)
         if self.length >= 0 and len(lst_w) > self.length:
@@ -95,11 +75,6 @@
 
     def convert_array_from_object(self, cdata, w_ob):
         space = self.space
-        if self._convert_array_from_list_strategy_maybe(cdata, w_ob):
-            # the fast path worked, we are done now
-            return
-        #
-        # continue with the slow path
         if (space.isinstance_w(w_ob, space.w_list) or
             space.isinstance_w(w_ob, space.w_tuple)):
             self._convert_array_from_listview(cdata, w_ob)
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -315,3 +315,47 @@
             _raw_memclear_tp(TP, TPP, dest)
             return
     raise NotImplementedError("bad clear size")
+
+# ____________________________________________________________
+
+def pack_list_to_raw_array_bounds(int_list, target, size, vmin, vrangemax):
+    for TP, TPP in _prim_signed_types:
+        if size == rffi.sizeof(TP):
+            ptr = rffi.cast(TPP, target)
+            for i in range(len(int_list)):
+                x = int_list[i]
+                if r_uint(x) - vmin > vrangemax:
+                    return x      # overflow
+                ptr[i] = rffi.cast(TP, x)
+            return 0
+    raise NotImplementedError("bad integer size")
+
+ at specialize.arg(2)
+def pack_float_list_to_raw_array(float_list, target, TP, TPP):
+    target = rffi.cast(TPP, target)
+    for i in range(len(float_list)):
+        x = float_list[i]
+        target[i] = rffi.cast(TP, x)
+
+def unpack_list_from_raw_array(int_list, source, size):
+    for TP, TPP in _prim_signed_types:
+        if size == rffi.sizeof(TP):
+            ptr = rffi.cast(TPP, source)
+            for i in range(len(int_list)):
+                int_list[i] = rffi.cast(lltype.Signed, ptr[i])
+            return
+    raise NotImplementedError("bad integer size")
+
+def unpack_unsigned_list_from_raw_array(int_list, source, size):
+    for TP, TPP in _prim_unsigned_types:
+        if size == rffi.sizeof(TP):
+            ptr = rffi.cast(TPP, source)
+            for i in range(len(int_list)):
+                int_list[i] = rffi.cast(lltype.Signed, ptr[i])
+            return
+    raise NotImplementedError("bad integer size")
+
+def unpack_cfloat_list_from_raw_array(float_list, source):
+    ptr = rffi.cast(rffi.FLOATP, source)
+    for i in range(len(float_list)):
+        float_list[i] = rffi.cast(lltype.Float, ptr[i])
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -117,13 +117,17 @@
 
 SF_MSVC_BITFIELDS = 1
 SF_GCC_ARM_BITFIELDS = 2
+SF_GCC_BIG_ENDIAN = 4
 
 if sys.platform == 'win32':
     DEFAULT_SFLAGS = SF_MSVC_BITFIELDS
-elif rffi_platform.getdefined('__arm__', ''):
-    DEFAULT_SFLAGS = SF_GCC_ARM_BITFIELDS
 else:
-    DEFAULT_SFLAGS = 0
+    if rffi_platform.getdefined('__arm__', ''):
+        DEFAULT_SFLAGS = SF_GCC_ARM_BITFIELDS
+    else:
+        DEFAULT_SFLAGS = 0
+    if sys.byteorder == 'big':
+        DEFAULT_SFLAGS |= SF_GCC_BIG_ENDIAN
 
 @unwrap_spec(name=str)
 def new_struct_type(space, name):
@@ -325,6 +329,9 @@
                     prev_bitfield_free -= fbitsize
                     field_offset_bytes = boffset / 8 - ftype.size
 
+                if sflags & SF_GCC_BIG_ENDIAN:
+                    bitshift = 8 * ftype.size - fbitsize- bitshift
+
                 fld = ctypestruct.W_CField(ftype, field_offset_bytes,
                                            bitshift, fbitsize)
                 fields_list.append(fld)
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2949,8 +2949,6 @@
     _test_bitfield_details(flag=2)
 
 def test_bitfield_as_big_endian():
-    if '__pypy__' in sys.builtin_module_names:
-        py.test.skip("no big endian machine supported on pypy for now")
     _test_bitfield_details(flag=4)
 
 
diff --git a/pypy/module/_cffi_backend/test/test_fastpath.py b/pypy/module/_cffi_backend/test/test_fastpath.py
--- a/pypy/module/_cffi_backend/test/test_fastpath.py
+++ b/pypy/module/_cffi_backend/test/test_fastpath.py
@@ -1,18 +1,19 @@
-# side-effect: FORMAT_LONGDOUBLE must be built before test_checkmodule()
+# side-effect: FORMAT_LONGDOUBLE must be built before the first test
 from pypy.module._cffi_backend import misc
-from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
+from pypy.module._cffi_backend.ctypeobj import W_CType
+
 
 class AppTest_fast_path_from_list(object):
     spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
 
     def setup_method(self, meth):
-        def forbidden(self, *args):
+        def forbidden(*args):
             assert False, 'The slow path is forbidden'
-        self._original = W_CTypePtrOrArray._convert_array_from_listview.im_func
-        W_CTypePtrOrArray._convert_array_from_listview = forbidden
+        self._original = W_CType.pack_list_of_items.im_func
+        W_CType.pack_list_of_items = forbidden
 
     def teardown_method(self, meth):
-        W_CTypePtrOrArray._convert_array_from_listview = self._original
+        W_CType.pack_list_of_items = self._original
 
     def test_fast_init_from_list(self):
         import _cffi_backend
@@ -34,6 +35,101 @@
         assert buf[1] == 2.2
         assert buf[2] == 3.3
 
+    def test_fast_init_short_from_list(self):
+        import _cffi_backend
+        SHORT = _cffi_backend.new_primitive_type('short')
+        P_SHORT = _cffi_backend.new_pointer_type(SHORT)
+        SHORT_ARRAY = _cffi_backend.new_array_type(P_SHORT, None)
+        buf = _cffi_backend.newp(SHORT_ARRAY, [1, -2, 3])
+        assert buf[0] == 1
+        assert buf[1] == -2
+        assert buf[2] == 3
+        raises(OverflowError, _cffi_backend.newp, SHORT_ARRAY, [40000])
+        raises(OverflowError, _cffi_backend.newp, SHORT_ARRAY, [-40000])
+
+    def test_fast_init_longlong_from_list(self):
+        if type(2 ** 50) is long:
+            large_int = 2 ** 30
+        else:
+            large_int = 2 ** 50
+        import _cffi_backend
+        LONGLONG = _cffi_backend.new_primitive_type('long long')
+        P_LONGLONG = _cffi_backend.new_pointer_type(LONGLONG)
+        LONGLONG_ARRAY = _cffi_backend.new_array_type(P_LONGLONG, None)
+        buf = _cffi_backend.newp(LONGLONG_ARRAY, [1, -2, 3, large_int])
+        assert buf[0] == 1
+        assert buf[1] == -2
+        assert buf[2] == 3
+        assert buf[3] == large_int
+
+    def test_fast_init_ushort_from_list(self):
+        import _cffi_backend
+        USHORT = _cffi_backend.new_primitive_type('unsigned short')
+        P_USHORT = _cffi_backend.new_pointer_type(USHORT)
+        USHORT_ARRAY = _cffi_backend.new_array_type(P_USHORT, None)
+        buf = _cffi_backend.newp(USHORT_ARRAY, [1, 2, 40000])
+        assert buf[0] == 1
+        assert buf[1] == 2
+        assert buf[2] == 40000
+        raises(OverflowError, _cffi_backend.newp, USHORT_ARRAY, [70000])
+        raises(OverflowError, _cffi_backend.newp, USHORT_ARRAY, [-1])
+
+    def test_fast_init_ulong_from_list(self):
+        import sys
+        import _cffi_backend
+        ULONG = _cffi_backend.new_primitive_type('unsigned long')
+        P_ULONG = _cffi_backend.new_pointer_type(ULONG)
+        ULONG_ARRAY = _cffi_backend.new_array_type(P_ULONG, None)
+        buf = _cffi_backend.newp(ULONG_ARRAY, [1, 2, sys.maxint])
+        assert buf[0] == 1
+        assert buf[1] == 2
+        assert buf[2] == sys.maxint
+        raises(OverflowError, _cffi_backend.newp, ULONG_ARRAY, [-1])
+        raises(OverflowError, _cffi_backend.newp, ULONG_ARRAY, [-sys.maxint])
+
+    def test_fast_init_cfloat_from_list(self):
+        import _cffi_backend
+        FLOAT = _cffi_backend.new_primitive_type('float')
+        P_FLOAT = _cffi_backend.new_pointer_type(FLOAT)
+        FLOAT_ARRAY = _cffi_backend.new_array_type(P_FLOAT, None)
+        buf = _cffi_backend.newp(FLOAT_ARRAY, [1.25, -3.5])
+        assert buf[0] == 1.25
+        assert buf[1] == -3.5
+
+    def test_fast_init_clongdouble_from_list(self):
+        import _cffi_backend
+        LONGDOUBLE = _cffi_backend.new_primitive_type('long double')
+        P_LONGDOUBLE = _cffi_backend.new_pointer_type(LONGDOUBLE)
+        LONGDOUBLE_ARRAY = _cffi_backend.new_array_type(P_LONGDOUBLE, None)
+        buf = _cffi_backend.newp(LONGDOUBLE_ARRAY, [1.25, -3.5])
+        assert float(buf[0]) == 1.25
+        assert float(buf[1]) == -3.5
+
+    def test_fast_init_bool_from_list(self):
+        import _cffi_backend
+        BOOL = _cffi_backend.new_primitive_type('_Bool')
+        P_BOOL = _cffi_backend.new_pointer_type(BOOL)
+        BOOL_ARRAY = _cffi_backend.new_array_type(P_BOOL, None)
+        buf = _cffi_backend.newp(BOOL_ARRAY, [1, 0])
+        assert buf[0] == 1
+        assert buf[1] == 0
+        assert type(buf[1]) is int
+        raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [2])
+        raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [-1])
+
+
+class AppTest_fast_path_bug(object):
+    spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
+
+    def test_bug_not_list_or_tuple(self):
+        import _cffi_backend
+        LONG = _cffi_backend.new_primitive_type('long')
+        P_LONG = _cffi_backend.new_pointer_type(LONG)
+        LONG_ARRAY_2 = _cffi_backend.new_array_type(P_LONG, 2)
+        P_LONG_ARRAY_2 = _cffi_backend.new_pointer_type(LONG_ARRAY_2)
+        LONG_ARRAY_ARRAY = _cffi_backend.new_array_type(P_LONG_ARRAY_2, None)
+        raises(TypeError, _cffi_backend.newp, LONG_ARRAY_ARRAY, [set([4, 5])])
+
 
 class AppTest_fast_path_to_list(object):
     spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO'))
@@ -54,12 +150,38 @@
         self._original = original
         rarray.populate_list_from_raw_array = populate_list_from_raw_array
         #
+        original2 = misc.unpack_list_from_raw_array
+        def unpack_list_from_raw_array(*args):
+            self.count += 1
+            return original2(*args)
+        self._original2 = original2
+        misc.unpack_list_from_raw_array = unpack_list_from_raw_array
+        #
+        original3 = misc.unpack_cfloat_list_from_raw_array
+        def unpack_cfloat_list_from_raw_array(*args):
+            self.count += 1
+            return original3(*args)
+        self._original3 = original3
+        misc.unpack_cfloat_list_from_raw_array = (
+            unpack_cfloat_list_from_raw_array)
+        #
+        original4 = misc.unpack_unsigned_list_from_raw_array
+        def unpack_unsigned_list_from_raw_array(*args):
+            self.count += 1
+            return original4(*args)
+        self._original4 = original4
+        misc.unpack_unsigned_list_from_raw_array = (
+            unpack_unsigned_list_from_raw_array)
+        #
         self.w_runappdirect = self.space.wrap(self.runappdirect)
 
 
     def teardown_method(self, meth):
         from rpython.rlib import rarray
         rarray.populate_list_from_raw_array = self._original
+        misc.unpack_list_from_raw_array = self._original2
+        misc.unpack_cfloat_list_from_raw_array = self._original3
+        misc.unpack_unsigned_list_from_raw_array = self._original4
 
     def test_list_int(self):
         import _cffi_backend
@@ -84,6 +206,14 @@
         pbuf = _cffi_backend.cast(P_LONG, buf)
         raises(TypeError, "list(pbuf)")
 
+    def test_bug(self):
+        import _cffi_backend
+        LONG = _cffi_backend.new_primitive_type('long')
+        five = _cffi_backend.cast(LONG, 5)
+        raises(TypeError, list, five)
+        DOUBLE = _cffi_backend.new_primitive_type('double')
+        five_and_a_half = _cffi_backend.cast(DOUBLE, 5.5)
+        raises(TypeError, list, five_and_a_half)
 
     def test_list_float(self):
         import _cffi_backend
@@ -98,3 +228,45 @@
         assert lst == [1.1, 2.2, 3.3]
         if not self.runappdirect:
             assert self.get_count() == 1
+
+    def test_list_short(self):
+        import _cffi_backend
+        SHORT = _cffi_backend.new_primitive_type('short')
+        P_SHORT = _cffi_backend.new_pointer_type(SHORT)
+        SHORT_ARRAY = _cffi_backend.new_array_type(P_SHORT, 3)
+        buf = _cffi_backend.newp(SHORT_ARRAY)
+        buf[0] = 1
+        buf[1] = 2
+        buf[2] = 3
+        lst = list(buf)
+        assert lst == [1, 2, 3]
+        if not self.runappdirect:
+            assert self.get_count() == 1
+
+    def test_list_ushort(self):
+        import _cffi_backend
+        USHORT = _cffi_backend.new_primitive_type('unsigned short')
+        P_USHORT = _cffi_backend.new_pointer_type(USHORT)
+        USHORT_ARRAY = _cffi_backend.new_array_type(P_USHORT, 3)
+        buf = _cffi_backend.newp(USHORT_ARRAY)
+        buf[0] = 1
+        buf[1] = 2
+        buf[2] = 50505
+        lst = list(buf)
+        assert lst == [1, 2, 50505]
+        if not self.runappdirect:
+            assert self.get_count() == 1
+
+    def test_list_cfloat(self):
+        import _cffi_backend
+        FLOAT = _cffi_backend.new_primitive_type('float')
+        P_FLOAT = _cffi_backend.new_pointer_type(FLOAT)
+        FLOAT_ARRAY = _cffi_backend.new_array_type(P_FLOAT, 3)
+        buf = _cffi_backend.newp(FLOAT_ARRAY)
+        buf[0] = 1.25
+        buf[1] = -2.5
+        buf[2] = 3.75
+        lst = list(buf)
+        assert lst == [1.25, -2.5, 3.75]
+        if not self.runappdirect:
+            assert self.get_count() == 1
diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py
--- a/pypy/module/micronumpy/interp_dtype.py
+++ b/pypy/module/micronumpy/interp_dtype.py
@@ -84,6 +84,7 @@
 
     def build_and_convert(self, space, box):
         return self.itemtype.build_and_convert(space, self, box)
+
     def coerce(self, space, w_item):
         return self.itemtype.coerce(space, self, w_item)
 
diff --git a/pypy/module/rctime/test/test_rctime.py b/pypy/module/rctime/test/test_rctime.py
--- a/pypy/module/rctime/test/test_rctime.py
+++ b/pypy/module/rctime/test/test_rctime.py
@@ -140,7 +140,7 @@
         ltime = rctime.localtime()
         assert rctime.asctime(tuple(ltime)) == rctime.asctime(ltime)
         try:
-            assert rctime.asctime((12345,) + (0,) * 8).split()[-1] == '12345'
+            rctime.asctime((12345,) + (0,) * 8)  # assert this doesn't crash
         except ValueError:
             pass  # some OS (ie POSIXes besides Linux) reject year > 9999
 
diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py
--- a/rpython/jit/codewriter/call.py
+++ b/rpython/jit/codewriter/call.py
@@ -11,6 +11,7 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.translator.backendopt.canraise import RaiseAnalyzer
 from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer
+from rpython.translator.backendopt.graphanalyze import DependencyTracker
 
 
 class CallControl(object):
@@ -32,6 +33,9 @@
             self.virtualizable_analyzer = VirtualizableAnalyzer(translator)
             self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator)
             self.randomeffects_analyzer = RandomEffectsAnalyzer(translator)
+            self.seen = DependencyTracker(self.readwrite_analyzer)
+        else:
+            self.seen = None
         #
         for index, jd in enumerate(jitdrivers_sd):
             jd.index = index
@@ -231,8 +235,8 @@
                 extraeffect = EffectInfo.EF_CANNOT_RAISE
         #
         effectinfo = effectinfo_from_writeanalyze(
-            self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
-            oopspecindex, can_invalidate, call_release_gil_target,
+            self.readwrite_analyzer.analyze(op, self.seen), self.cpu,
+            extraeffect, oopspecindex, can_invalidate, call_release_gil_target,
         )
         #
         assert effectinfo is not None
diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -82,6 +82,7 @@
         # GETFIELD_GC, MARK_OPAQUE_PTR, PTR_EQ, and PTR_NE don't escape their
         # arguments
         elif (opnum != rop.GETFIELD_GC and
+              opnum != rop.GETFIELD_GC_PURE and
               opnum != rop.MARK_OPAQUE_PTR and
               opnum != rop.PTR_EQ and
               opnum != rop.PTR_NE and
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1398,7 +1398,7 @@
                     assembler_call_jd)
             if resbox is not None:
                 self.make_result_of_lastop(resbox)
-            self.metainterp.vable_after_residual_call()
+            self.metainterp.vable_after_residual_call(funcbox)
             self.metainterp.generate_guard(rop.GUARD_NOT_FORCED, None)
             if vablebox is not None:
                 self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None)
@@ -2437,7 +2437,7 @@
                 # it by ConstPtr(NULL).
                 self.stop_tracking_virtualref(i)
 
-    def vable_after_residual_call(self):
+    def vable_after_residual_call(self, funcbox):
         vinfo = self.jitdriver_sd.virtualizable_info
         if vinfo is not None:
             virtualizable_box = self.virtualizable_boxes[-1]
@@ -2445,6 +2445,14 @@
             if vinfo.tracing_after_residual_call(virtualizable):
                 # the virtualizable escaped during CALL_MAY_FORCE.
                 self.load_fields_from_virtualizable()
+                target_name = self.staticdata.get_name_from_address(funcbox.getaddr())
+                if target_name:
+                    target_name = "ConstClass(%s)" % target_name
+                else:
+                    target_name = str(funcbox.getaddr())
+                debug_print('vable escaped during a call in %s to %s' % (
+                    self.framestack[-1].jitcode.name, target_name
+                ))
                 raise SwitchToBlackhole(Counters.ABORT_ESCAPE,
                                         raising_exception=True)
                 # ^^^ we set 'raising_exception' to True because we must still
diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -3360,21 +3360,28 @@
         self.check_resops(call=0, getfield_gc=0)
 
     def test_isvirtual_call_assembler(self):
-        driver = JitDriver(greens = ['code'], reds = ['n'])
+        driver = JitDriver(greens = ['code'], reds = ['n', 's'])
 
         @look_inside_iff(lambda t1, t2: isvirtual(t1))
         def g(t1, t2):
             return t1[0] == t2[0]
 
+        def create(n):
+            return (1, 2, n)
+        create._dont_inline_ = True
+
         def f(code, n):
+            s = 0
             while n > 0:
-                driver.can_enter_jit(code=code, n=n)
-                driver.jit_merge_point(code=code, n=n)
-                t = (1, 2, n)
+                driver.can_enter_jit(code=code, n=n, s=s)
+                driver.jit_merge_point(code=code, n=n, s=s)
+                t = create(n)
                 if code:
                     f(0, 3)
+                s += t[2]
                 g(t, (1, 2, n))
                 n -= 1
+            return s
 
         self.meta_interp(f, [1, 10], inline=True)
         self.check_resops(call=0, call_may_force=0, call_assembler=2)
diff --git a/rpython/rlib/rstack.py b/rpython/rlib/rstack.py
--- a/rpython/rlib/rstack.py
+++ b/rpython/rlib/rstack.py
@@ -67,6 +67,7 @@
     # Else call the slow path
     stack_check_slowpath(current)
 stack_check._always_inline_ = True
+stack_check._dont_insert_stackcheck_ = True
 
 @rgc.no_collect
 def stack_check_slowpath(current):
@@ -74,3 +75,4 @@
         from rpython.rlib.rstackovf import _StackOverflow
         raise _StackOverflow
 stack_check_slowpath._dont_inline_ = True
+stack_check_slowpath._dont_insert_stackcheck_ = True
diff --git a/rpython/rtyper/test/test_rdict.py b/rpython/rtyper/test/test_rdict.py
--- a/rpython/rtyper/test/test_rdict.py
+++ b/rpython/rtyper/test/test_rdict.py
@@ -1078,6 +1078,13 @@
         res = self.interpret(func, [42])
         assert res == 42
 
+    def test_dict_with_empty_tuple_key(self):
+        def func(i):
+            d = {(): i}
+            return d[()]
+        res = self.interpret(func, [42])
+        assert res == 42
+
 
 class TestStress:
 
diff --git a/rpython/translator/transform.py b/rpython/translator/transform.py
--- a/rpython/translator/transform.py
+++ b/rpython/translator/transform.py
@@ -213,6 +213,10 @@
     insert_in = set()
     block2graph = {}
     for caller in translator.graphs:
+        pyobj = getattr(caller, 'func', None)
+        if pyobj is not None:
+            if getattr(pyobj, '_dont_insert_stackcheck_', False):
+                continue
         for block, callee in find_calls_from(translator, caller):
             if getattr(getattr(callee, 'func', None),
                        'insert_stack_check_here', False):
@@ -269,4 +273,4 @@
     transform_dead_op_vars(ann, block_subset)
     if ann.translator:
         checkgraphs(ann, block_subset)
- 
+


More information about the pypy-commit mailing list