[pypy-commit] pypy fast_cffi_list_init: add a fast-path also for floats. Also, remove the unnecessary copy in case of int lists, because now this is already guaranteed by unpackiterable_int

antocuni noreply at buildbot.pypy.org
Thu Oct 10 16:26:42 CEST 2013


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: fast_cffi_list_init
Changeset: r67294:474e7f3e7d2d
Date: 2013-10-10 16:25 +0200
http://bitbucket.org/pypy/pypy/changeset/474e7f3e7d2d/

Log:	add a fast-path also for floats. Also, remove the unnecessary copy
	in case of int lists, because now this is already guaranteed by
	unpackiterable_int

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,7 +283,10 @@
         return self.ctype.iter(self)
 
     def unpackiterable_int(self, space):
-        return self.ctype.unpackiterable_int(self)
+        return self.ctype.aslist_int(self)
+
+    def unpackiterable_float(self, space):
+        return self.ctype.aslist_float(self)
 
     @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,7 +105,7 @@
     def iter(self, cdata):
         return W_CDataIter(self.space, self.ctitem, cdata)
 
-    def unpackiterable_int(self, cdata):
+    def aslist_int(self, cdata):
         from rpython.rlib.rarray import populate_list_from_raw_array
         if self.ctitem.is_long():
             res = []
@@ -115,6 +115,16 @@
             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/test/test_extra.py b/pypy/module/_cffi_backend/test/test_extra.py
--- a/pypy/module/_cffi_backend/test/test_extra.py
+++ b/pypy/module/_cffi_backend/test/test_extra.py
@@ -71,3 +71,16 @@
         lst = list(buf)
         assert lst == [1, 2, 3]
         assert self.get_count() == 1
+
+    def test_list_float(self):
+        import _cffi_backend
+        DOUBLE = _cffi_backend.new_primitive_type('double')
+        P_DOUBLE = _cffi_backend.new_pointer_type(DOUBLE)
+        DOUBLE_ARRAY = _cffi_backend.new_array_type(P_DOUBLE, 3)
+        buf = _cffi_backend.newp(DOUBLE_ARRAY)
+        buf[0] = 1.1
+        buf[1] = 2.2
+        buf[2] = 3.3
+        lst = list(buf)
+        assert lst == [1.1, 2.2, 3.3]
+        assert self.get_count() == 1
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -949,13 +949,16 @@
             w_list.__init__(space, w_iterable.getitems_copy())
             return
 
-        intlist = space.listview_int(w_iterable)
-        if intlist is None:
-            intlist = space.unpackiterable_int(w_iterable)
+        intlist = space.unpackiterable_int(w_iterable)
         if intlist is not None:
             w_list.strategy = strategy = space.fromcache(IntegerListStrategy)
-            # need to copy because intlist can share with w_iterable
-            w_list.lstorage = strategy.erase(intlist[:])
+            w_list.lstorage = strategy.erase(intlist)
+            return
+
+        floatlist = space.unpackiterable_float(w_iterable)
+        if floatlist is not None:
+            w_list.strategy = strategy = space.fromcache(FloatListStrategy)
+            w_list.lstorage = strategy.erase(floatlist)
             return
 
         strlist = space.listview_str(w_iterable)


More information about the pypy-commit mailing list